LCOV - code coverage report
Current view: top level - glib/gio - gdbusinterfaceskeleton.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 257 296 86.8 %
Date: 2024-03-26 05:16:46 Functions: 36 39 92.3 %
Branches: 62 86 72.1 %

           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   [ +  +  +  -  :       4048 : 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                 :         31 : g_dbus_interface_skeleton_finalize (GObject *object)
     100                 :            : {
     101                 :         31 :   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                 :         31 :   g_mutex_lock (&interface->priv->lock);
     105                 :            : 
     106                 :            :   /* unexport from all connections if we're exported anywhere */
     107         [ +  + ]:         33 :   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                 :         31 :   set_object_path_locked (interface, NULL);
     114                 :            : 
     115                 :         31 :   g_mutex_unlock (&interface->priv->lock);
     116                 :            : 
     117                 :         31 :   g_free (interface->priv->hooked_vtable);
     118                 :            : 
     119         [ -  + ]:         31 :   if (interface->priv->object != NULL)
     120                 :          0 :     g_object_remove_weak_pointer (G_OBJECT (interface->priv->object), (gpointer *) &interface->priv->object);
     121                 :            : 
     122                 :         31 :   g_mutex_clear (&interface->priv->lock);
     123                 :            : 
     124                 :         31 :   G_OBJECT_CLASS (g_dbus_interface_skeleton_parent_class)->finalize (object);
     125                 :         31 : }
     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                 :          6 : g_dbus_interface_skeleton_class_init (GDBusInterfaceSkeletonClass *klass)
     176                 :            : {
     177                 :            :   GObjectClass *gobject_class;
     178                 :            : 
     179                 :          6 :   gobject_class = G_OBJECT_CLASS (klass);
     180                 :          6 :   gobject_class->finalize     = g_dbus_interface_skeleton_finalize;
     181                 :          6 :   gobject_class->set_property = g_dbus_interface_skeleton_set_property;
     182                 :          6 :   gobject_class->get_property = g_dbus_interface_skeleton_get_property;
     183                 :            : 
     184                 :          6 :   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                 :          6 :   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                 :          6 :   signals[G_AUTHORIZE_METHOD_SIGNAL] =
     246                 :          6 :     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                 :          6 :   g_signal_set_va_marshaller (signals[G_AUTHORIZE_METHOD_SIGNAL],
     257                 :            :                               G_TYPE_FROM_CLASS (klass),
     258                 :            :                               _g_cclosure_marshal_BOOLEAN__OBJECTv);
     259                 :          6 : }
     260                 :            : 
     261                 :            : static void
     262                 :         53 : g_dbus_interface_skeleton_init (GDBusInterfaceSkeleton *interface)
     263                 :            : {
     264                 :         53 :   interface->priv = g_dbus_interface_skeleton_get_instance_private (interface);
     265                 :         53 :   g_mutex_init (&interface->priv->lock);
     266                 :         53 : }
     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                 :          3 : g_dbus_interface_skeleton_set_flags (GDBusInterfaceSkeleton      *interface_,
     299                 :            :                                      GDBusInterfaceSkeletonFlags  flags)
     300                 :            : {
     301                 :          3 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_));
     302                 :          3 :   g_mutex_lock (&interface_->priv->lock);
     303         [ +  - ]:          3 :   if (interface_->priv->flags != flags)
     304                 :            :     {
     305                 :          3 :       interface_->priv->flags = flags;
     306                 :          3 :       g_mutex_unlock (&interface_->priv->lock);
     307                 :          3 :       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                 :        230 : g_dbus_interface_skeleton_get_info (GDBusInterfaceSkeleton *interface_)
     328                 :            : {
     329                 :            :   GDBusInterfaceInfo *ret;
     330                 :        230 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     331                 :        230 :   ret = G_DBUS_INTERFACE_SKELETON_GET_CLASS (interface_)->get_info (interface_);
     332         [ -  + ]:        230 :   g_warn_if_fail (ret != NULL);
     333                 :        230 :   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                 :         90 : g_dbus_interface_skeleton_get_vtable (GDBusInterfaceSkeleton *interface_)
     350                 :            : {
     351                 :            :   GDBusInterfaceVTable *ret;
     352                 :         90 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     353                 :         90 :   ret = G_DBUS_INTERFACE_SKELETON_GET_CLASS (interface_)->get_vtable (interface_);
     354         [ -  + ]:         90 :   g_warn_if_fail (ret != NULL);
     355                 :         90 :   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                 :          6 : dbus_interface_interface_init (GDBusInterfaceIface *iface)
     450                 :            : {
     451                 :          6 :   iface->get_info    = _g_dbus_interface_skeleton_get_info;
     452                 :          6 :   iface->get_object  = g_dbus_interface_skeleton_get_object;
     453                 :          6 :   iface->dup_object  = g_dbus_interface_skeleton_dup_object;
     454                 :          6 :   iface->set_object  = g_dbus_interface_skeleton_set_object;
     455                 :          6 : }
     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                 :         42 : 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                 :         42 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface));
     586                 :         42 :   g_return_if_fail (method_call_func != NULL);
     587                 :         42 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     588                 :            : 
     589                 :         42 :   g_mutex_lock (&interface->priv->lock);
     590                 :         42 :   flags = interface->priv->flags;
     591                 :         42 :   object = interface->priv->object;
     592         [ +  + ]:         42 :   if (object != NULL)
     593                 :          9 :     g_object_ref (object);
     594                 :         42 :   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                 :         42 :   has_handlers = g_signal_has_handler_pending (interface,
     602                 :            :                                                signals[G_AUTHORIZE_METHOD_SIGNAL],
     603                 :            :                                                0,
     604                 :            :                                                TRUE);
     605                 :         42 :   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   [ +  +  -  + ]:         42 :   emit_authorized_signal = (has_handlers || !has_default_class_handler);
     609         [ +  + ]:         42 :   if (!emit_authorized_signal)
     610                 :            :     {
     611         [ -  + ]:         33 :       if (object != NULL)
     612                 :          0 :         emit_authorized_signal = _g_dbus_object_skeleton_has_authorize_method_handlers (G_DBUS_OBJECT_SKELETON (object));
     613                 :            :     }
     614                 :            : 
     615                 :         42 :   run_in_thread = (flags & G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
     616   [ +  +  +  + ]:         42 :   if (!emit_authorized_signal && !run_in_thread)
     617                 :            :     {
     618                 :         30 :       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         [ +  + ]:         42 :   if (object != NULL)
     646                 :          9 :     g_object_unref (object);
     647                 :            : }
     648                 :            : 
     649                 :            : static void
     650                 :         42 : 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                 :         42 :   GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (user_data);
     660                 :         42 :   g_dbus_interface_method_dispatch_helper (interface,
     661                 :         42 :                                            g_dbus_interface_skeleton_get_vtable (interface)->method_call,
     662                 :            :                                            invocation);
     663                 :         42 : }
     664                 :            : 
     665                 :            : /* ---------------------------------------------------------------------------------------------------- */
     666                 :            : 
     667                 :            : static ConnectionData *
     668                 :         57 : new_connection (GDBusConnection *connection,
     669                 :            :                 guint            registration_id)
     670                 :            : {
     671                 :            :   ConnectionData *data;
     672                 :            : 
     673                 :         57 :   data = g_slice_new0 (ConnectionData);
     674                 :         57 :   data->connection      = g_object_ref (connection);
     675                 :         57 :   data->registration_id = registration_id;
     676                 :            : 
     677                 :         57 :   return data;
     678                 :            : }
     679                 :            : 
     680                 :            : static void
     681                 :         57 : free_connection (ConnectionData *data)
     682                 :            : {
     683         [ +  - ]:         57 :   if (data != NULL)
     684                 :            :     {
     685                 :         57 :       g_object_unref (data->connection);
     686                 :         57 :       g_slice_free (ConnectionData, data);
     687                 :            :     }
     688                 :         57 : }
     689                 :            : 
     690                 :            : static gboolean
     691                 :         57 : add_connection_locked (GDBusInterfaceSkeleton *interface_,
     692                 :            :                        GDBusConnection        *connection,
     693                 :            :                        GError                **error)
     694                 :            : {
     695                 :            :   ConnectionData *data;
     696                 :            :   guint registration_id;
     697                 :         57 :   gboolean ret = FALSE;
     698                 :            : 
     699         [ +  + ]:         57 :   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                 :         44 :       interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
     710                 :         44 :       interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call;
     711                 :            :     }
     712                 :            : 
     713                 :        114 :   registration_id = g_dbus_connection_register_object (connection,
     714                 :         57 :                                                        interface_->priv->object_path,
     715                 :            :                                                        g_dbus_interface_skeleton_get_info (interface_),
     716                 :         57 :                                                        interface_->priv->hooked_vtable,
     717                 :            :                                                        interface_,
     718                 :            :                                                        NULL, /* user_data_free_func */
     719                 :            :                                                        error);
     720                 :            : 
     721         [ +  - ]:         57 :   if (registration_id > 0)
     722                 :            :     {
     723                 :         57 :       data = new_connection (connection, registration_id);
     724                 :         57 :       interface_->priv->connections = g_slist_append (interface_->priv->connections, data);
     725                 :         57 :       ret = TRUE;
     726                 :            :     }
     727                 :            : 
     728                 :         57 :   return ret;
     729                 :            : }
     730                 :            : 
     731                 :            : static void
     732                 :         57 : 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         [ +  - ]:         57 :   for (l = interface_->priv->connections; l != NULL; l = l->next)
     740                 :            :     {
     741                 :         57 :       data = l->data;
     742         [ +  - ]:         57 :       if (data->connection == connection)
     743                 :            :         {
     744         [ -  + ]:         57 :           g_warn_if_fail (g_dbus_connection_unregister_object (data->connection, data->registration_id));
     745                 :         57 :           free_connection (data);
     746                 :         57 :           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                 :         57 :           goto out;
     749                 :            :         }
     750                 :            :     }
     751                 :          0 :  out:
     752                 :            :   ;
     753                 :         57 : }
     754                 :            : 
     755                 :            : static void
     756                 :        143 : set_object_path_locked (GDBusInterfaceSkeleton *interface_,
     757                 :            :                         const gchar            *object_path)
     758                 :            : {
     759         [ +  + ]:        143 :   if (g_strcmp0 (interface_->priv->object_path, object_path) != 0)
     760                 :            :     {
     761                 :        112 :       g_free (interface_->priv->object_path);
     762                 :        224 :       interface_->priv->object_path = g_strdup (object_path);
     763                 :            :     }
     764                 :        143 : }
     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                 :         58 : g_dbus_interface_skeleton_get_connections (GDBusInterfaceSkeleton *interface_)
     816                 :            : {
     817                 :            :   GList           *connections;
     818                 :            :   GSList          *l;
     819                 :            :   ConnectionData  *data;
     820                 :            : 
     821                 :         58 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     822                 :            : 
     823                 :         58 :   g_mutex_lock (&interface_->priv->lock);
     824                 :         58 :   connections = NULL;
     825                 :            : 
     826         [ +  + ]:        118 :   for (l = interface_->priv->connections; l != NULL; l = l->next)
     827                 :            :     {
     828                 :         60 :       data        = l->data;
     829                 :         60 :       connections = g_list_prepend (connections,
     830                 :            :                                     /* Return a reference to each connection */
     831                 :         60 :                                     g_object_ref (data->connection));
     832                 :            :     }
     833                 :            : 
     834                 :         58 :   g_mutex_unlock (&interface_->priv->lock);
     835                 :            : 
     836                 :         58 :   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                 :        698 : g_dbus_interface_skeleton_get_object_path (GDBusInterfaceSkeleton *interface_)
     890                 :            : {
     891                 :            :   const gchar *ret;
     892                 :        698 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), NULL);
     893                 :        698 :   g_mutex_lock (&interface_->priv->lock);
     894                 :        698 :   ret = interface_->priv->object_path;
     895                 :        698 :   g_mutex_unlock (&interface_->priv->lock);
     896                 :        698 :   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                 :         57 : g_dbus_interface_skeleton_export (GDBusInterfaceSkeleton  *interface_,
     921                 :            :                                   GDBusConnection         *connection,
     922                 :            :                                   const gchar             *object_path,
     923                 :            :                                   GError                 **error)
     924                 :            : {
     925                 :         57 :   gboolean ret = FALSE;
     926                 :            : 
     927                 :         57 :   g_return_val_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_), FALSE);
     928                 :         57 :   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
     929                 :         57 :   g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
     930                 :         57 :   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                 :         57 :   g_return_val_if_fail (interface_->priv->object_path == NULL ||
     934                 :            :                         g_strcmp0 (interface_->priv->object_path, object_path) == 0, FALSE);
     935                 :            : 
     936                 :         57 :   g_mutex_lock (&interface_->priv->lock);
     937                 :            : 
     938                 :            :   /* Set the object path */
     939                 :         57 :   set_object_path_locked (interface_, object_path);
     940                 :            : 
     941                 :            :   /* Add the connection */
     942                 :         57 :   ret = add_connection_locked (interface_, connection, error);
     943                 :            : 
     944                 :         57 :   g_mutex_unlock (&interface_->priv->lock);
     945                 :         57 :   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                 :         55 : g_dbus_interface_skeleton_unexport (GDBusInterfaceSkeleton *interface_)
     961                 :            : {
     962                 :         55 :   g_return_if_fail (G_IS_DBUS_INTERFACE_SKELETON (interface_));
     963                 :         55 :   g_return_if_fail (interface_->priv->connections != NULL);
     964                 :            : 
     965                 :         55 :   g_mutex_lock (&interface_->priv->lock);
     966                 :            : 
     967                 :         55 :   g_assert (interface_->priv->object_path != NULL);
     968                 :         55 :   g_assert (interface_->priv->hooked_vtable != NULL);
     969                 :            : 
     970                 :            :   /* Remove all connections */
     971         [ +  + ]:        110 :   while (interface_->priv->connections != NULL)
     972                 :            :     {
     973                 :         55 :       ConnectionData *data = interface_->priv->connections->data;
     974                 :         55 :       remove_connection_locked (interface_, data->connection);
     975                 :            :     }
     976                 :            : 
     977                 :            :   /* Unset the object path since there are no connections left */
     978                 :         55 :   set_object_path_locked (interface_, NULL);
     979                 :            : 
     980                 :         55 :   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 1.14