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

Generated by: LCOV version 2.0-1