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