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