LCOV - code coverage report
Current view: top level - gio - gdbusobjectmanagerclient.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 77.6 % 509 395
Test Date: 2024-11-26 05:23:01 Functions: 84.6 % 39 33
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 "gcancellable.h"
      26                 :             : #include "gdbusobjectmanager.h"
      27                 :             : #include "gdbusobjectmanagerclient.h"
      28                 :             : #include "gdbusobject.h"
      29                 :             : #include "gdbusprivate.h"
      30                 :             : #include "gioenumtypes.h"
      31                 :             : #include "gioerror.h"
      32                 :             : #include "ginitable.h"
      33                 :             : #include "gasyncresult.h"
      34                 :             : #include "gasyncinitable.h"
      35                 :             : #include "gdbusconnection.h"
      36                 :             : #include "gdbusutils.h"
      37                 :             : #include "gdbusobject.h"
      38                 :             : #include "gdbusobjectproxy.h"
      39                 :             : #include "gdbusproxy.h"
      40                 :             : #include "gdbusinterface.h"
      41                 :             : 
      42                 :             : #include "glibintl.h"
      43                 :             : #include "gmarshal-internal.h"
      44                 :             : 
      45                 :             : /**
      46                 :             :  * GDBusObjectManagerClient:
      47                 :             :  *
      48                 :             :  * `GDBusObjectManagerClient` is used to create, monitor and delete object
      49                 :             :  * proxies for remote objects exported by a [class@Gio.DBusObjectManagerServer]
      50                 :             :  * (or any code implementing the
      51                 :             :  * [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
      52                 :             :  * interface).
      53                 :             :  *
      54                 :             :  * Once an instance of this type has been created, you can connect to
      55                 :             :  * the [signal@Gio.DBusObjectManager::object-added] and
      56                 :             :  * [signal@Gio.DBusObjectManager::object-removed signals] and inspect the
      57                 :             :  * [class@Gio.DBusObjectProxy] objects returned by
      58                 :             :  * [method@Gio.DBusObjectManager.get_objects].
      59                 :             :  *
      60                 :             :  * If the name for a `GDBusObjectManagerClient` is not owned by anyone at
      61                 :             :  * object construction time, the default behavior is to request the
      62                 :             :  * message bus to launch an owner for the name. This behavior can be
      63                 :             :  * disabled using the `G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START`
      64                 :             :  * flag. It’s also worth noting that this only works if the name of
      65                 :             :  * interest is activatable in the first place. E.g. in some cases it
      66                 :             :  * is not possible to launch an owner for the requested name. In this
      67                 :             :  * case, `GDBusObjectManagerClient` object construction still succeeds but
      68                 :             :  * there will be no object proxies
      69                 :             :  * (e.g. [method@Gio.DBusObjectManager.get_objects] returns the empty list) and
      70                 :             :  * the [property@Gio.DBusObjectManagerClient:name-owner] property is `NULL`.
      71                 :             :  *
      72                 :             :  * The owner of the requested name can come and go (for example
      73                 :             :  * consider a system service being restarted) – `GDBusObjectManagerClient`
      74                 :             :  * handles this case too; simply connect to the [signal@GObject.Object::notify]
      75                 :             :  * signal to watch for changes on the
      76                 :             :  * [property@Gio.DBusObjectManagerClient:name-owner] property. When the name
      77                 :             :  * owner vanishes, the behavior is that
      78                 :             :  * [property@Gio.DBusObjectManagerClient:name-owner] is set to `NULL` (this
      79                 :             :  * includes emission of the [signal@GObject.Object::notify] signal) and then
      80                 :             :  * [signal@Gio.DBusObjectManager::object-removed] signals are synthesized
      81                 :             :  * for all currently existing object proxies. Since
      82                 :             :  * [property@Gio.DBusObjectManagerClient:name-owner] is `NULL` when this
      83                 :             :  * happens, you can use this information to disambiguate a synthesized signal
      84                 :             :  * from a genuine signal caused by object removal on the remote
      85                 :             :  * [iface@Gio.DBusObjectManager]. Similarly, when a new name owner appears,
      86                 :             :  * [signal@Gio.DBusObjectManager::object-added] signals are synthesized
      87                 :             :  * while [property@Gio.DBusObjectManagerClient:name-owner] is still `NULL`. Only
      88                 :             :  * when all object proxies have been added, the
      89                 :             :  * [property@Gio.DBusObjectManagerClient:name-owner] is set to the new name
      90                 :             :  * owner (this includes emission of the [signal@GObject.Object::notify] signal).
      91                 :             :  * Furthermore, you are guaranteed that
      92                 :             :  * [property@Gio.DBusObjectManagerClient:name-owner] will alternate between a
      93                 :             :  * name owner (e.g. `:1.42`) and `NULL` even in the case where
      94                 :             :  * the name of interest is atomically replaced
      95                 :             :  *
      96                 :             :  * Ultimately, `GDBusObjectManagerClient` is used to obtain
      97                 :             :  * [class@Gio.DBusProxy] instances. All signals (including the
      98                 :             :  * `org.freedesktop.DBus.Properties::PropertiesChanged` signal)
      99                 :             :  * delivered to [class@Gio.DBusProxy] instances are guaranteed to originate
     100                 :             :  * from the name owner. This guarantee along with the behavior
     101                 :             :  * described above, means that certain race conditions including the
     102                 :             :  * “half the proxy is from the old owner and the other half is from
     103                 :             :  * the new owner” problem cannot happen.
     104                 :             :  *
     105                 :             :  * To avoid having the application connect to signals on the returned
     106                 :             :  * [class@Gio.DBusObjectProxy] and [class@Gio.DBusProxy] objects, the
     107                 :             :  * [signal@Gio.DBusObject::interface-added],
     108                 :             :  * [signal@Gio.DBusObject::interface-removed],
     109                 :             :  * [signal@Gio.DBusProxy::g-properties-changed] and
     110                 :             :  * [signal@Gio.DBusProxy::g-signal] signals
     111                 :             :  * are also emitted on the `GDBusObjectManagerClient` instance managing these
     112                 :             :  * objects. The signals emitted are
     113                 :             :  * [signal@Gio.DBusObjectManager::interface-added],
     114                 :             :  * [signal@Gio.DBusObjectManager::interface-removed],
     115                 :             :  * [signal@Gio.DBusObjectManagerClient::interface-proxy-properties-changed] and
     116                 :             :  * [signal@Gio.DBusObjectManagerClient::interface-proxy-signal].
     117                 :             :  *
     118                 :             :  * Note that all callbacks and signals are emitted in the
     119                 :             :  * thread-default main context (see
     120                 :             :  * [method@GLib.MainContext.push_thread_default]) that the
     121                 :             :  * `GDBusObjectManagerClient` object was constructed in. Additionally, the
     122                 :             :  * [class@Gio.DBusObjectProxy] and [class@Gio.DBusProxy] objects
     123                 :             :  * originating from the `GDBusObjectManagerClient` object will be created in
     124                 :             :  * the same context and, consequently, will deliver signals in the
     125                 :             :  * same main loop.
     126                 :             :  *
     127                 :             :  * Since: 2.30
     128                 :             :  */
     129                 :             : 
     130                 :             : struct _GDBusObjectManagerClientPrivate
     131                 :             : {
     132                 :             :   GMutex lock;
     133                 :             : 
     134                 :             :   GBusType bus_type;
     135                 :             :   GDBusConnection *connection;
     136                 :             :   gchar *object_path;
     137                 :             :   gchar *name;
     138                 :             :   gchar *name_owner;
     139                 :             :   GDBusObjectManagerClientFlags flags;
     140                 :             : 
     141                 :             :   GDBusProxy *control_proxy;
     142                 :             : 
     143                 :             :   GHashTable *map_object_path_to_object_proxy;
     144                 :             : 
     145                 :             :   guint signal_subscription_id;
     146                 :             :   gchar *match_rule;
     147                 :             : 
     148                 :             :   GDBusProxyTypeFunc get_proxy_type_func;
     149                 :             :   gpointer get_proxy_type_user_data;
     150                 :             :   GDestroyNotify get_proxy_type_destroy_notify;
     151                 :             : 
     152                 :             :   gulong name_owner_signal_id;
     153                 :             :   gulong signal_signal_id;
     154                 :             :   GCancellable *cancel;
     155                 :             : };
     156                 :             : 
     157                 :             : enum
     158                 :             : {
     159                 :             :   PROP_0,
     160                 :             :   PROP_BUS_TYPE,
     161                 :             :   PROP_CONNECTION,
     162                 :             :   PROP_FLAGS,
     163                 :             :   PROP_OBJECT_PATH,
     164                 :             :   PROP_NAME,
     165                 :             :   PROP_NAME_OWNER,
     166                 :             :   PROP_GET_PROXY_TYPE_FUNC,
     167                 :             :   PROP_GET_PROXY_TYPE_USER_DATA,
     168                 :             :   PROP_GET_PROXY_TYPE_DESTROY_NOTIFY
     169                 :             : };
     170                 :             : 
     171                 :             : enum
     172                 :             : {
     173                 :             :   INTERFACE_PROXY_SIGNAL_SIGNAL,
     174                 :             :   INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL,
     175                 :             :   LAST_SIGNAL
     176                 :             : };
     177                 :             : 
     178                 :             : static guint signals[LAST_SIGNAL] = { 0 };
     179                 :             : 
     180                 :             : static void initable_iface_init       (GInitableIface *initable_iface);
     181                 :             : static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
     182                 :             : static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
     183                 :             : 
     184                 :         445 : G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerClient, g_dbus_object_manager_client, G_TYPE_OBJECT,
     185                 :             :                          G_ADD_PRIVATE (GDBusObjectManagerClient)
     186                 :             :                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
     187                 :             :                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
     188                 :             :                          G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init))
     189                 :             : 
     190                 :             : static void maybe_unsubscribe_signals (GDBusObjectManagerClient *manager);
     191                 :             : 
     192                 :             : static void on_control_proxy_g_signal (GDBusProxy   *proxy,
     193                 :             :                                        const gchar  *sender_name,
     194                 :             :                                        const gchar  *signal_name,
     195                 :             :                                        GVariant     *parameters,
     196                 :             :                                        gpointer      user_data);
     197                 :             : 
     198                 :             : static void process_get_all_result (GDBusObjectManagerClient *manager,
     199                 :             :                                     GVariant          *value,
     200                 :             :                                     const gchar       *name_owner);
     201                 :             : 
     202                 :             : static void
     203                 :           8 : g_dbus_object_manager_client_dispose (GObject *object)
     204                 :             : {
     205                 :           8 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object);
     206                 :             : 
     207                 :           8 :   if (manager->priv->cancel != NULL)
     208                 :             :     {
     209                 :           8 :       g_cancellable_cancel (manager->priv->cancel);
     210                 :           8 :       g_clear_object (&manager->priv->cancel);
     211                 :             :     }
     212                 :             : 
     213                 :           8 :   G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->dispose (object);
     214                 :           8 : }
     215                 :             : 
     216                 :             : static void
     217                 :           8 : g_dbus_object_manager_client_finalize (GObject *object)
     218                 :             : {
     219                 :           8 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object);
     220                 :             : 
     221                 :           8 :   maybe_unsubscribe_signals (manager);
     222                 :             : 
     223                 :           8 :   g_hash_table_unref (manager->priv->map_object_path_to_object_proxy);
     224                 :             : 
     225                 :           8 :   if (manager->priv->control_proxy != NULL && manager->priv->signal_signal_id != 0)
     226                 :           5 :     g_signal_handler_disconnect (manager->priv->control_proxy,
     227                 :           5 :                                  manager->priv->signal_signal_id);
     228                 :           8 :   manager->priv->signal_signal_id = 0;
     229                 :             : 
     230                 :           8 :   if (manager->priv->control_proxy != NULL && manager->priv->name_owner_signal_id != 0)
     231                 :           5 :     g_signal_handler_disconnect (manager->priv->control_proxy,
     232                 :           5 :                                  manager->priv->name_owner_signal_id);
     233                 :           8 :   manager->priv->name_owner_signal_id = 0;
     234                 :             : 
     235                 :           8 :   g_clear_object (&manager->priv->control_proxy);
     236                 :             : 
     237                 :           8 :   if (manager->priv->connection != NULL)
     238                 :           8 :     g_object_unref (manager->priv->connection);
     239                 :           8 :   g_free (manager->priv->object_path);
     240                 :           8 :   g_free (manager->priv->name);
     241                 :           8 :   g_free (manager->priv->name_owner);
     242                 :             : 
     243                 :           8 :   if (manager->priv->get_proxy_type_destroy_notify != NULL)
     244                 :           0 :     manager->priv->get_proxy_type_destroy_notify (manager->priv->get_proxy_type_user_data);
     245                 :             : 
     246                 :           8 :   g_mutex_clear (&manager->priv->lock);
     247                 :             : 
     248                 :           8 :   if (G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize != NULL)
     249                 :           8 :     G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize (object);
     250                 :           8 : }
     251                 :             : 
     252                 :             : static void
     253                 :          15 : g_dbus_object_manager_client_get_property (GObject    *_object,
     254                 :             :                                            guint       prop_id,
     255                 :             :                                            GValue     *value,
     256                 :             :                                            GParamSpec *pspec)
     257                 :             : {
     258                 :          15 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
     259                 :             : 
     260                 :          15 :   switch (prop_id)
     261                 :             :     {
     262                 :           3 :     case PROP_CONNECTION:
     263                 :           3 :       g_value_set_object (value, g_dbus_object_manager_client_get_connection (manager));
     264                 :           3 :       break;
     265                 :             : 
     266                 :           3 :     case PROP_OBJECT_PATH:
     267                 :           3 :       g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
     268                 :           3 :       break;
     269                 :             : 
     270                 :           3 :     case PROP_NAME:
     271                 :           3 :       g_value_set_string (value, g_dbus_object_manager_client_get_name (manager));
     272                 :           3 :       break;
     273                 :             : 
     274                 :           3 :     case PROP_FLAGS:
     275                 :           3 :       g_value_set_flags (value, g_dbus_object_manager_client_get_flags (manager));
     276                 :           3 :       break;
     277                 :             : 
     278                 :           3 :     case PROP_NAME_OWNER:
     279                 :           3 :       g_value_take_string (value, g_dbus_object_manager_client_get_name_owner (manager));
     280                 :           3 :       break;
     281                 :             : 
     282                 :           0 :     default:
     283                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (manager, prop_id, pspec);
     284                 :           0 :       break;
     285                 :             :     }
     286                 :          15 : }
     287                 :             : 
     288                 :             : static void
     289                 :          64 : g_dbus_object_manager_client_set_property (GObject       *_object,
     290                 :             :                                            guint          prop_id,
     291                 :             :                                            const GValue  *value,
     292                 :             :                                            GParamSpec    *pspec)
     293                 :             : {
     294                 :          64 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
     295                 :             :   const gchar *name;
     296                 :             : 
     297                 :          64 :   switch (prop_id)
     298                 :             :     {
     299                 :           8 :     case PROP_BUS_TYPE:
     300                 :           8 :       manager->priv->bus_type = g_value_get_enum (value);
     301                 :           8 :       break;
     302                 :             : 
     303                 :           8 :     case PROP_CONNECTION:
     304                 :           8 :       if (g_value_get_object (value) != NULL)
     305                 :             :         {
     306                 :           8 :           g_assert (manager->priv->connection == NULL);
     307                 :           8 :           g_assert (G_IS_DBUS_CONNECTION (g_value_get_object (value)));
     308                 :           8 :           manager->priv->connection = g_value_dup_object (value);
     309                 :             :         }
     310                 :           8 :       break;
     311                 :             : 
     312                 :           8 :     case PROP_OBJECT_PATH:
     313                 :           8 :       g_assert (manager->priv->object_path == NULL);
     314                 :           8 :       g_assert (g_variant_is_object_path (g_value_get_string (value)));
     315                 :           8 :       manager->priv->object_path = g_value_dup_string (value);
     316                 :           8 :       break;
     317                 :             : 
     318                 :           8 :     case PROP_NAME:
     319                 :           8 :       g_assert (manager->priv->name == NULL);
     320                 :           8 :       name = g_value_get_string (value);
     321                 :           8 :       g_assert (name == NULL || g_dbus_is_name (name));
     322                 :           8 :       manager->priv->name = g_strdup (name);
     323                 :           8 :       break;
     324                 :             : 
     325                 :           8 :     case PROP_FLAGS:
     326                 :           8 :       manager->priv->flags = g_value_get_flags (value);
     327                 :           8 :       break;
     328                 :             : 
     329                 :           8 :     case PROP_GET_PROXY_TYPE_FUNC:
     330                 :           8 :       manager->priv->get_proxy_type_func = g_value_get_pointer (value);
     331                 :           8 :       break;
     332                 :             : 
     333                 :           8 :     case PROP_GET_PROXY_TYPE_USER_DATA:
     334                 :           8 :       manager->priv->get_proxy_type_user_data = g_value_get_pointer (value);
     335                 :           8 :       break;
     336                 :             : 
     337                 :           8 :     case PROP_GET_PROXY_TYPE_DESTROY_NOTIFY:
     338                 :           8 :       manager->priv->get_proxy_type_destroy_notify = g_value_get_pointer (value);
     339                 :           8 :       break;
     340                 :             : 
     341                 :           0 :     default:
     342                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (manager, prop_id, pspec);
     343                 :           0 :       break;
     344                 :             :     }
     345                 :          64 : }
     346                 :             : 
     347                 :             : static void
     348                 :           5 : g_dbus_object_manager_client_class_init (GDBusObjectManagerClientClass *klass)
     349                 :             : {
     350                 :           5 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     351                 :             : 
     352                 :           5 :   gobject_class->dispose      = g_dbus_object_manager_client_dispose;
     353                 :           5 :   gobject_class->finalize     = g_dbus_object_manager_client_finalize;
     354                 :           5 :   gobject_class->set_property = g_dbus_object_manager_client_set_property;
     355                 :           5 :   gobject_class->get_property = g_dbus_object_manager_client_get_property;
     356                 :             : 
     357                 :             :   /**
     358                 :             :    * GDBusObjectManagerClient:connection:
     359                 :             :    *
     360                 :             :    * The #GDBusConnection to use.
     361                 :             :    *
     362                 :             :    * Since: 2.30
     363                 :             :    */
     364                 :           5 :   g_object_class_install_property (gobject_class,
     365                 :             :                                    PROP_CONNECTION,
     366                 :             :                                    g_param_spec_object ("connection", NULL, NULL,
     367                 :             :                                                         G_TYPE_DBUS_CONNECTION,
     368                 :             :                                                         G_PARAM_READABLE |
     369                 :             :                                                         G_PARAM_WRITABLE |
     370                 :             :                                                         G_PARAM_CONSTRUCT_ONLY |
     371                 :             :                                                         G_PARAM_STATIC_STRINGS));
     372                 :             : 
     373                 :             :   /**
     374                 :             :    * GDBusObjectManagerClient:bus-type:
     375                 :             :    *
     376                 :             :    * If this property is not %G_BUS_TYPE_NONE, then
     377                 :             :    * #GDBusObjectManagerClient:connection must be %NULL and will be set to the
     378                 :             :    * #GDBusConnection obtained by calling g_bus_get() with the value
     379                 :             :    * of this property.
     380                 :             :    *
     381                 :             :    * Since: 2.30
     382                 :             :    */
     383                 :           5 :   g_object_class_install_property (gobject_class,
     384                 :             :                                    PROP_BUS_TYPE,
     385                 :             :                                    g_param_spec_enum ("bus-type", NULL, NULL,
     386                 :             :                                                       G_TYPE_BUS_TYPE,
     387                 :             :                                                       G_BUS_TYPE_NONE,
     388                 :             :                                                       G_PARAM_WRITABLE |
     389                 :             :                                                       G_PARAM_CONSTRUCT_ONLY |
     390                 :             :                                                       G_PARAM_STATIC_NAME |
     391                 :             :                                                       G_PARAM_STATIC_BLURB |
     392                 :             :                                                       G_PARAM_STATIC_NICK));
     393                 :             : 
     394                 :             :   /**
     395                 :             :    * GDBusObjectManagerClient:flags:
     396                 :             :    *
     397                 :             :    * Flags from the #GDBusObjectManagerClientFlags enumeration.
     398                 :             :    *
     399                 :             :    * Since: 2.30
     400                 :             :    */
     401                 :           5 :   g_object_class_install_property (gobject_class,
     402                 :             :                                    PROP_FLAGS,
     403                 :             :                                    g_param_spec_flags ("flags", NULL, NULL,
     404                 :             :                                                        G_TYPE_DBUS_OBJECT_MANAGER_CLIENT_FLAGS,
     405                 :             :                                                        G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
     406                 :             :                                                        G_PARAM_READABLE |
     407                 :             :                                                        G_PARAM_WRITABLE |
     408                 :             :                                                        G_PARAM_CONSTRUCT_ONLY |
     409                 :             :                                                        G_PARAM_STATIC_NAME |
     410                 :             :                                                        G_PARAM_STATIC_BLURB |
     411                 :             :                                                        G_PARAM_STATIC_NICK));
     412                 :             : 
     413                 :             :   /**
     414                 :             :    * GDBusObjectManagerClient:object-path:
     415                 :             :    *
     416                 :             :    * The object path the manager is for.
     417                 :             :    *
     418                 :             :    * Since: 2.30
     419                 :             :    */
     420                 :           5 :   g_object_class_install_property (gobject_class,
     421                 :             :                                    PROP_OBJECT_PATH,
     422                 :             :                                    g_param_spec_string ("object-path", NULL, NULL,
     423                 :             :                                                         NULL,
     424                 :             :                                                         G_PARAM_READABLE |
     425                 :             :                                                         G_PARAM_WRITABLE |
     426                 :             :                                                         G_PARAM_CONSTRUCT_ONLY |
     427                 :             :                                                         G_PARAM_STATIC_STRINGS));
     428                 :             : 
     429                 :             :   /**
     430                 :             :    * GDBusObjectManagerClient:name:
     431                 :             :    *
     432                 :             :    * The well-known name or unique name that the manager is for.
     433                 :             :    *
     434                 :             :    * Since: 2.30
     435                 :             :    */
     436                 :           5 :   g_object_class_install_property (gobject_class,
     437                 :             :                                    PROP_NAME,
     438                 :             :                                    g_param_spec_string ("name", NULL, NULL,
     439                 :             :                                                         NULL,
     440                 :             :                                                         G_PARAM_READABLE |
     441                 :             :                                                         G_PARAM_WRITABLE |
     442                 :             :                                                         G_PARAM_CONSTRUCT_ONLY |
     443                 :             :                                                         G_PARAM_STATIC_STRINGS));
     444                 :             : 
     445                 :             :   /**
     446                 :             :    * GDBusObjectManagerClient:name-owner:
     447                 :             :    *
     448                 :             :    * The unique name that owns #GDBusObjectManagerClient:name or %NULL if
     449                 :             :    * no-one is currently owning the name. Connect to the
     450                 :             :    * #GObject::notify signal to track changes to this property.
     451                 :             :    *
     452                 :             :    * Since: 2.30
     453                 :             :    */
     454                 :           5 :   g_object_class_install_property (gobject_class,
     455                 :             :                                    PROP_NAME_OWNER,
     456                 :             :                                    g_param_spec_string ("name-owner", NULL, NULL,
     457                 :             :                                                         NULL,
     458                 :             :                                                         G_PARAM_READABLE |
     459                 :             :                                                         G_PARAM_STATIC_STRINGS));
     460                 :             : 
     461                 :             :   /**
     462                 :             :    * GDBusObjectManagerClient:get-proxy-type-func:
     463                 :             :    *
     464                 :             :    * The #GDBusProxyTypeFunc to use when determining what #GType to
     465                 :             :    * use for interface proxies or %NULL.
     466                 :             :    *
     467                 :             :    * Since: 2.30
     468                 :             :    */
     469                 :           5 :   g_object_class_install_property (gobject_class,
     470                 :             :                                    PROP_GET_PROXY_TYPE_FUNC,
     471                 :             :                                    g_param_spec_pointer ("get-proxy-type-func", NULL, NULL,
     472                 :             :                                                          G_PARAM_READABLE |
     473                 :             :                                                          G_PARAM_WRITABLE |
     474                 :             :                                                          G_PARAM_CONSTRUCT_ONLY |
     475                 :             :                                                          G_PARAM_STATIC_STRINGS));
     476                 :             : 
     477                 :             :   /**
     478                 :             :    * GDBusObjectManagerClient:get-proxy-type-user-data:
     479                 :             :    *
     480                 :             :    * The #gpointer user_data to pass to #GDBusObjectManagerClient:get-proxy-type-func.
     481                 :             :    *
     482                 :             :    * Since: 2.30
     483                 :             :    */
     484                 :           5 :   g_object_class_install_property (gobject_class,
     485                 :             :                                    PROP_GET_PROXY_TYPE_USER_DATA,
     486                 :             :                                    g_param_spec_pointer ("get-proxy-type-user-data", NULL, NULL,
     487                 :             :                                                          G_PARAM_READABLE |
     488                 :             :                                                          G_PARAM_WRITABLE |
     489                 :             :                                                          G_PARAM_CONSTRUCT_ONLY |
     490                 :             :                                                          G_PARAM_STATIC_STRINGS));
     491                 :             : 
     492                 :             :   /**
     493                 :             :    * GDBusObjectManagerClient:get-proxy-type-destroy-notify:
     494                 :             :    *
     495                 :             :    * A #GDestroyNotify for the #gpointer user_data in #GDBusObjectManagerClient:get-proxy-type-user-data.
     496                 :             :    *
     497                 :             :    * Since: 2.30
     498                 :             :    */
     499                 :           5 :   g_object_class_install_property (gobject_class,
     500                 :             :                                    PROP_GET_PROXY_TYPE_DESTROY_NOTIFY,
     501                 :             :                                    g_param_spec_pointer ("get-proxy-type-destroy-notify", NULL, NULL,
     502                 :             :                                                          G_PARAM_READABLE |
     503                 :             :                                                          G_PARAM_WRITABLE |
     504                 :             :                                                          G_PARAM_CONSTRUCT_ONLY |
     505                 :             :                                                          G_PARAM_STATIC_STRINGS));
     506                 :             : 
     507                 :             :   /**
     508                 :             :    * GDBusObjectManagerClient::interface-proxy-signal:
     509                 :             :    * @manager: The #GDBusObjectManagerClient emitting the signal.
     510                 :             :    * @object_proxy: The #GDBusObjectProxy on which an interface is emitting a D-Bus signal.
     511                 :             :    * @interface_proxy: The #GDBusProxy that is emitting a D-Bus signal.
     512                 :             :    * @sender_name: The sender of the signal or NULL if the connection is not a bus connection.
     513                 :             :    * @signal_name: The signal name.
     514                 :             :    * @parameters: A #GVariant tuple with parameters for the signal.
     515                 :             :    *
     516                 :             :    * Emitted when a D-Bus signal is received on @interface_proxy.
     517                 :             :    *
     518                 :             :    * This signal exists purely as a convenience to avoid having to
     519                 :             :    * connect signals to all interface proxies managed by @manager.
     520                 :             :    *
     521                 :             :    * This signal is emitted in the
     522                 :             :    * [thread-default main context][g-main-context-push-thread-default]
     523                 :             :    * that @manager was constructed in.
     524                 :             :    *
     525                 :             :    * Since: 2.30
     526                 :             :    */
     527                 :           5 :   signals[INTERFACE_PROXY_SIGNAL_SIGNAL] =
     528                 :           5 :     g_signal_new (I_("interface-proxy-signal"),
     529                 :             :                   G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
     530                 :             :                   G_SIGNAL_RUN_LAST,
     531                 :             :                   G_STRUCT_OFFSET (GDBusObjectManagerClientClass, interface_proxy_signal),
     532                 :             :                   NULL,
     533                 :             :                   NULL,
     534                 :             :                   _g_cclosure_marshal_VOID__OBJECT_OBJECT_STRING_STRING_VARIANT,
     535                 :             :                   G_TYPE_NONE,
     536                 :             :                   5,
     537                 :             :                   G_TYPE_DBUS_OBJECT_PROXY,
     538                 :             :                   G_TYPE_DBUS_PROXY,
     539                 :             :                   G_TYPE_STRING,
     540                 :             :                   G_TYPE_STRING,
     541                 :             :                   G_TYPE_VARIANT);
     542                 :           5 :   g_signal_set_va_marshaller (signals[INTERFACE_PROXY_SIGNAL_SIGNAL],
     543                 :             :                               G_TYPE_FROM_CLASS (klass),
     544                 :             :                               _g_cclosure_marshal_VOID__OBJECT_OBJECT_STRING_STRING_VARIANTv);
     545                 :             : 
     546                 :             :   /**
     547                 :             :    * GDBusObjectManagerClient::interface-proxy-properties-changed:
     548                 :             :    * @manager: The #GDBusObjectManagerClient emitting the signal.
     549                 :             :    * @object_proxy: The #GDBusObjectProxy on which an interface has properties that are changing.
     550                 :             :    * @interface_proxy: The #GDBusProxy that has properties that are changing.
     551                 :             :    * @changed_properties: A #GVariant containing the properties that changed (type: `a{sv}`).
     552                 :             :    * @invalidated_properties: (array zero-terminated=1) (element-type utf8): A %NULL terminated
     553                 :             :    *   array of properties that were invalidated.
     554                 :             :    *
     555                 :             :    * Emitted when one or more D-Bus properties on proxy changes. The
     556                 :             :    * local cache has already been updated when this signal fires. Note
     557                 :             :    * that both @changed_properties and @invalidated_properties are
     558                 :             :    * guaranteed to never be %NULL (either may be empty though).
     559                 :             :    *
     560                 :             :    * This signal exists purely as a convenience to avoid having to
     561                 :             :    * connect signals to all interface proxies managed by @manager.
     562                 :             :    *
     563                 :             :    * This signal is emitted in the
     564                 :             :    * [thread-default main context][g-main-context-push-thread-default]
     565                 :             :    * that @manager was constructed in.
     566                 :             :    *
     567                 :             :    * Since: 2.30
     568                 :             :    */
     569                 :           5 :   signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL] =
     570                 :           5 :     g_signal_new (I_("interface-proxy-properties-changed"),
     571                 :             :                   G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
     572                 :             :                   G_SIGNAL_RUN_LAST,
     573                 :             :                   G_STRUCT_OFFSET (GDBusObjectManagerClientClass, interface_proxy_properties_changed),
     574                 :             :                   NULL,
     575                 :             :                   NULL,
     576                 :             :                   _g_cclosure_marshal_VOID__OBJECT_OBJECT_VARIANT_BOXED,
     577                 :             :                   G_TYPE_NONE,
     578                 :             :                   4,
     579                 :             :                   G_TYPE_DBUS_OBJECT_PROXY,
     580                 :             :                   G_TYPE_DBUS_PROXY,
     581                 :             :                   G_TYPE_VARIANT,
     582                 :             :                   G_TYPE_STRV);
     583                 :           5 :   g_signal_set_va_marshaller (signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL],
     584                 :             :                               G_TYPE_FROM_CLASS (klass),
     585                 :             :                               _g_cclosure_marshal_VOID__OBJECT_OBJECT_VARIANT_BOXEDv);
     586                 :           5 : }
     587                 :             : 
     588                 :             : static void
     589                 :           8 : g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager)
     590                 :             : {
     591                 :           8 :   manager->priv = g_dbus_object_manager_client_get_instance_private (manager);
     592                 :           8 :   g_mutex_init (&manager->priv->lock);
     593                 :           8 :   manager->priv->map_object_path_to_object_proxy = g_hash_table_new_full (g_str_hash,
     594                 :             :                                                                           g_str_equal,
     595                 :             :                                                                           g_free,
     596                 :             :                                                                           (GDestroyNotify) g_object_unref);
     597                 :           8 :   manager->priv->cancel = g_cancellable_new ();
     598                 :           8 : }
     599                 :             : 
     600                 :             : /* ---------------------------------------------------------------------------------------------------- */
     601                 :             : 
     602                 :             : /**
     603                 :             :  * g_dbus_object_manager_client_new_sync:
     604                 :             :  * @connection: A #GDBusConnection.
     605                 :             :  * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
     606                 :             :  * @name: (nullable): The owner of the control object (unique or well-known name), or %NULL when not using a message bus connection.
     607                 :             :  * @object_path: The object path of the control object.
     608                 :             :  * @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
     609                 :             :  * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
     610                 :             :  * @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
     611                 :             :  * @cancellable: (nullable): A #GCancellable or %NULL
     612                 :             :  * @error: Return location for error or %NULL.
     613                 :             :  *
     614                 :             :  * Creates a new #GDBusObjectManagerClient object.
     615                 :             :  *
     616                 :             :  * This is a synchronous failable constructor - the calling thread is
     617                 :             :  * blocked until a reply is received. See g_dbus_object_manager_client_new()
     618                 :             :  * for the asynchronous version.
     619                 :             :  *
     620                 :             :  * Returns: (transfer full) (type GDBusObjectManagerClient): A
     621                 :             :  *   #GDBusObjectManagerClient object or %NULL if @error is set. Free
     622                 :             :  *   with g_object_unref().
     623                 :             :  *
     624                 :             :  * Since: 2.30
     625                 :             :  */
     626                 :             : GDBusObjectManager *
     627                 :           0 : g_dbus_object_manager_client_new_sync (GDBusConnection               *connection,
     628                 :             :                                        GDBusObjectManagerClientFlags  flags,
     629                 :             :                                        const gchar                   *name,
     630                 :             :                                        const gchar                   *object_path,
     631                 :             :                                        GDBusProxyTypeFunc             get_proxy_type_func,
     632                 :             :                                        gpointer                       get_proxy_type_user_data,
     633                 :             :                                        GDestroyNotify                 get_proxy_type_destroy_notify,
     634                 :             :                                        GCancellable                  *cancellable,
     635                 :             :                                        GError                       **error)
     636                 :             : {
     637                 :             :   GInitable *initable;
     638                 :             : 
     639                 :           0 :   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
     640                 :           0 :   g_return_val_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
     641                 :             :                         g_dbus_is_name (name), NULL);
     642                 :           0 :   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
     643                 :           0 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     644                 :             : 
     645                 :           0 :   initable = g_initable_new (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
     646                 :             :                              cancellable,
     647                 :             :                              error,
     648                 :             :                              "connection", connection,
     649                 :             :                              "flags", flags,
     650                 :             :                              "name", name,
     651                 :             :                              "object-path", object_path,
     652                 :             :                              "get-proxy-type-func", get_proxy_type_func,
     653                 :             :                              "get-proxy-type-user-data", get_proxy_type_user_data,
     654                 :             :                              "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
     655                 :             :                              NULL);
     656                 :           0 :   if (initable != NULL)
     657                 :           0 :     return G_DBUS_OBJECT_MANAGER (initable);
     658                 :             :   else
     659                 :           0 :     return NULL;
     660                 :             : }
     661                 :             : 
     662                 :             : /**
     663                 :             :  * g_dbus_object_manager_client_new:
     664                 :             :  * @connection: A #GDBusConnection.
     665                 :             :  * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
     666                 :             :  * @name: The owner of the control object (unique or well-known name).
     667                 :             :  * @object_path: The object path of the control object.
     668                 :             :  * @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
     669                 :             :  * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
     670                 :             :  * @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
     671                 :             :  * @cancellable: (nullable): A #GCancellable or %NULL
     672                 :             :  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
     673                 :             :  * @user_data: The data to pass to @callback.
     674                 :             :  *
     675                 :             :  * Asynchronously creates a new #GDBusObjectManagerClient object.
     676                 :             :  *
     677                 :             :  * This is an asynchronous failable constructor. When the result is
     678                 :             :  * ready, @callback will be invoked in the
     679                 :             :  * [thread-default main context][g-main-context-push-thread-default]
     680                 :             :  * of the thread you are calling this method from. You can
     681                 :             :  * then call g_dbus_object_manager_client_new_finish() to get the result. See
     682                 :             :  * g_dbus_object_manager_client_new_sync() for the synchronous version.
     683                 :             :  *
     684                 :             :  * Since: 2.30
     685                 :             :  */
     686                 :             : void
     687                 :           2 : g_dbus_object_manager_client_new (GDBusConnection               *connection,
     688                 :             :                                   GDBusObjectManagerClientFlags  flags,
     689                 :             :                                   const gchar                   *name,
     690                 :             :                                   const gchar                   *object_path,
     691                 :             :                                   GDBusProxyTypeFunc             get_proxy_type_func,
     692                 :             :                                   gpointer                       get_proxy_type_user_data,
     693                 :             :                                   GDestroyNotify                 get_proxy_type_destroy_notify,
     694                 :             :                                   GCancellable                  *cancellable,
     695                 :             :                                   GAsyncReadyCallback            callback,
     696                 :             :                                   gpointer                       user_data)
     697                 :             : {
     698                 :           2 :   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
     699                 :           2 :   g_return_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
     700                 :             :                         g_dbus_is_name (name));
     701                 :           2 :   g_return_if_fail (g_variant_is_object_path (object_path));
     702                 :             : 
     703                 :           2 :   g_async_initable_new_async (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
     704                 :             :                               G_PRIORITY_DEFAULT,
     705                 :             :                               cancellable,
     706                 :             :                               callback,
     707                 :             :                               user_data,
     708                 :             :                               "connection", connection,
     709                 :             :                               "flags", flags,
     710                 :             :                               "name", name,
     711                 :             :                               "object-path", object_path,
     712                 :             :                               "get-proxy-type-func", get_proxy_type_func,
     713                 :             :                               "get-proxy-type-user-data", get_proxy_type_user_data,
     714                 :             :                               "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
     715                 :             :                               NULL);
     716                 :             : }
     717                 :             : 
     718                 :             : /**
     719                 :             :  * g_dbus_object_manager_client_new_finish:
     720                 :             :  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_object_manager_client_new().
     721                 :             :  * @error: Return location for error or %NULL.
     722                 :             :  *
     723                 :             :  * Finishes an operation started with g_dbus_object_manager_client_new().
     724                 :             :  *
     725                 :             :  * Returns: (transfer full) (type GDBusObjectManagerClient): A
     726                 :             :  *   #GDBusObjectManagerClient object or %NULL if @error is set. Free
     727                 :             :  *   with g_object_unref().
     728                 :             :  *
     729                 :             :  * Since: 2.30
     730                 :             :  */
     731                 :             : GDBusObjectManager *
     732                 :           2 : g_dbus_object_manager_client_new_finish (GAsyncResult   *res,
     733                 :             :                                          GError        **error)
     734                 :             : {
     735                 :             :   GObject *object;
     736                 :             :   GObject *source_object;
     737                 :             : 
     738                 :           2 :   source_object = g_async_result_get_source_object (res);
     739                 :           2 :   g_assert (source_object != NULL);
     740                 :             : 
     741                 :           2 :   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
     742                 :             :                                         res,
     743                 :             :                                         error);
     744                 :           2 :   g_object_unref (source_object);
     745                 :             : 
     746                 :           2 :   if (object != NULL)
     747                 :           2 :     return G_DBUS_OBJECT_MANAGER (object);
     748                 :             :   else
     749                 :           0 :     return NULL;
     750                 :             : }
     751                 :             : 
     752                 :             : /* ---------------------------------------------------------------------------------------------------- */
     753                 :             : 
     754                 :             : /**
     755                 :             :  * g_dbus_object_manager_client_new_for_bus_sync:
     756                 :             :  * @bus_type: A #GBusType.
     757                 :             :  * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
     758                 :             :  * @name: The owner of the control object (unique or well-known name).
     759                 :             :  * @object_path: The object path of the control object.
     760                 :             :  * @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
     761                 :             :  * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
     762                 :             :  * @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
     763                 :             :  * @cancellable: (nullable): A #GCancellable or %NULL
     764                 :             :  * @error: Return location for error or %NULL.
     765                 :             :  *
     766                 :             :  * Like g_dbus_object_manager_client_new_sync() but takes a #GBusType instead
     767                 :             :  * of a #GDBusConnection.
     768                 :             :  *
     769                 :             :  * This is a synchronous failable constructor - the calling thread is
     770                 :             :  * blocked until a reply is received. See g_dbus_object_manager_client_new_for_bus()
     771                 :             :  * for the asynchronous version.
     772                 :             :  *
     773                 :             :  * Returns: (transfer full) (type GDBusObjectManagerClient): A
     774                 :             :  *   #GDBusObjectManagerClient object or %NULL if @error is set. Free
     775                 :             :  *   with g_object_unref().
     776                 :             :  *
     777                 :             :  * Since: 2.30
     778                 :             :  */
     779                 :             : GDBusObjectManager *
     780                 :           0 : g_dbus_object_manager_client_new_for_bus_sync (GBusType                       bus_type,
     781                 :             :                                                GDBusObjectManagerClientFlags  flags,
     782                 :             :                                                const gchar                   *name,
     783                 :             :                                                const gchar                   *object_path,
     784                 :             :                                                GDBusProxyTypeFunc             get_proxy_type_func,
     785                 :             :                                                gpointer                       get_proxy_type_user_data,
     786                 :             :                                                GDestroyNotify                 get_proxy_type_destroy_notify,
     787                 :             :                                                GCancellable                  *cancellable,
     788                 :             :                                                GError                       **error)
     789                 :             : {
     790                 :             :   GInitable *initable;
     791                 :             : 
     792                 :           0 :   g_return_val_if_fail (bus_type != G_BUS_TYPE_NONE, NULL);
     793                 :           0 :   g_return_val_if_fail (g_dbus_is_name (name), NULL);
     794                 :           0 :   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
     795                 :           0 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     796                 :             : 
     797                 :           0 :   initable = g_initable_new (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
     798                 :             :                              cancellable,
     799                 :             :                              error,
     800                 :             :                              "bus-type", bus_type,
     801                 :             :                              "flags", flags,
     802                 :             :                              "name", name,
     803                 :             :                              "object-path", object_path,
     804                 :             :                              "get-proxy-type-func", get_proxy_type_func,
     805                 :             :                              "get-proxy-type-user-data", get_proxy_type_user_data,
     806                 :             :                              "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
     807                 :             :                              NULL);
     808                 :           0 :   if (initable != NULL)
     809                 :           0 :     return G_DBUS_OBJECT_MANAGER (initable);
     810                 :             :   else
     811                 :           0 :     return NULL;
     812                 :             : }
     813                 :             : 
     814                 :             : /**
     815                 :             :  * g_dbus_object_manager_client_new_for_bus:
     816                 :             :  * @bus_type: A #GBusType.
     817                 :             :  * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
     818                 :             :  * @name: The owner of the control object (unique or well-known name).
     819                 :             :  * @object_path: The object path of the control object.
     820                 :             :  * @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
     821                 :             :  * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
     822                 :             :  * @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
     823                 :             :  * @cancellable: (nullable): A #GCancellable or %NULL
     824                 :             :  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
     825                 :             :  * @user_data: The data to pass to @callback.
     826                 :             :  *
     827                 :             :  * Like g_dbus_object_manager_client_new() but takes a #GBusType instead of a
     828                 :             :  * #GDBusConnection.
     829                 :             :  *
     830                 :             :  * This is an asynchronous failable constructor. When the result is
     831                 :             :  * ready, @callback will be invoked in the
     832                 :             :  * [thread-default main loop][g-main-context-push-thread-default]
     833                 :             :  * of the thread you are calling this method from. You can
     834                 :             :  * then call g_dbus_object_manager_client_new_for_bus_finish() to get the result. See
     835                 :             :  * g_dbus_object_manager_client_new_for_bus_sync() for the synchronous version.
     836                 :             :  *
     837                 :             :  * Since: 2.30
     838                 :             :  */
     839                 :             : void
     840                 :           0 : g_dbus_object_manager_client_new_for_bus (GBusType                       bus_type,
     841                 :             :                                           GDBusObjectManagerClientFlags  flags,
     842                 :             :                                           const gchar                   *name,
     843                 :             :                                           const gchar                   *object_path,
     844                 :             :                                           GDBusProxyTypeFunc             get_proxy_type_func,
     845                 :             :                                           gpointer                       get_proxy_type_user_data,
     846                 :             :                                           GDestroyNotify                 get_proxy_type_destroy_notify,
     847                 :             :                                           GCancellable                  *cancellable,
     848                 :             :                                           GAsyncReadyCallback            callback,
     849                 :             :                                           gpointer                       user_data)
     850                 :             : {
     851                 :           0 :   g_return_if_fail (bus_type != G_BUS_TYPE_NONE);
     852                 :           0 :   g_return_if_fail (g_dbus_is_name (name));
     853                 :           0 :   g_return_if_fail (g_variant_is_object_path (object_path));
     854                 :             : 
     855                 :           0 :   g_async_initable_new_async (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
     856                 :             :                               G_PRIORITY_DEFAULT,
     857                 :             :                               cancellable,
     858                 :             :                               callback,
     859                 :             :                               user_data,
     860                 :             :                               "bus-type", bus_type,
     861                 :             :                               "flags", flags,
     862                 :             :                               "name", name,
     863                 :             :                               "object-path", object_path,
     864                 :             :                               "get-proxy-type-func", get_proxy_type_func,
     865                 :             :                               "get-proxy-type-user-data", get_proxy_type_user_data,
     866                 :             :                               "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
     867                 :             :                               NULL);
     868                 :             : }
     869                 :             : 
     870                 :             : /**
     871                 :             :  * g_dbus_object_manager_client_new_for_bus_finish:
     872                 :             :  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_object_manager_client_new_for_bus().
     873                 :             :  * @error: Return location for error or %NULL.
     874                 :             :  *
     875                 :             :  * Finishes an operation started with g_dbus_object_manager_client_new_for_bus().
     876                 :             :  *
     877                 :             :  * Returns: (transfer full) (type GDBusObjectManagerClient): A
     878                 :             :  *   #GDBusObjectManagerClient object or %NULL if @error is set. Free
     879                 :             :  *   with g_object_unref().
     880                 :             :  *
     881                 :             :  * Since: 2.30
     882                 :             :  */
     883                 :             : GDBusObjectManager *
     884                 :           0 : g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult   *res,
     885                 :             :                                                  GError        **error)
     886                 :             : {
     887                 :             :   GObject *object;
     888                 :             :   GObject *source_object;
     889                 :             : 
     890                 :           0 :   source_object = g_async_result_get_source_object (res);
     891                 :           0 :   g_assert (source_object != NULL);
     892                 :             : 
     893                 :           0 :   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
     894                 :             :                                         res,
     895                 :             :                                         error);
     896                 :           0 :   g_object_unref (source_object);
     897                 :             : 
     898                 :           0 :   if (object != NULL)
     899                 :           0 :     return G_DBUS_OBJECT_MANAGER (object);
     900                 :             :   else
     901                 :           0 :     return NULL;
     902                 :             : }
     903                 :             : 
     904                 :             : /* ---------------------------------------------------------------------------------------------------- */
     905                 :             : 
     906                 :             : /**
     907                 :             :  * g_dbus_object_manager_client_get_connection:
     908                 :             :  * @manager: A #GDBusObjectManagerClient
     909                 :             :  *
     910                 :             :  * Gets the #GDBusConnection used by @manager.
     911                 :             :  *
     912                 :             :  * Returns: (transfer none): A #GDBusConnection object. Do not free,
     913                 :             :  *   the object belongs to @manager.
     914                 :             :  *
     915                 :             :  * Since: 2.30
     916                 :             :  */
     917                 :             : GDBusConnection *
     918                 :           3 : g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager)
     919                 :             : {
     920                 :             :   GDBusConnection *ret;
     921                 :           3 :   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
     922                 :           3 :   g_mutex_lock (&manager->priv->lock);
     923                 :           3 :   ret = manager->priv->connection;
     924                 :           3 :   g_mutex_unlock (&manager->priv->lock);
     925                 :           3 :   return ret;
     926                 :             : }
     927                 :             : 
     928                 :             : /**
     929                 :             :  * g_dbus_object_manager_client_get_name:
     930                 :             :  * @manager: A #GDBusObjectManagerClient
     931                 :             :  *
     932                 :             :  * Gets the name that @manager is for, or %NULL if not a message bus
     933                 :             :  * connection.
     934                 :             :  *
     935                 :             :  * Returns: A unique or well-known name. Do not free, the string
     936                 :             :  * belongs to @manager.
     937                 :             :  *
     938                 :             :  * Since: 2.30
     939                 :             :  */
     940                 :             : const gchar *
     941                 :           3 : g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager)
     942                 :             : {
     943                 :             :   const gchar *ret;
     944                 :           3 :   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
     945                 :           3 :   g_mutex_lock (&manager->priv->lock);
     946                 :           3 :   ret = manager->priv->name;
     947                 :           3 :   g_mutex_unlock (&manager->priv->lock);
     948                 :           3 :   return ret;
     949                 :             : }
     950                 :             : 
     951                 :             : /**
     952                 :             :  * g_dbus_object_manager_client_get_flags:
     953                 :             :  * @manager: A #GDBusObjectManagerClient
     954                 :             :  *
     955                 :             :  * Gets the flags that @manager was constructed with.
     956                 :             :  *
     957                 :             :  * Returns: Zero of more flags from the #GDBusObjectManagerClientFlags
     958                 :             :  * enumeration.
     959                 :             :  *
     960                 :             :  * Since: 2.30
     961                 :             :  */
     962                 :             : GDBusObjectManagerClientFlags
     963                 :           3 : g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager)
     964                 :             : {
     965                 :             :   GDBusObjectManagerClientFlags ret;
     966                 :           3 :   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE);
     967                 :           3 :   g_mutex_lock (&manager->priv->lock);
     968                 :           3 :   ret = manager->priv->flags;
     969                 :           3 :   g_mutex_unlock (&manager->priv->lock);
     970                 :           3 :   return ret;
     971                 :             : }
     972                 :             : 
     973                 :             : /**
     974                 :             :  * g_dbus_object_manager_client_get_name_owner:
     975                 :             :  * @manager: A #GDBusObjectManagerClient.
     976                 :             :  *
     977                 :             :  * The unique name that owns the name that @manager is for or %NULL if
     978                 :             :  * no-one currently owns that name. You can connect to the
     979                 :             :  * #GObject::notify signal to track changes to the
     980                 :             :  * #GDBusObjectManagerClient:name-owner property.
     981                 :             :  *
     982                 :             :  * Returns: (nullable): The name owner or %NULL if no name owner
     983                 :             :  * exists. Free with g_free().
     984                 :             :  *
     985                 :             :  * Since: 2.30
     986                 :             :  */
     987                 :             : gchar *
     988                 :           3 : g_dbus_object_manager_client_get_name_owner (GDBusObjectManagerClient *manager)
     989                 :             : {
     990                 :             :   gchar *ret;
     991                 :           3 :   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
     992                 :           3 :   g_mutex_lock (&manager->priv->lock);
     993                 :           3 :   ret = g_strdup (manager->priv->name_owner);
     994                 :           3 :   g_mutex_unlock (&manager->priv->lock);
     995                 :           3 :   return ret;
     996                 :             : }
     997                 :             : 
     998                 :             : /* ---------------------------------------------------------------------------------------------------- */
     999                 :             : 
    1000                 :             : /* signal handler for all objects we manage - we dispatch signals
    1001                 :             :  * from here to the objects
    1002                 :             :  */
    1003                 :             : static void
    1004                 :          54 : signal_cb (GDBusConnection *connection,
    1005                 :             :            const gchar     *sender_name,
    1006                 :             :            const gchar     *object_path,
    1007                 :             :            const gchar     *interface_name,
    1008                 :             :            const gchar     *signal_name,
    1009                 :             :            GVariant        *parameters,
    1010                 :             :            gpointer         user_data)
    1011                 :             : {
    1012                 :          54 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data);
    1013                 :             :   GDBusObjectProxy *object_proxy;
    1014                 :             :   GDBusInterface *interface;
    1015                 :             : 
    1016                 :          54 :   g_mutex_lock (&manager->priv->lock);
    1017                 :          54 :   object_proxy = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
    1018                 :          54 :   if (object_proxy == NULL)
    1019                 :             :     {
    1020                 :          36 :       g_mutex_unlock (&manager->priv->lock);
    1021                 :          36 :       goto out;
    1022                 :             :     }
    1023                 :          18 :   g_object_ref (object_proxy);
    1024                 :          18 :   g_mutex_unlock (&manager->priv->lock);
    1025                 :             : 
    1026                 :             :   //g_debug ("yay, signal_cb %s %s: %s\n", signal_name, object_path, g_variant_print (parameters, TRUE));
    1027                 :             : 
    1028                 :          18 :   g_object_ref (manager);
    1029                 :          18 :   if (g_strcmp0 (interface_name, DBUS_INTERFACE_PROPERTIES) == 0)
    1030                 :             :     {
    1031                 :          15 :       if (g_strcmp0 (signal_name, "PropertiesChanged") == 0)
    1032                 :             :         {
    1033                 :             :           const gchar *properties_interface_name;
    1034                 :             :           GVariant *changed_properties;
    1035                 :             :           const gchar **invalidated_properties;
    1036                 :             : 
    1037                 :          15 :           g_variant_get (parameters,
    1038                 :             :                          "(&s@a{sv}^a&s)",
    1039                 :             :                          &properties_interface_name,
    1040                 :             :                          &changed_properties,
    1041                 :             :                          &invalidated_properties);
    1042                 :             : 
    1043                 :          15 :           interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object_proxy), properties_interface_name);
    1044                 :          15 :           if (interface != NULL)
    1045                 :             :             {
    1046                 :             :               GVariantIter property_iter;
    1047                 :             :               const gchar *property_name;
    1048                 :             :               GVariant *property_value;
    1049                 :             :               guint n;
    1050                 :             : 
    1051                 :             :               /* update caches... */
    1052                 :          15 :               g_variant_iter_init (&property_iter, changed_properties);
    1053                 :          30 :               while (g_variant_iter_next (&property_iter,
    1054                 :             :                                           "{&sv}",
    1055                 :             :                                           &property_name,
    1056                 :             :                                           &property_value))
    1057                 :             :                 {
    1058                 :          15 :                   g_dbus_proxy_set_cached_property (G_DBUS_PROXY (interface),
    1059                 :             :                                                     property_name,
    1060                 :             :                                                     property_value);
    1061                 :          15 :                   g_variant_unref (property_value);
    1062                 :             :                 }
    1063                 :             : 
    1064                 :          15 :               for (n = 0; invalidated_properties[n] != NULL; n++)
    1065                 :             :                 {
    1066                 :           0 :                   g_dbus_proxy_set_cached_property (G_DBUS_PROXY (interface),
    1067                 :           0 :                                                     invalidated_properties[n],
    1068                 :             :                                                     NULL);
    1069                 :             :                 }
    1070                 :             :               /* ... and then synthesize the signal */
    1071                 :          15 :               g_signal_emit_by_name (interface,
    1072                 :             :                                      "g-properties-changed",
    1073                 :             :                                      changed_properties,
    1074                 :             :                                      invalidated_properties);
    1075                 :          15 :               g_signal_emit (manager,
    1076                 :             :                              signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL],
    1077                 :             :                              0,
    1078                 :             :                              object_proxy,
    1079                 :             :                              interface,
    1080                 :             :                              changed_properties,
    1081                 :             :                              invalidated_properties);
    1082                 :          15 :               g_object_unref (interface);
    1083                 :             :             }
    1084                 :          15 :           g_variant_unref (changed_properties);
    1085                 :          15 :           g_free (invalidated_properties);
    1086                 :             :         }
    1087                 :             :     }
    1088                 :             :   else
    1089                 :             :     {
    1090                 :             :       /* regular signal - just dispatch it */
    1091                 :           3 :       interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object_proxy), interface_name);
    1092                 :           3 :       if (interface != NULL)
    1093                 :             :         {
    1094                 :           3 :           g_signal_emit_by_name (interface,
    1095                 :             :                                  "g-signal",
    1096                 :             :                                  sender_name,
    1097                 :             :                                  signal_name,
    1098                 :             :                                  parameters);
    1099                 :           3 :           g_signal_emit (manager,
    1100                 :             :                          signals[INTERFACE_PROXY_SIGNAL_SIGNAL],
    1101                 :             :                          0,
    1102                 :             :                          object_proxy,
    1103                 :             :                          interface,
    1104                 :             :                          sender_name,
    1105                 :             :                          signal_name,
    1106                 :             :                          parameters);
    1107                 :           3 :           g_object_unref (interface);
    1108                 :             :         }
    1109                 :             :     }
    1110                 :          18 :   g_object_unref (manager);
    1111                 :             : 
    1112                 :          54 :  out:
    1113                 :          54 :   g_clear_object (&object_proxy);
    1114                 :          54 : }
    1115                 :             : 
    1116                 :             : static void
    1117                 :           8 : subscribe_signals (GDBusObjectManagerClient *manager,
    1118                 :             :                    const gchar *name_owner)
    1119                 :             : {
    1120                 :           8 :   GError *error = NULL;
    1121                 :             :   GVariant *ret;
    1122                 :             : 
    1123                 :           8 :   g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
    1124                 :           8 :   g_return_if_fail (manager->priv->signal_subscription_id == 0);
    1125                 :           8 :   g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
    1126                 :             : 
    1127                 :           8 :   if (name_owner != NULL)
    1128                 :             :     {
    1129                 :             :       /* Only add path_namespace if it's non-'/'. This removes a no-op key from
    1130                 :             :        * the match rule, and also works around a D-Bus bug where
    1131                 :             :        * path_namespace='/' matches nothing in D-Bus versions < 1.6.18.
    1132                 :             :        *
    1133                 :             :        * See: https://bugs.freedesktop.org/show_bug.cgi?id=70799 */
    1134                 :           6 :       if (g_str_equal (manager->priv->object_path, "/"))
    1135                 :             :         {
    1136                 :           0 :           manager->priv->match_rule = g_strdup_printf ("type='signal',sender='%s'",
    1137                 :             :                                                        name_owner);
    1138                 :             :         }
    1139                 :             :       else
    1140                 :             :         {
    1141                 :           6 :           manager->priv->match_rule = g_strdup_printf ("type='signal',sender='%s',path_namespace='%s'",
    1142                 :           6 :                                                        name_owner, manager->priv->object_path);
    1143                 :             :         }
    1144                 :             : 
    1145                 :             :       /* The bus daemon may not implement path_namespace so gracefully
    1146                 :             :        * handle this by using a fallback triggered if @error is set. */
    1147                 :           6 :       ret = g_dbus_connection_call_sync (manager->priv->connection,
    1148                 :             :                                          DBUS_SERVICE_DBUS,
    1149                 :             :                                          DBUS_PATH_DBUS,
    1150                 :             :                                          DBUS_INTERFACE_DBUS,
    1151                 :             :                                          "AddMatch",
    1152                 :             :                                          g_variant_new ("(s)",
    1153                 :           6 :                                                         manager->priv->match_rule),
    1154                 :             :                                          NULL, /* reply_type */
    1155                 :             :                                          G_DBUS_CALL_FLAGS_NONE,
    1156                 :             :                                          -1, /* default timeout */
    1157                 :             :                                          NULL, /* TODO: Cancellable */
    1158                 :             :                                          &error);
    1159                 :             : 
    1160                 :             :       /* yay, bus daemon supports path_namespace */
    1161                 :           6 :       if (ret != NULL)
    1162                 :           6 :         g_variant_unref (ret);
    1163                 :             :     }
    1164                 :             : 
    1165                 :           8 :   if (error == NULL)
    1166                 :             :     {
    1167                 :             :       /* still need to ask GDBusConnection for the callbacks */
    1168                 :           8 :       manager->priv->signal_subscription_id =
    1169                 :           8 :         g_dbus_connection_signal_subscribe (manager->priv->connection,
    1170                 :             :                                             name_owner,
    1171                 :             :                                             NULL, /* interface */
    1172                 :             :                                             NULL, /* member */
    1173                 :             :                                             NULL, /* path - TODO: really want wildcard support here */
    1174                 :             :                                             NULL, /* arg0 */
    1175                 :             :                                             G_DBUS_SIGNAL_FLAGS_NONE |
    1176                 :             :                                             G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
    1177                 :             :                                             signal_cb,
    1178                 :             :                                             manager,
    1179                 :             :                                             NULL); /* user_data_free_func */
    1180                 :             : 
    1181                 :             :     }
    1182                 :             :   else
    1183                 :             :     {
    1184                 :             :       /* TODO: we could report this to the user
    1185                 :             :       g_warning ("Message bus daemon does not support path_namespace: %s (%s %d)",
    1186                 :             :                  error->message,
    1187                 :             :                  g_quark_to_string (error->domain),
    1188                 :             :                  error->code);
    1189                 :             :       */
    1190                 :             : 
    1191                 :           0 :       g_error_free (error);
    1192                 :             : 
    1193                 :             :       /* no need to call RemoveMatch when done since it didn't work */
    1194                 :           0 :       g_free (manager->priv->match_rule);
    1195                 :           0 :       manager->priv->match_rule = NULL;
    1196                 :             : 
    1197                 :             :       /* Fallback is to subscribe to *all* signals from the name owner which
    1198                 :             :        * is rather wasteful. It's probably not a big practical problem because
    1199                 :             :        * users typically want all objects that the name owner supplies.
    1200                 :             :        */
    1201                 :           0 :       manager->priv->signal_subscription_id =
    1202                 :           0 :         g_dbus_connection_signal_subscribe (manager->priv->connection,
    1203                 :             :                                             name_owner,
    1204                 :             :                                             NULL, /* interface */
    1205                 :             :                                             NULL, /* member */
    1206                 :             :                                             NULL, /* path - TODO: really want wildcard support here */
    1207                 :             :                                             NULL, /* arg0 */
    1208                 :             :                                             G_DBUS_SIGNAL_FLAGS_NONE,
    1209                 :             :                                             signal_cb,
    1210                 :             :                                             manager,
    1211                 :             :                                             NULL); /* user_data_free_func */
    1212                 :             :     }
    1213                 :             : }
    1214                 :             : 
    1215                 :             : static void
    1216                 :          11 : maybe_unsubscribe_signals (GDBusObjectManagerClient *manager)
    1217                 :             : {
    1218                 :          11 :   g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
    1219                 :             : 
    1220                 :          11 :   if (manager->priv->signal_subscription_id > 0)
    1221                 :           8 :     g_dbus_connection_signal_unsubscribe (manager->priv->connection,
    1222                 :           8 :                                           g_steal_handle_id (&manager->priv->signal_subscription_id));
    1223                 :             : 
    1224                 :          11 :   if (manager->priv->match_rule != NULL)
    1225                 :             :     {
    1226                 :             :       /* Since the AddMatch call succeeded this is guaranteed to not
    1227                 :             :        * fail - therefore, don't bother checking the return value
    1228                 :             :        */
    1229                 :           6 :       g_dbus_connection_call (manager->priv->connection,
    1230                 :             :                               DBUS_SERVICE_DBUS,
    1231                 :             :                               DBUS_PATH_DBUS,
    1232                 :             :                               DBUS_INTERFACE_DBUS,
    1233                 :             :                               "RemoveMatch",
    1234                 :             :                               g_variant_new ("(s)",
    1235                 :           6 :                                              manager->priv->match_rule),
    1236                 :             :                               NULL, /* reply_type */
    1237                 :             :                               G_DBUS_CALL_FLAGS_NONE,
    1238                 :             :                               -1, /* default timeout */
    1239                 :             :                               NULL, /* GCancellable */
    1240                 :             :                               NULL, /* GAsyncReadyCallback */
    1241                 :             :                               NULL); /* user data */
    1242                 :           6 :       g_free (manager->priv->match_rule);
    1243                 :           6 :       manager->priv->match_rule = NULL;
    1244                 :             :     }
    1245                 :             : 
    1246                 :             : }
    1247                 :             : 
    1248                 :             : /* ---------------------------------------------------------------------------------------------------- */
    1249                 :             : 
    1250                 :             : static GWeakRef *
    1251                 :          16 : weak_ref_new (GObject *object)
    1252                 :             : {
    1253                 :          16 :   GWeakRef *weak_ref = g_new0 (GWeakRef, 1);
    1254                 :          16 :   g_weak_ref_init (weak_ref, object);
    1255                 :          16 :   return g_steal_pointer (&weak_ref);
    1256                 :             : }
    1257                 :             : 
    1258                 :             : static void
    1259                 :          16 : weak_ref_free (GWeakRef *weak_ref)
    1260                 :             : {
    1261                 :          16 :   g_weak_ref_clear (weak_ref);
    1262                 :          16 :   g_free (weak_ref);
    1263                 :          16 : }
    1264                 :             : 
    1265                 :             : static void
    1266                 :           0 : on_get_managed_objects_finish (GObject      *source,
    1267                 :             :                                GAsyncResult *result,
    1268                 :             :                                gpointer      user_data)
    1269                 :             : {
    1270                 :             : 
    1271                 :           0 :   GDBusProxy *proxy = G_DBUS_PROXY (source);
    1272                 :           0 :   GWeakRef *manager_weak = user_data;
    1273                 :             :   GDBusObjectManagerClient *manager;
    1274                 :           0 :   GError *error = NULL;
    1275                 :           0 :   GVariant *value = NULL;
    1276                 :           0 :   gchar *new_name_owner = NULL;
    1277                 :             : 
    1278                 :           0 :   value = g_dbus_proxy_call_finish (proxy, result, &error);
    1279                 :             : 
    1280                 :           0 :   manager = G_DBUS_OBJECT_MANAGER_CLIENT (g_weak_ref_get (manager_weak));
    1281                 :             :   /* Manager got disposed, nothing to do */
    1282                 :           0 :   if (manager == NULL)
    1283                 :             :     {
    1284                 :           0 :       goto out;
    1285                 :             :     }
    1286                 :             : 
    1287                 :           0 :   new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
    1288                 :           0 :   if (value == NULL)
    1289                 :             :     {
    1290                 :           0 :       maybe_unsubscribe_signals (manager);
    1291                 :           0 :       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
    1292                 :             :         {
    1293                 :           0 :           g_warning ("Error calling GetManagedObjects() when name owner %s for name %s came back: %s",
    1294                 :             :                      new_name_owner,
    1295                 :             :                      manager->priv->name,
    1296                 :             :                      error->message);
    1297                 :             :         }
    1298                 :             :     }
    1299                 :             :   else
    1300                 :             :     {
    1301                 :           0 :       process_get_all_result (manager, value, new_name_owner);
    1302                 :             :     }
    1303                 :             : 
    1304                 :             :   /* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this
    1305                 :             :    * way the user knows that the signals were emitted because the name owner came back
    1306                 :             :    */
    1307                 :           0 :   g_mutex_lock (&manager->priv->lock);
    1308                 :           0 :   manager->priv->name_owner = g_steal_pointer (&new_name_owner);
    1309                 :           0 :   g_mutex_unlock (&manager->priv->lock);
    1310                 :           0 :   g_object_notify (G_OBJECT (manager), "name-owner");
    1311                 :             : 
    1312                 :           0 :   g_object_unref (manager);
    1313                 :           0 :  out:
    1314                 :           0 :   g_clear_error (&error);
    1315                 :           0 :   g_clear_pointer (&value, g_variant_unref);
    1316                 :           0 :   weak_ref_free (manager_weak);
    1317                 :           0 : }
    1318                 :             : 
    1319                 :             : static void
    1320                 :           0 : on_notify_g_name_owner (GObject    *object,
    1321                 :             :                         GParamSpec *pspec,
    1322                 :             :                         gpointer    user_data)
    1323                 :             : {
    1324                 :           0 :   GWeakRef *manager_weak = user_data;
    1325                 :           0 :   GDBusObjectManagerClient *manager = NULL;
    1326                 :             :   gchar *old_name_owner;
    1327                 :             :   gchar *new_name_owner;
    1328                 :             : 
    1329                 :           0 :   manager = G_DBUS_OBJECT_MANAGER_CLIENT (g_weak_ref_get (manager_weak));
    1330                 :           0 :   if (manager == NULL)
    1331                 :           0 :     return;
    1332                 :             : 
    1333                 :           0 :   g_mutex_lock (&manager->priv->lock);
    1334                 :           0 :   old_name_owner = manager->priv->name_owner;
    1335                 :           0 :   new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
    1336                 :           0 :   manager->priv->name_owner = NULL;
    1337                 :             : 
    1338                 :           0 :   if (g_strcmp0 (old_name_owner, new_name_owner) != 0)
    1339                 :             :     {
    1340                 :             :       GPtrArray *proxies;
    1341                 :             : 
    1342                 :             :       /* remote manager changed; nuke all local proxies  */
    1343                 :           0 :       proxies = g_hash_table_steal_all_values (
    1344                 :           0 :         manager->priv->map_object_path_to_object_proxy);
    1345                 :             : 
    1346                 :           0 :       g_mutex_unlock (&manager->priv->lock);
    1347                 :             : 
    1348                 :             :       /* do the :name-owner notify with a NULL name - this way the user knows
    1349                 :             :        * the ::object-proxy-removed following is because the name owner went
    1350                 :             :        * away
    1351                 :             :        */
    1352                 :           0 :       g_object_notify (G_OBJECT (manager), "name-owner");
    1353                 :             : 
    1354                 :           0 :       for (guint i = 0; i < proxies->len; ++i)
    1355                 :             :         {
    1356                 :             :           GDBusObjectProxy *object_proxy =
    1357                 :           0 :             G_DBUS_OBJECT_PROXY (g_ptr_array_index (proxies, i));
    1358                 :           0 :           g_signal_emit_by_name (manager, "object-removed", object_proxy);
    1359                 :             :         }
    1360                 :           0 :       g_clear_pointer (&proxies, g_ptr_array_unref);
    1361                 :             : 
    1362                 :             :       /* nuke local filter */
    1363                 :           0 :       maybe_unsubscribe_signals (manager);
    1364                 :             :     }
    1365                 :             :   else
    1366                 :             :     {
    1367                 :           0 :       g_mutex_unlock (&manager->priv->lock);
    1368                 :             :     }
    1369                 :             : 
    1370                 :           0 :   if (new_name_owner != NULL)
    1371                 :             :     {
    1372                 :             :       //g_debug ("repopulating for %s", new_name_owner);
    1373                 :             : 
    1374                 :           0 :       subscribe_signals (manager,
    1375                 :             :                          new_name_owner);
    1376                 :           0 :       g_dbus_proxy_call (manager->priv->control_proxy,
    1377                 :             :                          "GetManagedObjects",
    1378                 :             :                          NULL, /* parameters */
    1379                 :             :                          G_DBUS_CALL_FLAGS_NONE,
    1380                 :             :                          -1,
    1381                 :           0 :                          manager->priv->cancel,
    1382                 :             :                          on_get_managed_objects_finish,
    1383                 :           0 :                          weak_ref_new (G_OBJECT (manager)));
    1384                 :             :     }
    1385                 :           0 :   g_free (new_name_owner);
    1386                 :           0 :   g_free (old_name_owner);
    1387                 :           0 :   g_object_unref (manager);
    1388                 :             : }
    1389                 :             : 
    1390                 :             : static gboolean
    1391                 :           8 : initable_init (GInitable     *initable,
    1392                 :             :                GCancellable  *cancellable,
    1393                 :             :                GError       **error)
    1394                 :             : {
    1395                 :           8 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (initable);
    1396                 :             :   gboolean ret;
    1397                 :             :   GVariant *value;
    1398                 :             :   GDBusProxyFlags proxy_flags;
    1399                 :             : 
    1400                 :           8 :   ret = FALSE;
    1401                 :             : 
    1402                 :           8 :   if (manager->priv->bus_type != G_BUS_TYPE_NONE)
    1403                 :             :     {
    1404                 :           0 :       g_assert (manager->priv->connection == NULL);
    1405                 :           0 :       manager->priv->connection = g_bus_get_sync (manager->priv->bus_type, cancellable, error);
    1406                 :           0 :       if (manager->priv->connection == NULL)
    1407                 :           0 :         goto out;
    1408                 :             :     }
    1409                 :             : 
    1410                 :           8 :   proxy_flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
    1411                 :           8 :   if (manager->priv->flags & G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START)
    1412                 :           2 :     proxy_flags |= G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
    1413                 :             : 
    1414                 :          16 :   manager->priv->control_proxy = g_dbus_proxy_new_sync (manager->priv->connection,
    1415                 :             :                                                         proxy_flags,
    1416                 :             :                                                         NULL, /* GDBusInterfaceInfo* */
    1417                 :           8 :                                                         manager->priv->name,
    1418                 :           8 :                                                         manager->priv->object_path,
    1419                 :             :                                                         DBUS_INTERFACE_OBJECT_MANAGER,
    1420                 :             :                                                         cancellable,
    1421                 :             :                                                         error);
    1422                 :           8 :   if (manager->priv->control_proxy == NULL)
    1423                 :           0 :     goto out;
    1424                 :             : 
    1425                 :             :   /* Use weak refs here. The @control_proxy will emit its signals in the current
    1426                 :             :    * #GMainContext (since we constructed it just above). However, the user may
    1427                 :             :    * drop the last external reference to this #GDBusObjectManagerClient in
    1428                 :             :    * another thread between a signal being emitted and scheduled in an idle
    1429                 :             :    * callback in this #GMainContext, and that idle callback being invoked. We
    1430                 :             :    * can’t use a strong reference here, as there’s no
    1431                 :             :    * g_dbus_object_manager_client_disconnect() (or similar) method to tell us
    1432                 :             :    * when the last external reference to this object has been dropped, so we
    1433                 :             :    * can’t break a strong reference count cycle. So use weak refs. */
    1434                 :          16 :   manager->priv->name_owner_signal_id =
    1435                 :           8 :       g_signal_connect_data (G_OBJECT (manager->priv->control_proxy),
    1436                 :             :                             "notify::g-name-owner",
    1437                 :             :                             G_CALLBACK (on_notify_g_name_owner),
    1438                 :           8 :                             weak_ref_new (G_OBJECT (manager)),
    1439                 :             :                             (GClosureNotify) weak_ref_free,
    1440                 :             :                             G_CONNECT_DEFAULT);
    1441                 :             : 
    1442                 :          16 :   manager->priv->signal_signal_id =
    1443                 :           8 :       g_signal_connect_data (manager->priv->control_proxy,
    1444                 :             :                             "g-signal",
    1445                 :             :                             G_CALLBACK (on_control_proxy_g_signal),
    1446                 :           8 :                             weak_ref_new (G_OBJECT (manager)),
    1447                 :             :                             (GClosureNotify) weak_ref_free,
    1448                 :             :                             G_CONNECT_DEFAULT);
    1449                 :             : 
    1450                 :           8 :   manager->priv->name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
    1451                 :           8 :   if (manager->priv->name_owner == NULL && manager->priv->name != NULL)
    1452                 :             :     {
    1453                 :             :       /* it's perfectly fine if there's no name owner.. we're just going to
    1454                 :             :        * wait until one is ready
    1455                 :             :        */
    1456                 :             :     }
    1457                 :             :   else
    1458                 :             :     {
    1459                 :             :       /* yay, we can get the objects */
    1460                 :           8 :       subscribe_signals (manager,
    1461                 :           8 :                          manager->priv->name_owner);
    1462                 :           8 :       value = g_dbus_proxy_call_sync (manager->priv->control_proxy,
    1463                 :             :                                       "GetManagedObjects",
    1464                 :             :                                       NULL, /* parameters */
    1465                 :             :                                       G_DBUS_CALL_FLAGS_NONE,
    1466                 :             :                                       -1,
    1467                 :             :                                       cancellable,
    1468                 :             :                                       error);
    1469                 :           8 :       if (value == NULL)
    1470                 :             :         {
    1471                 :           3 :           maybe_unsubscribe_signals (manager);
    1472                 :             : 
    1473                 :           3 :           g_warn_if_fail (manager->priv->signal_signal_id != 0);
    1474                 :           3 :           g_signal_handler_disconnect (manager->priv->control_proxy,
    1475                 :           3 :                                        manager->priv->signal_signal_id);
    1476                 :           3 :           manager->priv->signal_signal_id = 0;
    1477                 :             : 
    1478                 :           3 :           g_warn_if_fail (manager->priv->name_owner_signal_id != 0);
    1479                 :           3 :           g_signal_handler_disconnect (manager->priv->control_proxy,
    1480                 :           3 :                                        manager->priv->name_owner_signal_id);
    1481                 :           3 :           manager->priv->name_owner_signal_id = 0;
    1482                 :             : 
    1483                 :           3 :           g_object_unref (manager->priv->control_proxy);
    1484                 :           3 :           manager->priv->control_proxy = NULL;
    1485                 :             : 
    1486                 :           3 :           goto out;
    1487                 :             :         }
    1488                 :             : 
    1489                 :           5 :       process_get_all_result (manager, value, manager->priv->name_owner);
    1490                 :           5 :       g_variant_unref (value);
    1491                 :             :     }
    1492                 :             : 
    1493                 :           5 :   ret = TRUE;
    1494                 :             : 
    1495                 :           8 :  out:
    1496                 :           8 :   return ret;
    1497                 :             : }
    1498                 :             : 
    1499                 :             : static void
    1500                 :           5 : initable_iface_init (GInitableIface *initable_iface)
    1501                 :             : {
    1502                 :           5 :   initable_iface->init = initable_init;
    1503                 :           5 : }
    1504                 :             : 
    1505                 :             : static void
    1506                 :           5 : async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
    1507                 :             : {
    1508                 :             :   /* for now, just use default: run GInitable code in thread */
    1509                 :           5 : }
    1510                 :             : 
    1511                 :             : /* ---------------------------------------------------------------------------------------------------- */
    1512                 :             : 
    1513                 :             : static void
    1514                 :          25 : add_interfaces (GDBusObjectManagerClient *manager,
    1515                 :             :                 const gchar       *object_path,
    1516                 :             :                 GVariant          *ifaces_and_properties,
    1517                 :             :                 const gchar       *name_owner)
    1518                 :             : {
    1519                 :             :   GDBusObjectProxy *op;
    1520                 :             :   gboolean added;
    1521                 :             :   GVariantIter iter;
    1522                 :             :   const gchar *interface_name;
    1523                 :             :   GVariant *properties;
    1524                 :             :   GList *interface_added_signals, *l;
    1525                 :             :   GDBusProxy *interface_proxy;
    1526                 :             : 
    1527                 :          25 :   g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
    1528                 :             : 
    1529                 :          25 :   g_mutex_lock (&manager->priv->lock);
    1530                 :             : 
    1531                 :          25 :   interface_added_signals = NULL;
    1532                 :          25 :   added = FALSE;
    1533                 :             : 
    1534                 :          25 :   op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
    1535                 :          25 :   if (op == NULL)
    1536                 :             :     {
    1537                 :             :       GType object_proxy_type;
    1538                 :          22 :       if (manager->priv->get_proxy_type_func != NULL)
    1539                 :             :         {
    1540                 :          18 :           object_proxy_type = manager->priv->get_proxy_type_func (manager,
    1541                 :             :                                                                   object_path,
    1542                 :             :                                                                   NULL,
    1543                 :          18 :                                                                   manager->priv->get_proxy_type_user_data);
    1544                 :          18 :           g_warn_if_fail (g_type_is_a (object_proxy_type, G_TYPE_DBUS_OBJECT_PROXY));
    1545                 :             :         }
    1546                 :             :       else
    1547                 :             :         {
    1548                 :           4 :           object_proxy_type = G_TYPE_DBUS_OBJECT_PROXY;
    1549                 :             :         }
    1550                 :          22 :       op = g_object_new (object_proxy_type,
    1551                 :          22 :                          "g-connection", manager->priv->connection,
    1552                 :             :                          "g-object-path", object_path,
    1553                 :             :                          NULL);
    1554                 :          22 :       added = TRUE;
    1555                 :             :     }
    1556                 :          25 :   g_object_ref (op);
    1557                 :             : 
    1558                 :          25 :   g_variant_iter_init (&iter, ifaces_and_properties);
    1559                 :          53 :   while (g_variant_iter_next (&iter,
    1560                 :             :                               "{&s@a{sv}}",
    1561                 :             :                               &interface_name,
    1562                 :             :                               &properties))
    1563                 :             :     {
    1564                 :             :       GError *error;
    1565                 :             :       GType interface_proxy_type;
    1566                 :             : 
    1567                 :          28 :       if (manager->priv->get_proxy_type_func != NULL)
    1568                 :             :         {
    1569                 :          24 :           interface_proxy_type = manager->priv->get_proxy_type_func (manager,
    1570                 :             :                                                                      object_path,
    1571                 :             :                                                                      interface_name,
    1572                 :          24 :                                                                      manager->priv->get_proxy_type_user_data);
    1573                 :          24 :           g_warn_if_fail (g_type_is_a (interface_proxy_type, G_TYPE_DBUS_PROXY));
    1574                 :             :         }
    1575                 :             :       else
    1576                 :             :         {
    1577                 :           4 :           interface_proxy_type = G_TYPE_DBUS_PROXY;
    1578                 :             :         }
    1579                 :             : 
    1580                 :             :       /* this is fine - there is no blocking IO because we pass DO_NOT_LOAD_PROPERTIES and
    1581                 :             :        * DO_NOT_CONNECT_SIGNALS and use a unique name
    1582                 :             :        */
    1583                 :          28 :       error = NULL;
    1584                 :          28 :       interface_proxy = g_initable_new (interface_proxy_type,
    1585                 :             :                                         NULL, /* GCancellable */
    1586                 :             :                                         &error,
    1587                 :          28 :                                         "g-connection", manager->priv->connection,
    1588                 :             :                                         "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
    1589                 :             :                                                    G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
    1590                 :             :                                         "g-name", name_owner,
    1591                 :             :                                         "g-object-path", object_path,
    1592                 :             :                                         "g-interface-name", interface_name,
    1593                 :             :                                         NULL);
    1594                 :          28 :       if (interface_proxy == NULL)
    1595                 :             :         {
    1596                 :           0 :           g_warning ("%s: Error constructing proxy for path %s and interface %s: %s",
    1597                 :             :                      G_STRLOC,
    1598                 :             :                      object_path,
    1599                 :             :                      interface_name,
    1600                 :             :                      error->message);
    1601                 :           0 :           g_error_free (error);
    1602                 :             :         }
    1603                 :             :       else
    1604                 :             :         {
    1605                 :             :           GVariantIter property_iter;
    1606                 :             :           const gchar *property_name;
    1607                 :             :           GVariant *property_value;
    1608                 :             : 
    1609                 :             :           /* associate the interface proxy with the object */
    1610                 :          28 :           g_dbus_interface_set_object (G_DBUS_INTERFACE (interface_proxy),
    1611                 :          28 :                                        G_DBUS_OBJECT (op));
    1612                 :             : 
    1613                 :          28 :           g_variant_iter_init (&property_iter, properties);
    1614                 :         438 :           while (g_variant_iter_next (&property_iter,
    1615                 :             :                                       "{&sv}",
    1616                 :             :                                       &property_name,
    1617                 :             :                                       &property_value))
    1618                 :             :             {
    1619                 :         410 :               g_dbus_proxy_set_cached_property (interface_proxy,
    1620                 :             :                                                 property_name,
    1621                 :             :                                                 property_value);
    1622                 :         410 :               g_variant_unref (property_value);
    1623                 :             :             }
    1624                 :             : 
    1625                 :          28 :           _g_dbus_object_proxy_add_interface (op, interface_proxy);
    1626                 :          28 :           if (!added)
    1627                 :           3 :             interface_added_signals = g_list_append (interface_added_signals, g_object_ref (interface_proxy));
    1628                 :          28 :           g_object_unref (interface_proxy);
    1629                 :             :         }
    1630                 :          28 :       g_variant_unref (properties);
    1631                 :             :     }
    1632                 :             : 
    1633                 :          25 :   if (added)
    1634                 :             :     {
    1635                 :          22 :       g_hash_table_insert (manager->priv->map_object_path_to_object_proxy,
    1636                 :          22 :                            g_strdup (object_path),
    1637                 :             :                            op);
    1638                 :             :     }
    1639                 :             : 
    1640                 :          25 :   g_mutex_unlock (&manager->priv->lock);
    1641                 :             : 
    1642                 :             :   /* now that we don't hold the lock any more, emit signals */
    1643                 :          25 :   g_object_ref (manager);
    1644                 :          28 :   for (l = interface_added_signals; l != NULL; l = l->next)
    1645                 :             :     {
    1646                 :           3 :       interface_proxy = G_DBUS_PROXY (l->data);
    1647                 :           3 :       g_signal_emit_by_name (manager, "interface-added", op, interface_proxy);
    1648                 :           3 :       g_object_unref (interface_proxy);
    1649                 :             :     }
    1650                 :          25 :   g_list_free (interface_added_signals);
    1651                 :             : 
    1652                 :          25 :   if (added)
    1653                 :          22 :     g_signal_emit_by_name (manager, "object-added", op);
    1654                 :             : 
    1655                 :          25 :   g_object_unref (manager);
    1656                 :          25 :   g_object_unref (op);
    1657                 :             : }
    1658                 :             : 
    1659                 :             : static void
    1660                 :          15 : remove_interfaces (GDBusObjectManagerClient   *manager,
    1661                 :             :                    const gchar         *object_path,
    1662                 :             :                    const gchar *const  *interface_names)
    1663                 :             : {
    1664                 :             :   GDBusObjectProxy *op;
    1665                 :             :   GList *interfaces;
    1666                 :             :   guint n;
    1667                 :             :   guint num_interfaces;
    1668                 :             :   guint num_interfaces_to_remove;
    1669                 :             : 
    1670                 :          15 :   g_mutex_lock (&manager->priv->lock);
    1671                 :             : 
    1672                 :          15 :   op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
    1673                 :          15 :   if (op == NULL)
    1674                 :             :     {
    1675                 :           0 :       g_debug ("%s: Processing InterfaceRemoved signal for path %s but no object proxy exists",
    1676                 :             :                G_STRLOC,
    1677                 :             :                object_path);
    1678                 :           0 :       g_mutex_unlock (&manager->priv->lock);
    1679                 :           0 :       return;
    1680                 :             :     }
    1681                 :             : 
    1682                 :          15 :   interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (op));
    1683                 :          15 :   num_interfaces = g_list_length (interfaces);
    1684                 :          15 :   g_list_free_full (interfaces, g_object_unref);
    1685                 :             : 
    1686                 :          15 :   num_interfaces_to_remove = g_strv_length ((gchar **) interface_names);
    1687                 :             : 
    1688                 :             :   /* see if we are going to completety remove the object */
    1689                 :          15 :   g_object_ref (manager);
    1690                 :          15 :   if (num_interfaces_to_remove == num_interfaces)
    1691                 :             :     {
    1692                 :          12 :       g_object_ref (op);
    1693                 :          12 :       g_warn_if_fail (g_hash_table_remove (manager->priv->map_object_path_to_object_proxy, object_path));
    1694                 :          12 :       g_mutex_unlock (&manager->priv->lock);
    1695                 :          12 :       g_signal_emit_by_name (manager, "object-removed", op);
    1696                 :          12 :       g_object_unref (op);
    1697                 :             :     }
    1698                 :             :   else
    1699                 :             :     {
    1700                 :           3 :       g_object_ref (op);
    1701                 :           3 :       g_mutex_unlock (&manager->priv->lock);
    1702                 :           6 :       for (n = 0; interface_names != NULL && interface_names[n] != NULL; n++)
    1703                 :             :         {
    1704                 :             :           GDBusInterface *interface;
    1705                 :           3 :           interface = g_dbus_object_get_interface (G_DBUS_OBJECT (op), interface_names[n]);
    1706                 :           3 :           _g_dbus_object_proxy_remove_interface (op, interface_names[n]);
    1707                 :           3 :           if (interface != NULL)
    1708                 :             :             {
    1709                 :           3 :               g_signal_emit_by_name (manager, "interface-removed", op, interface);
    1710                 :           3 :               g_object_unref (interface);
    1711                 :             :             }
    1712                 :             :         }
    1713                 :           3 :       g_object_unref (op);
    1714                 :             :     }
    1715                 :          15 :   g_object_unref (manager);
    1716                 :             : }
    1717                 :             : 
    1718                 :             : static void
    1719                 :           5 : process_get_all_result (GDBusObjectManagerClient *manager,
    1720                 :             :                         GVariant          *value,
    1721                 :             :                         const gchar       *name_owner)
    1722                 :             : {
    1723                 :             :   GVariant *arg0;
    1724                 :             :   const gchar *object_path;
    1725                 :             :   GVariant *ifaces_and_properties;
    1726                 :             :   GVariantIter iter;
    1727                 :             : 
    1728                 :           5 :   g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
    1729                 :             : 
    1730                 :           5 :   arg0 = g_variant_get_child_value (value, 0);
    1731                 :           5 :   g_variant_iter_init (&iter, arg0);
    1732                 :           9 :   while (g_variant_iter_next (&iter,
    1733                 :             :                               "{&o@a{sa{sv}}}",
    1734                 :             :                               &object_path,
    1735                 :             :                               &ifaces_and_properties))
    1736                 :             :     {
    1737                 :           4 :       add_interfaces (manager, object_path, ifaces_and_properties, name_owner);
    1738                 :           4 :       g_variant_unref (ifaces_and_properties);
    1739                 :             :     }
    1740                 :           5 :   g_variant_unref (arg0);
    1741                 :             : }
    1742                 :             : 
    1743                 :             : static void
    1744                 :          36 : on_control_proxy_g_signal (GDBusProxy   *proxy,
    1745                 :             :                            const gchar  *sender_name,
    1746                 :             :                            const gchar  *signal_name,
    1747                 :             :                            GVariant     *parameters,
    1748                 :             :                            gpointer      user_data)
    1749                 :             : {
    1750                 :          36 :   GWeakRef *manager_weak = user_data;
    1751                 :          36 :   GDBusObjectManagerClient *manager = NULL;
    1752                 :             :   const gchar *object_path;
    1753                 :             : 
    1754                 :          36 :   manager = G_DBUS_OBJECT_MANAGER_CLIENT (g_weak_ref_get (manager_weak));
    1755                 :          36 :   if (manager == NULL)
    1756                 :           0 :     return;
    1757                 :             : 
    1758                 :             :   //g_debug ("yay, g_signal %s: %s\n", signal_name, g_variant_print (parameters, TRUE));
    1759                 :             : 
    1760                 :          36 :   if (g_strcmp0 (signal_name, "InterfacesAdded") == 0)
    1761                 :             :     {
    1762                 :             :       GVariant *ifaces_and_properties;
    1763                 :          21 :       g_variant_get (parameters,
    1764                 :             :                      "(&o@a{sa{sv}})",
    1765                 :             :                      &object_path,
    1766                 :             :                      &ifaces_and_properties);
    1767                 :          21 :       add_interfaces (manager, object_path, ifaces_and_properties, manager->priv->name_owner);
    1768                 :          21 :       g_variant_unref (ifaces_and_properties);
    1769                 :             :     }
    1770                 :          15 :   else if (g_strcmp0 (signal_name, "InterfacesRemoved") == 0)
    1771                 :             :     {
    1772                 :             :       const gchar **ifaces;
    1773                 :          15 :       g_variant_get (parameters,
    1774                 :             :                      "(&o^a&s)",
    1775                 :             :                      &object_path,
    1776                 :             :                      &ifaces);
    1777                 :          15 :       remove_interfaces (manager, object_path, ifaces);
    1778                 :          15 :       g_free (ifaces);
    1779                 :             :     }
    1780                 :             : 
    1781                 :          36 :   g_object_unref (manager);
    1782                 :             : }
    1783                 :             : 
    1784                 :             : /* ---------------------------------------------------------------------------------------------------- */
    1785                 :             : 
    1786                 :             : static const gchar *
    1787                 :           6 : g_dbus_object_manager_client_get_object_path (GDBusObjectManager *_manager)
    1788                 :             : {
    1789                 :           6 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
    1790                 :           6 :   return manager->priv->object_path;
    1791                 :             : }
    1792                 :             : 
    1793                 :             : static GDBusObject *
    1794                 :          16 : g_dbus_object_manager_client_get_object (GDBusObjectManager *_manager,
    1795                 :             :                                          const gchar        *object_path)
    1796                 :             : {
    1797                 :          16 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
    1798                 :             :   GDBusObject *ret;
    1799                 :             : 
    1800                 :          16 :   g_mutex_lock (&manager->priv->lock);
    1801                 :          16 :   ret = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
    1802                 :          16 :   if (ret != NULL)
    1803                 :          16 :     g_object_ref (ret);
    1804                 :          16 :   g_mutex_unlock (&manager->priv->lock);
    1805                 :          16 :   return ret;
    1806                 :             : }
    1807                 :             : 
    1808                 :             : static GDBusInterface *
    1809                 :          10 : g_dbus_object_manager_client_get_interface  (GDBusObjectManager  *_manager,
    1810                 :             :                                              const gchar         *object_path,
    1811                 :             :                                              const gchar         *interface_name)
    1812                 :             : {
    1813                 :             :   GDBusInterface *ret;
    1814                 :             :   GDBusObject *object;
    1815                 :             : 
    1816                 :          10 :   ret = NULL;
    1817                 :             : 
    1818                 :          10 :   object = g_dbus_object_manager_get_object (_manager, object_path);
    1819                 :          10 :   if (object == NULL)
    1820                 :           0 :     goto out;
    1821                 :             : 
    1822                 :          10 :   ret = g_dbus_object_get_interface (object, interface_name);
    1823                 :          10 :   g_object_unref (object);
    1824                 :             : 
    1825                 :          10 :  out:
    1826                 :          10 :   return ret;
    1827                 :             : }
    1828                 :             : 
    1829                 :             : static GList *
    1830                 :           6 : g_dbus_object_manager_client_get_objects (GDBusObjectManager *_manager)
    1831                 :             : {
    1832                 :           6 :   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
    1833                 :             :   GList *ret;
    1834                 :             : 
    1835                 :           6 :   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
    1836                 :             : 
    1837                 :           6 :   g_mutex_lock (&manager->priv->lock);
    1838                 :           6 :   ret = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
    1839                 :           6 :   g_list_foreach (ret, (GFunc) g_object_ref, NULL);
    1840                 :           6 :   g_mutex_unlock (&manager->priv->lock);
    1841                 :             : 
    1842                 :           6 :   return ret;
    1843                 :             : }
    1844                 :             : 
    1845                 :             : 
    1846                 :             : static void
    1847                 :           5 : dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
    1848                 :             : {
    1849                 :           5 :   iface->get_object_path = g_dbus_object_manager_client_get_object_path;
    1850                 :           5 :   iface->get_objects     = g_dbus_object_manager_client_get_objects;
    1851                 :           5 :   iface->get_object      = g_dbus_object_manager_client_get_object;
    1852                 :           5 :   iface->get_interface   = g_dbus_object_manager_client_get_interface;
    1853                 :           5 : }
    1854                 :             : 
    1855                 :             : /* ---------------------------------------------------------------------------------------------------- */
        

Generated by: LCOV version 2.0-1