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