LCOV - code coverage report
Current view: top level - gio - gdbusinterfaceskeleton.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 86.8 % 296 257
Test Date: 2024-11-26 05:23:01 Functions: 92.3 % 39 36
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GDBus - GLib D-Bus Library
       2                 :             :  *
       3                 :             :  * Copyright (C) 2008-2010 Red Hat, Inc.
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :             :  *
       7                 :             :  * This library is free software; you can redistribute it and/or
       8                 :             :  * modify it under the terms of the GNU Lesser General Public
       9                 :             :  * License as published by the Free Software Foundation; either
      10                 :             :  * version 2.1 of the License, or (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This library is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             :  * Lesser General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU Lesser General
      18                 :             :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  *
      20                 :             :  * Author: David Zeuthen <davidz@redhat.com>
      21                 :             :  */
      22                 :             : 
      23                 :             : #include "config.h"
      24                 :             : 
      25                 :             : #include "gdbusinterface.h"
      26                 :             : #include "gdbusinterfaceskeleton.h"
      27                 :             : #include "gdbusobjectskeleton.h"
      28                 :             : #include "gioenumtypes.h"
      29                 :             : #include "gdbusprivate.h"
      30                 :             : #include "gdbusmethodinvocation.h"
      31                 :             : #include "gdbusconnection.h"
      32                 :             : #include "gmarshal-internal.h"
      33                 :             : #include "gtask.h"
      34                 :             : #include "gioerror.h"
      35                 :             : 
      36                 :             : #include "glibintl.h"
      37                 :             : 
      38                 :             : /**
      39                 :             :  * GDBusInterfaceSkeleton:
      40                 :             :  *
      41                 :             :  * Abstract base class for D-Bus interfaces on the service side.
      42                 :             :  *
      43                 :             :  * Since: 2.30
      44                 :             :  */
      45                 :             : 
      46                 :             : struct _GDBusInterfaceSkeletonPrivate
      47                 :             : {
      48                 :             :   GMutex                      lock;
      49                 :             : 
      50                 :             :   GDBusObject                *object;
      51                 :             :   GDBusInterfaceSkeletonFlags flags;
      52                 :             : 
      53                 :             :   GSList                     *connections;   /* List of ConnectionData */
      54                 :             :   gchar                      *object_path;   /* The object path for this skeleton */
      55                 :             :   GDBusInterfaceVTable       *hooked_vtable;
      56                 :             : };
      57                 :             : 
      58                 :             : typedef struct
      59                 :             : {
      60                 :             :   GDBusConnection *connection;
      61                 :             :   guint            registration_id;
      62                 :             : } ConnectionData;
      63                 :             : 
      64                 :             : enum
      65                 :             : {
      66                 :             :   G_AUTHORIZE_METHOD_SIGNAL,
      67                 :             :   LAST_SIGNAL
      68                 :             : };
      69                 :             : 
      70                 :             : enum
      71                 :             : {
      72                 :             :   PROP_0,
      73                 :             :   PROP_G_FLAGS
      74                 :             : };
      75                 :             : 
      76                 :             : static guint signals[LAST_SIGNAL] = {0};
      77                 :             : 
      78                 :             : static void     dbus_interface_interface_init                      (GDBusInterfaceIface    *iface);
      79                 :             : 
      80                 :             : static void     set_object_path_locked                             (GDBusInterfaceSkeleton *interface_,
      81                 :             :                                                                     const gchar            *object_path);
      82                 :             : static void     remove_connection_locked                           (GDBusInterfaceSkeleton *interface_,
      83                 :             :                                                                     GDBusConnection        *connection);
      84                 :             : static void     skeleton_intercept_handle_method_call              (GDBusConnection        *connection,
      85                 :             :                                                                     const gchar            *sender,
      86                 :             :                                                                     const gchar            *object_path,
      87                 :             :                                                                     const gchar            *interface_name,
      88                 :             :                                                                     const gchar            *method_name,
      89                 :             :                                                                     GVariant               *parameters,
      90                 :             :                                                                     GDBusMethodInvocation  *invocation,
      91                 :             :                                                                     gpointer                user_data);
      92                 :             : 
      93                 :             : 
      94                 :        4206 : G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GDBusInterfaceSkeleton, g_dbus_interface_skeleton, G_TYPE_OBJECT,
      95                 :             :                                   G_ADD_PRIVATE (GDBusInterfaceSkeleton)
      96                 :             :                                   G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_INTERFACE, dbus_interface_interface_init))
      97                 :             : 
      98                 :             : static void
      99                 :          41 : g_dbus_interface_skeleton_finalize (GObject *object)
     100                 :             : {
     101                 :          41 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (object);
     102                 :             : 
     103                 :             :   /* Hold the lock just in case any code we call verifies that the lock is held */
     104                 :          41 :   g_mutex_lock (&interface->priv->lock);
     105                 :             : 
     106                 :             :   /* unexport from all connections if we're exported anywhere */
     107                 :          43 :   while (interface->priv->connections != NULL)
     108                 :             :     {
     109                 :           2 :       ConnectionData *data = interface->priv->connections->data;
     110                 :           2 :       remove_connection_locked (interface, data->connection);
     111                 :             :     }
     112                 :             : 
     113                 :          41 :   set_object_path_locked (interface, NULL);
     114                 :             : 
     115                 :          41 :   g_mutex_unlock (&interface->priv->lock);
     116                 :             : 
     117                 :          41 :   g_free (interface->priv->hooked_vtable);
     118                 :             : 
     119                 :          41 :   if (interface->priv->object != NULL)
     120                 :           0 :     g_object_remove_weak_pointer (G_OBJECT (interface->priv->object), (gpointer *) &interface->priv->object);
     121                 :             : 
     122                 :          41 :   g_mutex_clear (&interface->priv->lock);
     123                 :             : 
     124                 :          41 :   G_OBJECT_CLASS (g_dbus_interface_skeleton_parent_class)->finalize (object);
     125                 :          41 : }
     126                 :             : 
     127                 :             : static void
     128                 :           0 : g_dbus_interface_skeleton_get_property (GObject      *object,
     129                 :             :                                         guint         prop_id,
     130                 :             :                                         GValue       *value,
     131                 :             :                                         GParamSpec   *pspec)
     132                 :             : {
     133                 :           0 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (object);
     134                 :             : 
     135                 :           0 :   switch (prop_id)
     136                 :             :     {
     137                 :           0 :     case PROP_G_FLAGS:
     138                 :           0 :       g_value_set_flags (value, g_dbus_interface_skeleton_get_flags (interface));
     139                 :           0 :       break;
     140                 :             : 
     141                 :           0 :     default:
     142                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     143                 :           0 :       break;
     144                 :             :     }
     145                 :           0 : }
     146                 :             : 
     147                 :             : static void
     148                 :           0 : g_dbus_interface_skeleton_set_property (GObject      *object,
     149                 :             :                                         guint         prop_id,
     150                 :             :                                         const GValue *value,
     151                 :             :                                         GParamSpec   *pspec)
     152                 :             : {
     153                 :           0 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (object);
     154                 :             : 
     155                 :           0 :   switch (prop_id)
     156                 :             :     {
     157                 :           0 :     case PROP_G_FLAGS:
     158                 :           0 :       g_dbus_interface_skeleton_set_flags (interface, g_value_get_flags (value));
     159                 :           0 :       break;
     160                 :             : 
     161                 :           0 :     default:
     162                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     163                 :           0 :       break;
     164                 :             :     }
     165                 :           0 : }
     166                 :             : 
     167                 :             : static gboolean
     168                 :           6 : g_dbus_interface_skeleton_g_authorize_method_default (GDBusInterfaceSkeleton    *interface,
     169                 :             :                                                       GDBusMethodInvocation *invocation)
     170                 :             : {
     171                 :           6 :   return TRUE;
     172                 :             : }
     173                 :             : 
     174                 :             : static void
     175                 :           7 : g_dbus_interface_skeleton_class_init (GDBusInterfaceSkeletonClass *klass)
     176                 :             : {
     177                 :             :   GObjectClass *gobject_class;
     178                 :             : 
     179                 :           7 :   gobject_class = G_OBJECT_CLASS (klass);
     180                 :           7 :   gobject_class->finalize     = g_dbus_interface_skeleton_finalize;
     181                 :           7 :   gobject_class->set_property = g_dbus_interface_skeleton_set_property;
     182                 :           7 :   gobject_class->get_property = g_dbus_interface_skeleton_get_property;
     183                 :             : 
     184                 :           7 :   klass->g_authorize_method = g_dbus_interface_skeleton_g_authorize_method_default;
     185                 :             : 
     186                 :             :   /**
     187                 :             :    * GDBusInterfaceSkeleton:g-flags:
     188                 :             :    *
     189                 :             :    * Flags from the #GDBusInterfaceSkeletonFlags enumeration.
     190                 :             :    *
     191                 :             :    * Since: 2.30
     192                 :             :    */
     193                 :           7 :   g_object_class_install_property (gobject_class,
     194                 :             :                                    PROP_G_FLAGS,
     195                 :             :                                    g_param_spec_flags ("g-flags", NULL, NULL,
     196                 :             :                                                        G_TYPE_DBUS_INTERFACE_SKELETON_FLAGS,
     197                 :             :                                                        G_DBUS_INTERFACE_SKELETON_FLAGS_NONE,
     198                 :             :                                                        G_PARAM_READABLE |
     199                 :             :                                                        G_PARAM_WRITABLE |
     200                 :             :                                                        G_PARAM_STATIC_STRINGS));
     201                 :             : 
     202                 :             :   /**
     203                 :             :    * GDBusInterfaceSkeleton::g-authorize-method:
     204                 :             :    * @interface: The #GDBusInterfaceSkeleton emitting the signal.
     205                 :             :    * @invocation: A #GDBusMethodInvocation.
     206                 :             :    *
     207                 :             :    * Emitted when a method is invoked by a remote caller and used to
     208                 :             :    * determine if the method call is authorized.
     209                 :             :    *
     210                 :             :    * Note that this signal is emitted in a thread dedicated to
     211                 :             :    * handling the method call so handlers are allowed to perform
     212                 :             :    * blocking IO. This means that it is appropriate to call e.g.
     213                 :             :    * [polkit_authority_check_authorization_sync()](http://hal.freedesktop.org/docs/polkit/PolkitAuthority.html#polkit-authority-check-authorization-sync)
     214                 :             :    * with the
     215                 :             :    * [POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION](http://hal.freedesktop.org/docs/polkit/PolkitAuthority.html#POLKIT-CHECK-AUTHORIZATION-FLAGS-ALLOW-USER-INTERACTION:CAPS)
     216                 :             :    * flag set.
     217                 :             :    *
     218                 :             :    * If %FALSE is returned then no further handlers are run and the
     219                 :             :    * signal handler must take a reference to @invocation and finish
     220                 :             :    * handling the call (e.g. return an error via
     221                 :             :    * g_dbus_method_invocation_return_error()).
     222                 :             :    *
     223                 :             :    * Otherwise, if %TRUE is returned, signal emission continues. If no
     224                 :             :    * handlers return %FALSE, then the method is dispatched. If
     225                 :             :    * @interface has an enclosing #GDBusObjectSkeleton, then the
     226                 :             :    * #GDBusObjectSkeleton::authorize-method signal handlers run before
     227                 :             :    * the handlers for this signal.
     228                 :             :    *
     229                 :             :    * The default class handler just returns %TRUE.
     230                 :             :    *
     231                 :             :    * Please note that the common case is optimized: if no signals
     232                 :             :    * handlers are connected and the default class handler isn't
     233                 :             :    * overridden (for both @interface and the enclosing
     234                 :             :    * #GDBusObjectSkeleton, if any) and #GDBusInterfaceSkeleton:g-flags does
     235                 :             :    * not have the
     236                 :             :    * %G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD
     237                 :             :    * flags set, no dedicated thread is ever used and the call will be
     238                 :             :    * handled in the same thread as the object that @interface belongs
     239                 :             :    * to was exported in.
     240                 :             :    *
     241                 :             :    * Returns: %TRUE if the call is authorized, %FALSE otherwise.
     242                 :             :    *
     243                 :             :    * Since: 2.30
     244                 :             :    */
     245                 :           7 :   signals[G_AUTHORIZE_METHOD_SIGNAL] =
     246                 :           7 :     g_signal_new (I_("g-authorize-method"),
     247                 :             :                   G_TYPE_DBUS_INTERFACE_SKELETON,
     248                 :             :                   G_SIGNAL_RUN_LAST,
     249                 :             :                   G_STRUCT_OFFSET (GDBusInterfaceSkeletonClass, g_authorize_method),
     250                 :             :                   _g_signal_accumulator_false_handled,
     251                 :             :                   NULL,
     252                 :             :                   _g_cclosure_marshal_BOOLEAN__OBJECT,
     253                 :             :                   G_TYPE_BOOLEAN,
     254                 :             :                   1,
     255                 :             :                   G_TYPE_DBUS_METHOD_INVOCATION);
     256                 :           7 :   g_signal_set_va_marshaller (signals[G_AUTHORIZE_METHOD_SIGNAL],
     257                 :             :                               G_TYPE_FROM_CLASS (klass),
     258                 :             :                               _g_cclosure_marshal_BOOLEAN__OBJECTv);
     259                 :           7 : }
     260                 :             : 
     261                 :             : static void
     262                 :          63 : g_dbus_interface_skeleton_init (GDBusInterfaceSkeleton *interface)
     263                 :             : {
     264                 :          63 :   interface->priv = g_dbus_interface_skeleton_get_instance_private (interface);
     265                 :          63 :   g_mutex_init (&interface->priv->lock);
     266                 :          63 : }
     267                 :             : 
     268                 :             : /* ---------------------------------------------------------------------------------------------------- */
     269                 :             : 
     270                 :             : /**
     271                 :             :  * g_dbus_interface_skeleton_get_flags:
     272                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     273                 :             :  *
     274                 :             :  * Gets the #GDBusInterfaceSkeletonFlags that describes what the behavior
     275                 :             :  * of @interface_
     276                 :             :  *
     277                 :             :  * Returns: One or more flags from the #GDBusInterfaceSkeletonFlags enumeration.
     278                 :             :  *
     279                 :             :  * Since: 2.30
     280                 :             :  */
     281                 :             : GDBusInterfaceSkeletonFlags
     282                 :           6 : g_dbus_interface_skeleton_get_flags (GDBusInterfaceSkeleton  *interface_)
     283                 :             : {
     284                 :           6 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), G_DBUS_INTERFACE_SKELETON_FLAGS_NONE);
     285                 :           6 :   return interface_->priv->flags;
     286                 :             : }
     287                 :             : 
     288                 :             : /**
     289                 :             :  * g_dbus_interface_skeleton_set_flags:
     290                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     291                 :             :  * @flags: Flags from the #GDBusInterfaceSkeletonFlags enumeration.
     292                 :             :  *
     293                 :             :  * Sets flags describing what the behavior of @skeleton should be.
     294                 :             :  *
     295                 :             :  * Since: 2.30
     296                 :             :  */
     297                 :             : void
     298                 :           7 : g_dbus_interface_skeleton_set_flags (GDBusInterfaceSkeleton      *interface_,
     299                 :             :                                      GDBusInterfaceSkeletonFlags  flags)
     300                 :             : {
     301                 :           7 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_));
     302                 :           7 :   g_mutex_lock (&interface_->priv->lock);
     303                 :           7 :   if (interface_->priv->flags != flags)
     304                 :             :     {
     305                 :           7 :       interface_->priv->flags = flags;
     306                 :           7 :       g_mutex_unlock (&interface_->priv->lock);
     307                 :           7 :       g_object_notify (G_OBJECT (interface_), "g-flags");
     308                 :             :     }
     309                 :             :   else
     310                 :             :     {
     311                 :           0 :       g_mutex_unlock (&interface_->priv->lock);
     312                 :             :     }
     313                 :             : }
     314                 :             : 
     315                 :             : /**
     316                 :             :  * g_dbus_interface_skeleton_get_info:
     317                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     318                 :             :  *
     319                 :             :  * Gets D-Bus introspection information for the D-Bus interface
     320                 :             :  * implemented by @interface_.
     321                 :             :  *
     322                 :             :  * Returns: (transfer none): A #GDBusInterfaceInfo (never %NULL). Do not free.
     323                 :             :  *
     324                 :             :  * Since: 2.30
     325                 :             :  */
     326                 :             : GDBusInterfaceInfo *
     327                 :         240 : g_dbus_interface_skeleton_get_info (GDBusInterfaceSkeleton *interface_)
     328                 :             : {
     329                 :             :   GDBusInterfaceInfo *ret;
     330                 :         240 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     331                 :         240 :   ret = G_DBUS_INTERFACE_SKELETON_GET_CLASS (interface_)->get_info (interface_);
     332                 :         240 :   g_warn_if_fail (ret != NULL);
     333                 :         240 :   return ret;
     334                 :             : }
     335                 :             : 
     336                 :             : /**
     337                 :             :  * g_dbus_interface_skeleton_get_vtable:
     338                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     339                 :             :  *
     340                 :             :  * Gets the interface vtable for the D-Bus interface implemented by
     341                 :             :  * @interface_. The returned function pointers should expect @interface_
     342                 :             :  * itself to be passed as @user_data.
     343                 :             :  *
     344                 :             :  * Returns: (not nullable) (transfer none): the vtable of the D-Bus interface implemented by the skeleton
     345                 :             :  *
     346                 :             :  * Since: 2.30
     347                 :             :  */
     348                 :             : GDBusInterfaceVTable *
     349                 :         107 : g_dbus_interface_skeleton_get_vtable (GDBusInterfaceSkeleton *interface_)
     350                 :             : {
     351                 :             :   GDBusInterfaceVTable *ret;
     352                 :         107 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     353                 :         107 :   ret = G_DBUS_INTERFACE_SKELETON_GET_CLASS (interface_)->get_vtable (interface_);
     354                 :         107 :   g_warn_if_fail (ret != NULL);
     355                 :         107 :   return ret;
     356                 :             : }
     357                 :             : 
     358                 :             : /**
     359                 :             :  * g_dbus_interface_skeleton_get_properties:
     360                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     361                 :             :  *
     362                 :             :  * Gets all D-Bus properties for @interface_.
     363                 :             :  *
     364                 :             :  * Returns: (transfer full): A #GVariant of type
     365                 :             :  * ['a{sv}'][G-VARIANT-TYPE-VARDICT:CAPS].
     366                 :             :  * Free with g_variant_unref().
     367                 :             :  *
     368                 :             :  * Since: 2.30
     369                 :             :  */
     370                 :             : GVariant *
     371                 :          58 : g_dbus_interface_skeleton_get_properties (GDBusInterfaceSkeleton *interface_)
     372                 :             : {
     373                 :             :   GVariant *ret;
     374                 :          58 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     375                 :          58 :   ret = G_DBUS_INTERFACE_SKELETON_GET_CLASS (interface_)->get_properties (interface_);
     376                 :          58 :   return g_variant_take_ref (ret);
     377                 :             : }
     378                 :             : 
     379                 :             : /**
     380                 :             :  * g_dbus_interface_skeleton_flush:
     381                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     382                 :             :  *
     383                 :             :  * If @interface_ has outstanding changes, request for these changes to be
     384                 :             :  * emitted immediately.
     385                 :             :  *
     386                 :             :  * For example, an exported D-Bus interface may queue up property
     387                 :             :  * changes and emit the
     388                 :             :  * `org.freedesktop.DBus.Properties.PropertiesChanged`
     389                 :             :  * signal later (e.g. in an idle handler). This technique is useful
     390                 :             :  * for collapsing multiple property changes into one.
     391                 :             :  *
     392                 :             :  * Since: 2.30
     393                 :             :  */
     394                 :             : void
     395                 :           6 : g_dbus_interface_skeleton_flush (GDBusInterfaceSkeleton *interface_)
     396                 :             : {
     397                 :           6 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_));
     398                 :           6 :   G_DBUS_INTERFACE_SKELETON_GET_CLASS (interface_)->flush (interface_);
     399                 :             : }
     400                 :             : 
     401                 :             : /* ---------------------------------------------------------------------------------------------------- */
     402                 :             : 
     403                 :             : static GDBusInterfaceInfo *
     404                 :          42 : _g_dbus_interface_skeleton_get_info (GDBusInterface *interface_)
     405                 :             : {
     406                 :          42 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (interface_);
     407                 :          42 :   return g_dbus_interface_skeleton_get_info (interface);
     408                 :             : }
     409                 :             : 
     410                 :             : static GDBusObject *
     411                 :          12 : g_dbus_interface_skeleton_get_object (GDBusInterface *interface_)
     412                 :             : {
     413                 :          12 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (interface_);
     414                 :             :   GDBusObject *ret;
     415                 :          12 :   g_mutex_lock (&interface->priv->lock);
     416                 :          12 :   ret = interface->priv->object;
     417                 :          12 :   g_mutex_unlock (&interface->priv->lock);
     418                 :          12 :   return ret;
     419                 :             : }
     420                 :             : 
     421                 :             : static GDBusObject *
     422                 :           3 : g_dbus_interface_skeleton_dup_object (GDBusInterface *interface_)
     423                 :             : {
     424                 :           3 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (interface_);
     425                 :             :   GDBusObject *ret;
     426                 :           3 :   g_mutex_lock (&interface->priv->lock);
     427                 :           3 :   ret = interface->priv->object;
     428                 :           3 :   if (ret != NULL)
     429                 :           3 :     g_object_ref (ret);
     430                 :           3 :   g_mutex_unlock (&interface->priv->lock);
     431                 :           3 :   return ret;
     432                 :             : }
     433                 :             : 
     434                 :             : static void
     435                 :          49 : g_dbus_interface_skeleton_set_object (GDBusInterface *interface_,
     436                 :             :                                       GDBusObject    *object)
     437                 :             : {
     438                 :          49 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (interface_);
     439                 :          49 :   g_mutex_lock (&interface->priv->lock);
     440                 :          49 :   if (interface->priv->object != NULL)
     441                 :          15 :     g_object_remove_weak_pointer (G_OBJECT (interface->priv->object), (gpointer *) &interface->priv->object);
     442                 :          49 :   interface->priv->object = object;
     443                 :          49 :   if (object != NULL)
     444                 :          34 :     g_object_add_weak_pointer (G_OBJECT (interface->priv->object), (gpointer *) &interface->priv->object);
     445                 :          49 :   g_mutex_unlock (&interface->priv->lock);
     446                 :          49 : }
     447                 :             : 
     448                 :             : static void
     449                 :           7 : dbus_interface_interface_init (GDBusInterfaceIface *iface)
     450                 :             : {
     451                 :           7 :   iface->get_info    = _g_dbus_interface_skeleton_get_info;
     452                 :           7 :   iface->get_object  = g_dbus_interface_skeleton_get_object;
     453                 :           7 :   iface->dup_object  = g_dbus_interface_skeleton_dup_object;
     454                 :           7 :   iface->set_object  = g_dbus_interface_skeleton_set_object;
     455                 :           7 : }
     456                 :             : 
     457                 :             : /* ---------------------------------------------------------------------------------------------------- */
     458                 :             : 
     459                 :             : typedef struct
     460                 :             : {
     461                 :             :   gint ref_count;  /* (atomic) */
     462                 :             :   GDBusInterfaceMethodCallFunc  method_call_func;
     463                 :             :   GDBusMethodInvocation        *invocation;  /* (owned) */
     464                 :             : } DispatchData;
     465                 :             : 
     466                 :             : static void
     467                 :          15 : dispatch_data_unref (DispatchData *data)
     468                 :             : {
     469                 :          15 :   if (g_atomic_int_dec_and_test (&data->ref_count))
     470                 :             :     {
     471                 :          12 :       g_clear_object (&data->invocation);
     472                 :          12 :       g_slice_free (DispatchData, data);
     473                 :             :     }
     474                 :          15 : }
     475                 :             : 
     476                 :             : static DispatchData *
     477                 :           3 : dispatch_data_ref (DispatchData *data)
     478                 :             : {
     479                 :           3 :   g_atomic_int_inc (&data->ref_count);
     480                 :           3 :   return data;
     481                 :             : }
     482                 :             : 
     483                 :             : static gboolean
     484                 :           3 : dispatch_invoke_in_context_func (gpointer user_data)
     485                 :             : {
     486                 :           3 :   DispatchData *data = user_data;
     487                 :           3 :   data->method_call_func (g_dbus_method_invocation_get_connection (data->invocation),
     488                 :             :                           g_dbus_method_invocation_get_sender (data->invocation),
     489                 :             :                           g_dbus_method_invocation_get_object_path (data->invocation),
     490                 :             :                           g_dbus_method_invocation_get_interface_name (data->invocation),
     491                 :             :                           g_dbus_method_invocation_get_method_name (data->invocation),
     492                 :             :                           g_dbus_method_invocation_get_parameters (data->invocation),
     493                 :             :                           data->invocation,
     494                 :             :                           g_dbus_method_invocation_get_user_data (data->invocation));
     495                 :           3 :   return FALSE;
     496                 :             : }
     497                 :             : 
     498                 :             : static void
     499                 :          12 : dispatch_in_thread_func (GTask        *task,
     500                 :             :                          gpointer      source_object,
     501                 :             :                          gpointer      task_data,
     502                 :             :                          GCancellable *cancellable)
     503                 :             : {
     504                 :          12 :   DispatchData *data = task_data;
     505                 :          12 :   GDBusInterfaceSkeleton *interface = g_task_get_source_object (task);
     506                 :             :   GDBusInterfaceSkeletonFlags flags;
     507                 :             :   GDBusObject *object;
     508                 :             :   gboolean authorized;
     509                 :             : 
     510                 :          12 :   g_mutex_lock (&interface->priv->lock);
     511                 :          12 :   flags = interface->priv->flags;
     512                 :          12 :   object = interface->priv->object;
     513                 :          12 :   if (object != NULL)
     514                 :           9 :     g_object_ref (object);
     515                 :          12 :   g_mutex_unlock (&interface->priv->lock);
     516                 :             : 
     517                 :             :   /* first check on the enclosing object (if any), then the interface */
     518                 :          12 :   authorized = TRUE;
     519                 :          12 :   if (object != NULL)
     520                 :             :     {
     521                 :           9 :       g_signal_emit_by_name (object,
     522                 :             :                              "authorize-method",
     523                 :             :                              interface,
     524                 :             :                              data->invocation,
     525                 :             :                              &authorized);
     526                 :             :     }
     527                 :          12 :   if (authorized)
     528                 :             :     {
     529                 :           9 :       g_signal_emit (interface,
     530                 :             :                      signals[G_AUTHORIZE_METHOD_SIGNAL],
     531                 :             :                      0,
     532                 :             :                      data->invocation,
     533                 :             :                      &authorized);
     534                 :             :     }
     535                 :             : 
     536                 :          12 :   if (authorized)
     537                 :             :     {
     538                 :             :       gboolean run_in_thread;
     539                 :           6 :       run_in_thread = (flags & G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
     540                 :           6 :       if (run_in_thread)
     541                 :             :         {
     542                 :             :           /* might as well just re-use the existing thread */
     543                 :           3 :           data->method_call_func (g_dbus_method_invocation_get_connection (data->invocation),
     544                 :             :                                   g_dbus_method_invocation_get_sender (data->invocation),
     545                 :             :                                   g_dbus_method_invocation_get_object_path (data->invocation),
     546                 :             :                                   g_dbus_method_invocation_get_interface_name (data->invocation),
     547                 :             :                                   g_dbus_method_invocation_get_method_name (data->invocation),
     548                 :             :                                   g_dbus_method_invocation_get_parameters (data->invocation),
     549                 :             :                                   data->invocation,
     550                 :             :                                   g_dbus_method_invocation_get_user_data (data->invocation));
     551                 :             :         }
     552                 :             :       else
     553                 :             :         {
     554                 :             :           /* bah, back to original context */
     555                 :           3 :           g_main_context_invoke_full (g_task_get_context (task),
     556                 :             :                                       g_task_get_priority (task),
     557                 :             :                                       dispatch_invoke_in_context_func,
     558                 :           3 :                                       dispatch_data_ref (data),
     559                 :             :                                       (GDestroyNotify) dispatch_data_unref);
     560                 :             :         }
     561                 :             :     }
     562                 :             :   else
     563                 :             :     {
     564                 :             :       /* do nothing */
     565                 :             :     }
     566                 :             : 
     567                 :          12 :   if (object != NULL)
     568                 :           9 :     g_object_unref (object);
     569                 :             : 
     570                 :          12 :   g_task_return_boolean (task, TRUE);
     571                 :          12 : }
     572                 :             : 
     573                 :             : static void
     574                 :          49 : g_dbus_interface_method_dispatch_helper (GDBusInterfaceSkeleton       *interface,
     575                 :             :                                          GDBusInterfaceMethodCallFunc  method_call_func,
     576                 :             :                                          GDBusMethodInvocation        *invocation)
     577                 :             : {
     578                 :             :   gboolean has_handlers;
     579                 :             :   gboolean has_default_class_handler;
     580                 :             :   gboolean emit_authorized_signal;
     581                 :             :   gboolean run_in_thread;
     582                 :             :   GDBusInterfaceSkeletonFlags flags;
     583                 :             :   GDBusObject *object;
     584                 :             : 
     585                 :          49 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface));
     586                 :          49 :   g_return_if_fail (method_call_func != NULL);
     587                 :          49 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     588                 :             : 
     589                 :          49 :   g_mutex_lock (&interface->priv->lock);
     590                 :          49 :   flags = interface->priv->flags;
     591                 :          49 :   object = interface->priv->object;
     592                 :          49 :   if (object != NULL)
     593                 :           9 :     g_object_ref (object);
     594                 :          49 :   g_mutex_unlock (&interface->priv->lock);
     595                 :             : 
     596                 :             :   /* optimization for the common case where
     597                 :             :    *
     598                 :             :    *  a) no handler is connected and class handler is not overridden (both interface and object); and
     599                 :             :    *  b) method calls are not dispatched in a thread
     600                 :             :    */
     601                 :          49 :   has_handlers = g_signal_has_handler_pending (interface,
     602                 :             :                                                signals[G_AUTHORIZE_METHOD_SIGNAL],
     603                 :             :                                                0,
     604                 :             :                                                TRUE);
     605                 :          49 :   has_default_class_handler = (G_DBUS_INTERFACE_SKELETON_GET_CLASS (interface)->g_authorize_method ==
     606                 :             :                                g_dbus_interface_skeleton_g_authorize_method_default);
     607                 :             : 
     608                 :          49 :   emit_authorized_signal = (has_handlers || !has_default_class_handler);
     609                 :          49 :   if (!emit_authorized_signal)
     610                 :             :     {
     611                 :          40 :       if (object != NULL)
     612                 :           0 :         emit_authorized_signal = _g_dbus_object_skeleton_has_authorize_method_handlers (G_DBUS_OBJECT_SKELETON (object));
     613                 :             :     }
     614                 :             : 
     615                 :          49 :   run_in_thread = (flags & G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
     616                 :          49 :   if (!emit_authorized_signal && !run_in_thread)
     617                 :             :     {
     618                 :          37 :       method_call_func (g_dbus_method_invocation_get_connection (invocation),
     619                 :             :                         g_dbus_method_invocation_get_sender (invocation),
     620                 :             :                         g_dbus_method_invocation_get_object_path (invocation),
     621                 :             :                         g_dbus_method_invocation_get_interface_name (invocation),
     622                 :             :                         g_dbus_method_invocation_get_method_name (invocation),
     623                 :             :                         g_dbus_method_invocation_get_parameters (invocation),
     624                 :             :                         invocation,
     625                 :             :                         g_dbus_method_invocation_get_user_data (invocation));
     626                 :             :     }
     627                 :             :   else
     628                 :             :     {
     629                 :             :       GTask *task;
     630                 :             :       DispatchData *data;
     631                 :             : 
     632                 :          12 :       data = g_slice_new0 (DispatchData);
     633                 :          12 :       data->method_call_func = method_call_func;
     634                 :          12 :       data->invocation = g_object_ref (invocation);
     635                 :          12 :       data->ref_count = 1;
     636                 :             : 
     637                 :          12 :       task = g_task_new (interface, NULL, NULL, NULL);
     638                 :          12 :       g_task_set_source_tag (task, g_dbus_interface_method_dispatch_helper);
     639                 :          12 :       g_task_set_name (task, "[gio] D-Bus interface method dispatch");
     640                 :          12 :       g_task_set_task_data (task, data, (GDestroyNotify) dispatch_data_unref);
     641                 :          12 :       g_task_run_in_thread (task, dispatch_in_thread_func);
     642                 :          12 :       g_object_unref (task);
     643                 :             :     }
     644                 :             : 
     645                 :          49 :   if (object != NULL)
     646                 :           9 :     g_object_unref (object);
     647                 :             : }
     648                 :             : 
     649                 :             : static void
     650                 :          49 : skeleton_intercept_handle_method_call (GDBusConnection       *connection,
     651                 :             :                                        const gchar           *sender,
     652                 :             :                                        const gchar           *object_path,
     653                 :             :                                        const gchar           *interface_name,
     654                 :             :                                        const gchar           *method_name,
     655                 :             :                                        GVariant              *parameters,
     656                 :             :                                        GDBusMethodInvocation *invocation,
     657                 :             :                                        gpointer               user_data)
     658                 :             : {
     659                 :          49 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (user_data);
     660                 :          49 :   g_dbus_interface_method_dispatch_helper (interface,
     661                 :          49 :                                            g_dbus_interface_skeleton_get_vtable (interface)->method_call,
     662                 :             :                                            invocation);
     663                 :          49 : }
     664                 :             : 
     665                 :             : /* ---------------------------------------------------------------------------------------------------- */
     666                 :             : 
     667                 :             : static ConnectionData *
     668                 :          67 : new_connection (GDBusConnection *connection,
     669                 :             :                 guint            registration_id)
     670                 :             : {
     671                 :             :   ConnectionData *data;
     672                 :             : 
     673                 :          67 :   data = g_slice_new0 (ConnectionData);
     674                 :          67 :   data->connection      = g_object_ref (connection);
     675                 :          67 :   data->registration_id = registration_id;
     676                 :             : 
     677                 :          67 :   return data;
     678                 :             : }
     679                 :             : 
     680                 :             : static void
     681                 :          67 : free_connection (ConnectionData *data)
     682                 :             : {
     683                 :          67 :   if (data != NULL)
     684                 :             :     {
     685                 :          67 :       g_object_unref (data->connection);
     686                 :          67 :       g_slice_free (ConnectionData, data);
     687                 :             :     }
     688                 :          67 : }
     689                 :             : 
     690                 :             : static gboolean
     691                 :          67 : add_connection_locked (GDBusInterfaceSkeleton *interface_,
     692                 :             :                        GDBusConnection        *connection,
     693                 :             :                        GError                **error)
     694                 :             : {
     695                 :             :   ConnectionData *data;
     696                 :             :   guint registration_id;
     697                 :          67 :   gboolean ret = FALSE;
     698                 :             : 
     699                 :          67 :   if (interface_->priv->hooked_vtable == NULL)
     700                 :             :     {
     701                 :             :       /* Hook the vtable since we need to intercept method calls for
     702                 :             :        * ::g-authorize-method and for dispatching in thread vs
     703                 :             :        * context
     704                 :             :        *
     705                 :             :        * We need to wait until subclasses have had time to initialize
     706                 :             :        * properly before building the hooked_vtable, so we create it
     707                 :             :        * once at the last minute.
     708                 :             :        */
     709                 :          54 :       interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
     710                 :          54 :       interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call;
     711                 :             :     }
     712                 :             : 
     713                 :         134 :   registration_id = g_dbus_connection_register_object (connection,
     714                 :          67 :                                                        interface_->priv->object_path,
     715                 :             :                                                        g_dbus_interface_skeleton_get_info (interface_),
     716                 :          67 :                                                        interface_->priv->hooked_vtable,
     717                 :             :                                                        interface_,
     718                 :             :                                                        NULL, /* user_data_free_func */
     719                 :             :                                                        error);
     720                 :             : 
     721                 :          67 :   if (registration_id > 0)
     722                 :             :     {
     723                 :          67 :       data = new_connection (connection, registration_id);
     724                 :          67 :       interface_->priv->connections = g_slist_append (interface_->priv->connections, data);
     725                 :          67 :       ret = TRUE;
     726                 :             :     }
     727                 :             : 
     728                 :          67 :   return ret;
     729                 :             : }
     730                 :             : 
     731                 :             : static void
     732                 :          67 : remove_connection_locked (GDBusInterfaceSkeleton *interface_,
     733                 :             :                           GDBusConnection        *connection)
     734                 :             : {
     735                 :             :   ConnectionData *data;
     736                 :             :   GSList *l;
     737                 :             : 
     738                 :             :   /* Get the connection in the list and unregister ... */
     739                 :          67 :   for (l = interface_->priv->connections; l != NULL; l = l->next)
     740                 :             :     {
     741                 :          67 :       data = l->data;
     742                 :          67 :       if (data->connection == connection)
     743                 :             :         {
     744                 :          67 :           g_warn_if_fail (g_dbus_connection_unregister_object (data->connection, data->registration_id));
     745                 :          67 :           free_connection (data);
     746                 :          67 :           interface_->priv->connections = g_slist_delete_link (interface_->priv->connections, l);
     747                 :             :           /* we are guaranteed that the connection is only added once, so bail out early */
     748                 :          67 :           goto out;
     749                 :             :         }
     750                 :             :     }
     751                 :           0 :  out:
     752                 :             :   ;
     753                 :          67 : }
     754                 :             : 
     755                 :             : static void
     756                 :         173 : set_object_path_locked (GDBusInterfaceSkeleton *interface_,
     757                 :             :                         const gchar            *object_path)
     758                 :             : {
     759                 :         173 :   if (g_strcmp0 (interface_->priv->object_path, object_path) != 0)
     760                 :             :     {
     761                 :         132 :       g_free (interface_->priv->object_path);
     762                 :         264 :       interface_->priv->object_path = g_strdup (object_path);
     763                 :             :     }
     764                 :         173 : }
     765                 :             : 
     766                 :             : /* ---------------------------------------------------------------------------------------------------- */
     767                 :             : 
     768                 :             : /**
     769                 :             :  * g_dbus_interface_skeleton_get_connection:
     770                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     771                 :             :  *
     772                 :             :  * Gets the first connection that @interface_ is exported on, if any.
     773                 :             :  *
     774                 :             :  * Returns: (nullable) (transfer none): A #GDBusConnection or %NULL if @interface_ is
     775                 :             :  * not exported anywhere. Do not free, the object belongs to @interface_.
     776                 :             :  *
     777                 :             :  * Since: 2.30
     778                 :             :  */
     779                 :             : GDBusConnection *
     780                 :         776 : g_dbus_interface_skeleton_get_connection (GDBusInterfaceSkeleton *interface_)
     781                 :             : {
     782                 :             :   ConnectionData  *data;
     783                 :             :   GDBusConnection *ret;
     784                 :             : 
     785                 :         776 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     786                 :         776 :   g_mutex_lock (&interface_->priv->lock);
     787                 :             : 
     788                 :         776 :   ret = NULL;
     789                 :         776 :   if (interface_->priv->connections != NULL)
     790                 :             :     {
     791                 :         742 :       data = interface_->priv->connections->data;
     792                 :         742 :       if (data != NULL)
     793                 :         742 :         ret = data->connection;
     794                 :             :     }
     795                 :             : 
     796                 :         776 :   g_mutex_unlock (&interface_->priv->lock);
     797                 :             : 
     798                 :         776 :   return ret;
     799                 :             : }
     800                 :             : 
     801                 :             : /**
     802                 :             :  * g_dbus_interface_skeleton_get_connections:
     803                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     804                 :             :  *
     805                 :             :  * Gets a list of the connections that @interface_ is exported on.
     806                 :             :  *
     807                 :             :  * Returns: (element-type GDBusConnection) (transfer full): A list of
     808                 :             :  *   all the connections that @interface_ is exported on. The returned
     809                 :             :  *   list should be freed with g_list_free() after each element has
     810                 :             :  *   been freed with g_object_unref().
     811                 :             :  *
     812                 :             :  * Since: 2.32
     813                 :             :  */
     814                 :             : GList *
     815                 :          68 : g_dbus_interface_skeleton_get_connections (GDBusInterfaceSkeleton *interface_)
     816                 :             : {
     817                 :             :   GList           *connections;
     818                 :             :   GSList          *l;
     819                 :             :   ConnectionData  *data;
     820                 :             : 
     821                 :          68 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     822                 :             : 
     823                 :          68 :   g_mutex_lock (&interface_->priv->lock);
     824                 :          68 :   connections = NULL;
     825                 :             : 
     826                 :         138 :   for (l = interface_->priv->connections; l != NULL; l = l->next)
     827                 :             :     {
     828                 :          70 :       data        = l->data;
     829                 :          70 :       connections = g_list_prepend (connections,
     830                 :             :                                     /* Return a reference to each connection */
     831                 :          70 :                                     g_object_ref (data->connection));
     832                 :             :     }
     833                 :             : 
     834                 :          68 :   g_mutex_unlock (&interface_->priv->lock);
     835                 :             : 
     836                 :          68 :   return g_list_reverse (connections);
     837                 :             : }
     838                 :             : 
     839                 :             : /**
     840                 :             :  * g_dbus_interface_skeleton_has_connection:
     841                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     842                 :             :  * @connection: A #GDBusConnection.
     843                 :             :  *
     844                 :             :  * Checks if @interface_ is exported on @connection.
     845                 :             :  *
     846                 :             :  * Returns: %TRUE if @interface_ is exported on @connection, %FALSE otherwise.
     847                 :             :  *
     848                 :             :  * Since: 2.32
     849                 :             :  */
     850                 :             : gboolean
     851                 :           3 : g_dbus_interface_skeleton_has_connection (GDBusInterfaceSkeleton     *interface_,
     852                 :             :                                           GDBusConnection            *connection)
     853                 :             : {
     854                 :             :   GSList *l;
     855                 :           3 :   gboolean ret = FALSE;
     856                 :             : 
     857                 :           3 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), FALSE);
     858                 :           3 :   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
     859                 :             : 
     860                 :           3 :   g_mutex_lock (&interface_->priv->lock);
     861                 :             : 
     862                 :           3 :   for (l = interface_->priv->connections; l != NULL; l = l->next)
     863                 :             :     {
     864                 :           0 :       ConnectionData *data = l->data;
     865                 :           0 :       if (data->connection == connection)
     866                 :             :         {
     867                 :           0 :           ret = TRUE;
     868                 :           0 :           goto out;
     869                 :             :         }
     870                 :             :     }
     871                 :             : 
     872                 :           3 :  out:
     873                 :           3 :   g_mutex_unlock (&interface_->priv->lock);
     874                 :           3 :   return ret;
     875                 :             : }
     876                 :             : 
     877                 :             : /**
     878                 :             :  * g_dbus_interface_skeleton_get_object_path:
     879                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     880                 :             :  *
     881                 :             :  * Gets the object path that @interface_ is exported on, if any.
     882                 :             :  *
     883                 :             :  * Returns: (nullable): A string owned by @interface_ or %NULL if @interface_ is not exported
     884                 :             :  * anywhere. Do not free, the string belongs to @interface_.
     885                 :             :  *
     886                 :             :  * Since: 2.30
     887                 :             :  */
     888                 :             : const gchar *
     889                 :         708 : g_dbus_interface_skeleton_get_object_path (GDBusInterfaceSkeleton *interface_)
     890                 :             : {
     891                 :             :   const gchar *ret;
     892                 :         708 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     893                 :         708 :   g_mutex_lock (&interface_->priv->lock);
     894                 :         708 :   ret = interface_->priv->object_path;
     895                 :         708 :   g_mutex_unlock (&interface_->priv->lock);
     896                 :         708 :   return ret;
     897                 :             : }
     898                 :             : 
     899                 :             : /**
     900                 :             :  * g_dbus_interface_skeleton_export:
     901                 :             :  * @interface_: The D-Bus interface to export.
     902                 :             :  * @connection: A #GDBusConnection to export @interface_ on.
     903                 :             :  * @object_path: The path to export the interface at.
     904                 :             :  * @error: Return location for error or %NULL.
     905                 :             :  *
     906                 :             :  * Exports @interface_ at @object_path on @connection.
     907                 :             :  *
     908                 :             :  * This can be called multiple times to export the same @interface_
     909                 :             :  * onto multiple connections however the @object_path provided must be
     910                 :             :  * the same for all connections.
     911                 :             :  *
     912                 :             :  * Use g_dbus_interface_skeleton_unexport() to unexport the object.
     913                 :             :  *
     914                 :             :  * Returns: %TRUE if the interface was exported on @connection, otherwise %FALSE with
     915                 :             :  * @error set.
     916                 :             :  *
     917                 :             :  * Since: 2.30
     918                 :             :  */
     919                 :             : gboolean
     920                 :          67 : g_dbus_interface_skeleton_export (GDBusInterfaceSkeleton  *interface_,
     921                 :             :                                   GDBusConnection         *connection,
     922                 :             :                                   const gchar             *object_path,
     923                 :             :                                   GError                 **error)
     924                 :             : {
     925                 :          67 :   gboolean ret = FALSE;
     926                 :             : 
     927                 :          67 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), FALSE);
     928                 :          67 :   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
     929                 :          67 :   g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
     930                 :          67 :   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
     931                 :             : 
     932                 :             :   /* Assert that the object path is the same for multiple connections here */
     933                 :          67 :   g_return_val_if_fail (interface_->priv->object_path == NULL ||
     934                 :             :                         g_strcmp0 (interface_->priv->object_path, object_path) == 0, FALSE);
     935                 :             : 
     936                 :          67 :   g_mutex_lock (&interface_->priv->lock);
     937                 :             : 
     938                 :             :   /* Set the object path */
     939                 :          67 :   set_object_path_locked (interface_, object_path);
     940                 :             : 
     941                 :             :   /* Add the connection */
     942                 :          67 :   ret = add_connection_locked (interface_, connection, error);
     943                 :             : 
     944                 :          67 :   g_mutex_unlock (&interface_->priv->lock);
     945                 :          67 :   return ret;
     946                 :             : }
     947                 :             : 
     948                 :             : /**
     949                 :             :  * g_dbus_interface_skeleton_unexport:
     950                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     951                 :             :  *
     952                 :             :  * Stops exporting @interface_ on all connections it is exported on.
     953                 :             :  *
     954                 :             :  * To unexport @interface_ from only a single connection, use
     955                 :             :  * g_dbus_interface_skeleton_unexport_from_connection()
     956                 :             :  *
     957                 :             :  * Since: 2.30
     958                 :             :  */
     959                 :             : void
     960                 :          65 : g_dbus_interface_skeleton_unexport (GDBusInterfaceSkeleton *interface_)
     961                 :             : {
     962                 :          65 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_));
     963                 :          65 :   g_return_if_fail (interface_->priv->connections != NULL);
     964                 :             : 
     965                 :          65 :   g_mutex_lock (&interface_->priv->lock);
     966                 :             : 
     967                 :          65 :   g_assert (interface_->priv->object_path != NULL);
     968                 :          65 :   g_assert (interface_->priv->hooked_vtable != NULL);
     969                 :             : 
     970                 :             :   /* Remove all connections */
     971                 :         130 :   while (interface_->priv->connections != NULL)
     972                 :             :     {
     973                 :          65 :       ConnectionData *data = interface_->priv->connections->data;
     974                 :          65 :       remove_connection_locked (interface_, data->connection);
     975                 :             :     }
     976                 :             : 
     977                 :             :   /* Unset the object path since there are no connections left */
     978                 :          65 :   set_object_path_locked (interface_, NULL);
     979                 :             : 
     980                 :          65 :   g_mutex_unlock (&interface_->priv->lock);
     981                 :             : }
     982                 :             : 
     983                 :             : 
     984                 :             : /**
     985                 :             :  * g_dbus_interface_skeleton_unexport_from_connection:
     986                 :             :  * @interface_: A #GDBusInterfaceSkeleton.
     987                 :             :  * @connection: A #GDBusConnection.
     988                 :             :  *
     989                 :             :  * Stops exporting @interface_ on @connection.
     990                 :             :  *
     991                 :             :  * To stop exporting on all connections the interface is exported on,
     992                 :             :  * use g_dbus_interface_skeleton_unexport().
     993                 :             :  *
     994                 :             :  * Since: 2.32
     995                 :             :  */
     996                 :             : void
     997                 :           0 : g_dbus_interface_skeleton_unexport_from_connection (GDBusInterfaceSkeleton *interface_,
     998                 :             :                                                     GDBusConnection        *connection)
     999                 :             : {
    1000                 :           0 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_));
    1001                 :           0 :   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
    1002                 :           0 :   g_return_if_fail (interface_->priv->connections != NULL);
    1003                 :             : 
    1004                 :           0 :   g_mutex_lock (&interface_->priv->lock);
    1005                 :             : 
    1006                 :           0 :   g_assert (interface_->priv->object_path != NULL);
    1007                 :           0 :   g_assert (interface_->priv->hooked_vtable != NULL);
    1008                 :             : 
    1009                 :           0 :   remove_connection_locked (interface_, connection);
    1010                 :             : 
    1011                 :             :   /* Reset the object path if we removed the last connection */
    1012                 :           0 :   if (interface_->priv->connections == NULL)
    1013                 :           0 :     set_object_path_locked (interface_, NULL);
    1014                 :             : 
    1015                 :           0 :   g_mutex_unlock (&interface_->priv->lock);
    1016                 :             : }
    1017                 :             : 
    1018                 :             : /* ---------------------------------------------------------------------------------------------------- */
        

Generated by: LCOV version 2.0-1