Docs: Big entity cleanup
[platform/upstream/glib.git] / gio / gdbusproxy.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, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "gdbusutils.h"
27 #include "gdbusproxy.h"
28 #include "gioenumtypes.h"
29 #include "gdbusconnection.h"
30 #include "gdbuserror.h"
31 #include "gdbusprivate.h"
32 #include "ginitable.h"
33 #include "gasyncinitable.h"
34 #include "gioerror.h"
35 #include "gasyncresult.h"
36 #include "gsimpleasyncresult.h"
37 #include "gcancellable.h"
38 #include "gdbusinterface.h"
39
40 #ifdef G_OS_UNIX
41 #include "gunixfdlist.h"
42 #endif
43
44 #include "glibintl.h"
45
46 /**
47  * SECTION:gdbusproxy
48  * @short_description: Client-side D-Bus interface proxy
49  * @include: gio/gio.h
50  *
51  * #GDBusProxy is a base class used for proxies to access a D-Bus
52  * interface on a remote object. A #GDBusProxy can be constructed for
53  * both well-known and unique names.
54  *
55  * By default, #GDBusProxy will cache all properties (and listen to
56  * changes) of the remote object, and proxy all signals that gets
57  * emitted. This behaviour can be changed by passing suitable
58  * #GDBusProxyFlags when the proxy is created. If the proxy is for a
59  * well-known name, the property cache is flushed when the name owner
60  * vanishes and reloaded when a name owner appears.
61  *
62  * If a #GDBusProxy is used for a well-known name, the owner of the
63  * name is tracked and can be read from
64  * #GDBusProxy:g-name-owner. Connect to the #GObject::notify signal to
65  * get notified of changes. Additionally, only signals and property
66  * changes emitted from the current name owner are considered and
67  * calls are always sent to the current name owner. This avoids a
68  * number of race conditions when the name is lost by one owner and
69  * claimed by another. However, if no name owner currently exists,
70  * then calls will be sent to the well-known name which may result in
71  * the message bus launching an owner (unless
72  * %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START is set).
73  *
74  * The generic #GDBusProxy::g-properties-changed and
75  * #GDBusProxy::g-signal signals are not very convenient to work
76  * with. Therefore, the recommended way of working with proxies is to
77  * subclass #GDBusProxy, and have more natural properties and signals
78  * in your derived class. See <xref linkend="gdbus-example-gdbus-codegen"/>
79  * for how this can easily be done using the
80  * <command><link linkend="gdbus-codegen">gdbus-codegen</link></command>
81  * tool.
82  *
83  * A #GDBusProxy instance can be used from multiple threads but note
84  * that all signals (e.g. #GDBusProxy::g-signal, #GDBusProxy::g-properties-changed
85  * and #GObject::notify) are emitted in the
86  * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
87  * of the thread where the instance was constructed.
88  *
89  * <example id="gdbus-wellknown-proxy"><title>GDBusProxy for a well-known-name</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-watch-proxy.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
90  */
91
92 /* lock protecting the mutable properties: name_owner, timeout_msec,
93  * expected_interface, and the properties hash table
94  */
95 G_LOCK_DEFINE_STATIC (properties_lock);
96
97 /* ---------------------------------------------------------------------------------------------------- */
98
99 G_LOCK_DEFINE_STATIC (signal_subscription_lock);
100
101 typedef struct
102 {
103   volatile gint ref_count;
104   GDBusProxy *proxy;
105 } SignalSubscriptionData;
106
107 static SignalSubscriptionData *
108 signal_subscription_ref (SignalSubscriptionData *data)
109 {
110   g_atomic_int_inc (&data->ref_count);
111   return data;
112 }
113
114 static void
115 signal_subscription_unref (SignalSubscriptionData *data)
116 {
117   if (g_atomic_int_dec_and_test (&data->ref_count))
118     {
119       g_slice_free (SignalSubscriptionData, data);
120     }
121 }
122
123 /* ---------------------------------------------------------------------------------------------------- */
124
125 struct _GDBusProxyPrivate
126 {
127   GBusType bus_type;
128   GDBusProxyFlags flags;
129   GDBusConnection *connection;
130
131   gchar *name;
132   /* mutable, protected by properties_lock */
133   gchar *name_owner;
134   gchar *object_path;
135   gchar *interface_name;
136   /* mutable, protected by properties_lock */
137   gint timeout_msec;
138
139   guint name_owner_changed_subscription_id;
140
141   GCancellable *get_all_cancellable;
142
143   /* gchar* -> GVariant*, protected by properties_lock */
144   GHashTable *properties;
145
146   /* mutable, protected by properties_lock */
147   GDBusInterfaceInfo *expected_interface;
148
149   guint properties_changed_subscription_id;
150   guint signals_subscription_id;
151
152   gboolean initialized;
153
154   /* mutable, protected by properties_lock */
155   GDBusObject *object;
156
157   SignalSubscriptionData *signal_subscription_data;
158 };
159
160 enum
161 {
162   PROP_0,
163   PROP_G_CONNECTION,
164   PROP_G_BUS_TYPE,
165   PROP_G_NAME,
166   PROP_G_NAME_OWNER,
167   PROP_G_FLAGS,
168   PROP_G_OBJECT_PATH,
169   PROP_G_INTERFACE_NAME,
170   PROP_G_DEFAULT_TIMEOUT,
171   PROP_G_INTERFACE_INFO
172 };
173
174 enum
175 {
176   PROPERTIES_CHANGED_SIGNAL,
177   SIGNAL_SIGNAL,
178   LAST_SIGNAL,
179 };
180
181 static guint signals[LAST_SIGNAL] = {0};
182
183 static void dbus_interface_iface_init (GDBusInterfaceIface *dbus_interface_iface);
184 static void initable_iface_init       (GInitableIface *initable_iface);
185 static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
186
187 G_DEFINE_TYPE_WITH_CODE (GDBusProxy, g_dbus_proxy, G_TYPE_OBJECT,
188                          G_ADD_PRIVATE (GDBusProxy)
189                          G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_INTERFACE, dbus_interface_iface_init)
190                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
191                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init))
192
193 static void
194 g_dbus_proxy_dispose (GObject *object)
195 {
196   GDBusProxy *proxy = G_DBUS_PROXY (object);
197   G_LOCK (signal_subscription_lock);
198   if (proxy->priv->signal_subscription_data != NULL)
199     {
200       proxy->priv->signal_subscription_data->proxy = NULL;
201       signal_subscription_unref (proxy->priv->signal_subscription_data);
202       proxy->priv->signal_subscription_data = NULL;
203     }
204   G_UNLOCK (signal_subscription_lock);
205
206   G_OBJECT_CLASS (g_dbus_proxy_parent_class)->dispose (object);
207 }
208
209 static void
210 g_dbus_proxy_finalize (GObject *object)
211 {
212   GDBusProxy *proxy = G_DBUS_PROXY (object);
213
214   g_warn_if_fail (proxy->priv->get_all_cancellable == NULL);
215
216   if (proxy->priv->name_owner_changed_subscription_id > 0)
217     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
218                                           proxy->priv->name_owner_changed_subscription_id);
219
220   if (proxy->priv->properties_changed_subscription_id > 0)
221     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
222                                           proxy->priv->properties_changed_subscription_id);
223
224   if (proxy->priv->signals_subscription_id > 0)
225     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
226                                           proxy->priv->signals_subscription_id);
227
228   if (proxy->priv->connection != NULL)
229     g_object_unref (proxy->priv->connection);
230   g_free (proxy->priv->name);
231   g_free (proxy->priv->name_owner);
232   g_free (proxy->priv->object_path);
233   g_free (proxy->priv->interface_name);
234   if (proxy->priv->properties != NULL)
235     g_hash_table_unref (proxy->priv->properties);
236
237   if (proxy->priv->expected_interface != NULL)
238     {
239       g_dbus_interface_info_cache_release (proxy->priv->expected_interface);
240       g_dbus_interface_info_unref (proxy->priv->expected_interface);
241     }
242
243   if (proxy->priv->object != NULL)
244     g_object_remove_weak_pointer (G_OBJECT (proxy->priv->object), (gpointer *) &proxy->priv->object);
245
246   G_OBJECT_CLASS (g_dbus_proxy_parent_class)->finalize (object);
247 }
248
249 static void
250 g_dbus_proxy_get_property (GObject    *object,
251                            guint       prop_id,
252                            GValue     *value,
253                            GParamSpec *pspec)
254 {
255   GDBusProxy *proxy = G_DBUS_PROXY (object);
256
257   switch (prop_id)
258     {
259     case PROP_G_CONNECTION:
260       g_value_set_object (value, proxy->priv->connection);
261       break;
262
263     case PROP_G_FLAGS:
264       g_value_set_flags (value, proxy->priv->flags);
265       break;
266
267     case PROP_G_NAME:
268       g_value_set_string (value, proxy->priv->name);
269       break;
270
271     case PROP_G_NAME_OWNER:
272       g_value_take_string (value, g_dbus_proxy_get_name_owner (proxy));
273       break;
274
275     case PROP_G_OBJECT_PATH:
276       g_value_set_string (value, proxy->priv->object_path);
277       break;
278
279     case PROP_G_INTERFACE_NAME:
280       g_value_set_string (value, proxy->priv->interface_name);
281       break;
282
283     case PROP_G_DEFAULT_TIMEOUT:
284       g_value_set_int (value, g_dbus_proxy_get_default_timeout (proxy));
285       break;
286
287     case PROP_G_INTERFACE_INFO:
288       g_value_set_boxed (value, g_dbus_proxy_get_interface_info (proxy));
289       break;
290
291     default:
292       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
293       break;
294     }
295 }
296
297 static void
298 g_dbus_proxy_set_property (GObject      *object,
299                            guint         prop_id,
300                            const GValue *value,
301                            GParamSpec   *pspec)
302 {
303   GDBusProxy *proxy = G_DBUS_PROXY (object);
304
305   switch (prop_id)
306     {
307     case PROP_G_CONNECTION:
308       proxy->priv->connection = g_value_dup_object (value);
309       break;
310
311     case PROP_G_FLAGS:
312       proxy->priv->flags = g_value_get_flags (value);
313       break;
314
315     case PROP_G_NAME:
316       proxy->priv->name = g_value_dup_string (value);
317       break;
318
319     case PROP_G_OBJECT_PATH:
320       proxy->priv->object_path = g_value_dup_string (value);
321       break;
322
323     case PROP_G_INTERFACE_NAME:
324       proxy->priv->interface_name = g_value_dup_string (value);
325       break;
326
327     case PROP_G_DEFAULT_TIMEOUT:
328       g_dbus_proxy_set_default_timeout (proxy, g_value_get_int (value));
329       break;
330
331     case PROP_G_INTERFACE_INFO:
332       g_dbus_proxy_set_interface_info (proxy, g_value_get_boxed (value));
333       break;
334
335     case PROP_G_BUS_TYPE:
336       proxy->priv->bus_type = g_value_get_enum (value);
337       break;
338
339     default:
340       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
341       break;
342     }
343 }
344
345 static void
346 g_dbus_proxy_class_init (GDBusProxyClass *klass)
347 {
348   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
349
350   gobject_class->dispose      = g_dbus_proxy_dispose;
351   gobject_class->finalize     = g_dbus_proxy_finalize;
352   gobject_class->set_property = g_dbus_proxy_set_property;
353   gobject_class->get_property = g_dbus_proxy_get_property;
354
355   /* Note that all property names are prefixed to avoid collisions with D-Bus property names
356    * in derived classes */
357
358   /**
359    * GDBusProxy:g-interface-info:
360    *
361    * Ensure that interactions with this proxy conform to the given
362    * interface. This is mainly to ensure that malformed data received
363    * from the other peer is ignored. The given #GDBusInterfaceInfo is
364    * said to be the "expected interface".
365    *
366    * The checks performed are:
367    * - When completing a method call, if the type signature of
368    *   the reply message isn't what's expected, the reply is
369    *   discarded and the #GError is set to %G_IO_ERROR_INVALID_ARGUMENT.
370    *
371    * - Received signals that have a type signature mismatch are dropped and
372    *   a warning is logged via g_warning().
373    *
374    * - Properties received via the initial <literal>GetAll()</literal> call
375    *   or via the <literal>::PropertiesChanged</literal> signal (on the
376    *   <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.DBus.Properties</ulink> interface) or
377    *   set using g_dbus_proxy_set_cached_property() with a type signature
378    *   mismatch are ignored and a warning is logged via g_warning().
379    *
380    * Note that these checks are never done on methods, signals and
381    * properties that are not referenced in the given
382    * #GDBusInterfaceInfo, since extending a D-Bus interface on the
383    * service-side is not considered an ABI break.
384    *
385    * Since: 2.26
386    */
387   g_object_class_install_property (gobject_class,
388                                    PROP_G_INTERFACE_INFO,
389                                    g_param_spec_boxed ("g-interface-info",
390                                                        P_("Interface Information"),
391                                                        P_("Interface Information"),
392                                                        G_TYPE_DBUS_INTERFACE_INFO,
393                                                        G_PARAM_READABLE |
394                                                        G_PARAM_WRITABLE |
395                                                        G_PARAM_STATIC_NAME |
396                                                        G_PARAM_STATIC_BLURB |
397                                                        G_PARAM_STATIC_NICK));
398
399   /**
400    * GDBusProxy:g-connection:
401    *
402    * The #GDBusConnection the proxy is for.
403    *
404    * Since: 2.26
405    */
406   g_object_class_install_property (gobject_class,
407                                    PROP_G_CONNECTION,
408                                    g_param_spec_object ("g-connection",
409                                                         P_("g-connection"),
410                                                         P_("The connection the proxy is for"),
411                                                         G_TYPE_DBUS_CONNECTION,
412                                                         G_PARAM_READABLE |
413                                                         G_PARAM_WRITABLE |
414                                                         G_PARAM_CONSTRUCT_ONLY |
415                                                         G_PARAM_STATIC_NAME |
416                                                         G_PARAM_STATIC_BLURB |
417                                                         G_PARAM_STATIC_NICK));
418
419   /**
420    * GDBusProxy:g-bus-type:
421    *
422    * If this property is not %G_BUS_TYPE_NONE, then
423    * #GDBusProxy:g-connection must be %NULL and will be set to the
424    * #GDBusConnection obtained by calling g_bus_get() with the value
425    * of this property.
426    *
427    * Since: 2.26
428    */
429   g_object_class_install_property (gobject_class,
430                                    PROP_G_BUS_TYPE,
431                                    g_param_spec_enum ("g-bus-type",
432                                                       P_("Bus Type"),
433                                                       P_("The bus to connect to, if any"),
434                                                       G_TYPE_BUS_TYPE,
435                                                       G_BUS_TYPE_NONE,
436                                                       G_PARAM_WRITABLE |
437                                                       G_PARAM_CONSTRUCT_ONLY |
438                                                       G_PARAM_STATIC_NAME |
439                                                       G_PARAM_STATIC_BLURB |
440                                                       G_PARAM_STATIC_NICK));
441
442   /**
443    * GDBusProxy:g-flags:
444    *
445    * Flags from the #GDBusProxyFlags enumeration.
446    *
447    * Since: 2.26
448    */
449   g_object_class_install_property (gobject_class,
450                                    PROP_G_FLAGS,
451                                    g_param_spec_flags ("g-flags",
452                                                        P_("g-flags"),
453                                                        P_("Flags for the proxy"),
454                                                        G_TYPE_DBUS_PROXY_FLAGS,
455                                                        G_DBUS_PROXY_FLAGS_NONE,
456                                                        G_PARAM_READABLE |
457                                                        G_PARAM_WRITABLE |
458                                                        G_PARAM_CONSTRUCT_ONLY |
459                                                        G_PARAM_STATIC_NAME |
460                                                        G_PARAM_STATIC_BLURB |
461                                                        G_PARAM_STATIC_NICK));
462
463   /**
464    * GDBusProxy:g-name:
465    *
466    * The well-known or unique name that the proxy is for.
467    *
468    * Since: 2.26
469    */
470   g_object_class_install_property (gobject_class,
471                                    PROP_G_NAME,
472                                    g_param_spec_string ("g-name",
473                                                         P_("g-name"),
474                                                         P_("The well-known or unique name that the proxy is for"),
475                                                         NULL,
476                                                         G_PARAM_READABLE |
477                                                         G_PARAM_WRITABLE |
478                                                         G_PARAM_CONSTRUCT_ONLY |
479                                                         G_PARAM_STATIC_NAME |
480                                                         G_PARAM_STATIC_BLURB |
481                                                         G_PARAM_STATIC_NICK));
482
483   /**
484    * GDBusProxy:g-name-owner:
485    *
486    * The unique name that owns #GDBusProxy:g-name or %NULL if no-one
487    * currently owns that name. You may connect to #GObject::notify signal to
488    * track changes to this property.
489    *
490    * Since: 2.26
491    */
492   g_object_class_install_property (gobject_class,
493                                    PROP_G_NAME_OWNER,
494                                    g_param_spec_string ("g-name-owner",
495                                                         P_("g-name-owner"),
496                                                         P_("The unique name for the owner"),
497                                                         NULL,
498                                                         G_PARAM_READABLE |
499                                                         G_PARAM_STATIC_NAME |
500                                                         G_PARAM_STATIC_BLURB |
501                                                         G_PARAM_STATIC_NICK));
502
503   /**
504    * GDBusProxy:g-object-path:
505    *
506    * The object path the proxy is for.
507    *
508    * Since: 2.26
509    */
510   g_object_class_install_property (gobject_class,
511                                    PROP_G_OBJECT_PATH,
512                                    g_param_spec_string ("g-object-path",
513                                                         P_("g-object-path"),
514                                                         P_("The object path the proxy is for"),
515                                                         NULL,
516                                                         G_PARAM_READABLE |
517                                                         G_PARAM_WRITABLE |
518                                                         G_PARAM_CONSTRUCT_ONLY |
519                                                         G_PARAM_STATIC_NAME |
520                                                         G_PARAM_STATIC_BLURB |
521                                                         G_PARAM_STATIC_NICK));
522
523   /**
524    * GDBusProxy:g-interface-name:
525    *
526    * The D-Bus interface name the proxy is for.
527    *
528    * Since: 2.26
529    */
530   g_object_class_install_property (gobject_class,
531                                    PROP_G_INTERFACE_NAME,
532                                    g_param_spec_string ("g-interface-name",
533                                                         P_("g-interface-name"),
534                                                         P_("The D-Bus interface name the proxy is for"),
535                                                         NULL,
536                                                         G_PARAM_READABLE |
537                                                         G_PARAM_WRITABLE |
538                                                         G_PARAM_CONSTRUCT_ONLY |
539                                                         G_PARAM_STATIC_NAME |
540                                                         G_PARAM_STATIC_BLURB |
541                                                         G_PARAM_STATIC_NICK));
542
543   /**
544    * GDBusProxy:g-default-timeout:
545    *
546    * The timeout to use if -1 (specifying default timeout) is passed
547    * as @timeout_msec in the g_dbus_proxy_call() and
548    * g_dbus_proxy_call_sync() functions.
549    *
550    * This allows applications to set a proxy-wide timeout for all
551    * remote method invocations on the proxy. If this property is -1,
552    * the default timeout (typically 25 seconds) is used. If set to
553    * %G_MAXINT, then no timeout is used.
554    *
555    * Since: 2.26
556    */
557   g_object_class_install_property (gobject_class,
558                                    PROP_G_DEFAULT_TIMEOUT,
559                                    g_param_spec_int ("g-default-timeout",
560                                                      P_("Default Timeout"),
561                                                      P_("Timeout for remote method invocation"),
562                                                      -1,
563                                                      G_MAXINT,
564                                                      -1,
565                                                      G_PARAM_READABLE |
566                                                      G_PARAM_WRITABLE |
567                                                      G_PARAM_CONSTRUCT |
568                                                      G_PARAM_STATIC_NAME |
569                                                      G_PARAM_STATIC_BLURB |
570                                                      G_PARAM_STATIC_NICK));
571
572   /**
573    * GDBusProxy::g-properties-changed:
574    * @proxy: The #GDBusProxy emitting the signal.
575    * @changed_properties: A #GVariant containing the properties that changed
576    * @invalidated_properties: A %NULL terminated array of properties that was invalidated
577    *
578    * Emitted when one or more D-Bus properties on @proxy changes. The
579    * local cache has already been updated when this signal fires. Note
580    * that both @changed_properties and @invalidated_properties are
581    * guaranteed to never be %NULL (either may be empty though).
582    *
583    * If the proxy has the flag
584    * %G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES set, then
585    * @invalidated_properties will always be empty.
586    *
587    * This signal corresponds to the
588    * <literal>PropertiesChanged</literal> D-Bus signal on the
589    * <literal>org.freedesktop.DBus.Properties</literal> interface.
590    *
591    * Since: 2.26
592    */
593   signals[PROPERTIES_CHANGED_SIGNAL] = g_signal_new ("g-properties-changed",
594                                                      G_TYPE_DBUS_PROXY,
595                                                      G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
596                                                      G_STRUCT_OFFSET (GDBusProxyClass, g_properties_changed),
597                                                      NULL,
598                                                      NULL,
599                                                      NULL,
600                                                      G_TYPE_NONE,
601                                                      2,
602                                                      G_TYPE_VARIANT,
603                                                      G_TYPE_STRV | G_SIGNAL_TYPE_STATIC_SCOPE);
604
605   /**
606    * GDBusProxy::g-signal:
607    * @proxy: The #GDBusProxy emitting the signal.
608    * @sender_name: (allow-none): The sender of the signal or %NULL if the connection is not a bus connection.
609    * @signal_name: The name of the signal.
610    * @parameters: A #GVariant tuple with parameters for the signal.
611    *
612    * Emitted when a signal from the remote object and interface that @proxy is for, has been received.
613    *
614    * Since: 2.26
615    */
616   signals[SIGNAL_SIGNAL] = g_signal_new ("g-signal",
617                                          G_TYPE_DBUS_PROXY,
618                                          G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
619                                          G_STRUCT_OFFSET (GDBusProxyClass, g_signal),
620                                          NULL,
621                                          NULL,
622                                          NULL,
623                                          G_TYPE_NONE,
624                                          3,
625                                          G_TYPE_STRING,
626                                          G_TYPE_STRING,
627                                          G_TYPE_VARIANT);
628
629 }
630
631 static void
632 g_dbus_proxy_init (GDBusProxy *proxy)
633 {
634   proxy->priv = g_dbus_proxy_get_instance_private (proxy);
635   proxy->priv->signal_subscription_data = g_slice_new0 (SignalSubscriptionData);
636   proxy->priv->signal_subscription_data->ref_count = 1;
637   proxy->priv->signal_subscription_data->proxy = proxy;
638   proxy->priv->properties = g_hash_table_new_full (g_str_hash,
639                                                    g_str_equal,
640                                                    g_free,
641                                                    (GDestroyNotify) g_variant_unref);
642 }
643
644 /* ---------------------------------------------------------------------------------------------------- */
645
646 static gint
647 property_name_sort_func (const gchar **a,
648                          const gchar **b)
649 {
650   return g_strcmp0 (*a, *b);
651 }
652
653 /**
654  * g_dbus_proxy_get_cached_property_names:
655  * @proxy: A #GDBusProxy.
656  *
657  * Gets the names of all cached properties on @proxy.
658  *
659  * Returns: (transfer full): A %NULL-terminated array of strings or %NULL if
660  *          @proxy has no cached properties. Free the returned array with
661  *          g_strfreev().
662  *
663  * Since: 2.26
664  */
665 gchar **
666 g_dbus_proxy_get_cached_property_names (GDBusProxy  *proxy)
667 {
668   gchar **names;
669   GPtrArray *p;
670   GHashTableIter iter;
671   const gchar *key;
672
673   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
674
675   G_LOCK (properties_lock);
676
677   names = NULL;
678   if (g_hash_table_size (proxy->priv->properties) == 0)
679     goto out;
680
681   p = g_ptr_array_new ();
682
683   g_hash_table_iter_init (&iter, proxy->priv->properties);
684   while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL))
685     g_ptr_array_add (p, g_strdup (key));
686   g_ptr_array_sort (p, (GCompareFunc) property_name_sort_func);
687   g_ptr_array_add (p, NULL);
688
689   names = (gchar **) g_ptr_array_free (p, FALSE);
690
691  out:
692   G_UNLOCK (properties_lock);
693   return names;
694 }
695
696 /* properties_lock must be held for as long as you will keep the
697  * returned value
698  */
699 static const GDBusPropertyInfo *
700 lookup_property_info (GDBusProxy  *proxy,
701                       const gchar *property_name)
702 {
703   const GDBusPropertyInfo *info = NULL;
704
705   if (proxy->priv->expected_interface == NULL)
706     goto out;
707
708   info = g_dbus_interface_info_lookup_property (proxy->priv->expected_interface, property_name);
709
710  out:
711   return info;
712 }
713
714 /**
715  * g_dbus_proxy_get_cached_property:
716  * @proxy: A #GDBusProxy.
717  * @property_name: Property name.
718  *
719  * Looks up the value for a property from the cache. This call does no
720  * blocking IO.
721  *
722  * If @proxy has an expected interface (see
723  * #GDBusProxy:g-interface-info) and @property_name is referenced by
724  * it, then @value is checked against the type of the property.
725  *
726  * Returns: A reference to the #GVariant instance that holds the value
727  * for @property_name or %NULL if the value is not in the cache. The
728  * returned reference must be freed with g_variant_unref().
729  *
730  * Since: 2.26
731  */
732 GVariant *
733 g_dbus_proxy_get_cached_property (GDBusProxy   *proxy,
734                                   const gchar  *property_name)
735 {
736   const GDBusPropertyInfo *info;
737   GVariant *value;
738
739   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
740   g_return_val_if_fail (property_name != NULL, NULL);
741
742   G_LOCK (properties_lock);
743
744   value = g_hash_table_lookup (proxy->priv->properties, property_name);
745   if (value == NULL)
746     goto out;
747
748   info = lookup_property_info (proxy, property_name);
749   if (info != NULL)
750     {
751       const gchar *type_string = g_variant_get_type_string (value);
752       if (g_strcmp0 (type_string, info->signature) != 0)
753         {
754           g_warning ("Trying to get property %s with type %s but according to the expected "
755                      "interface the type is %s",
756                      property_name,
757                      type_string,
758                      info->signature);
759           value = NULL;
760           goto out;
761         }
762     }
763
764   g_variant_ref (value);
765
766  out:
767   G_UNLOCK (properties_lock);
768   return value;
769 }
770
771 /**
772  * g_dbus_proxy_set_cached_property:
773  * @proxy: A #GDBusProxy
774  * @property_name: Property name.
775  * @value: (allow-none): Value for the property or %NULL to remove it from the cache.
776  *
777  * If @value is not %NULL, sets the cached value for the property with
778  * name @property_name to the value in @value.
779  *
780  * If @value is %NULL, then the cached value is removed from the
781  * property cache.
782  *
783  * If @proxy has an expected interface (see
784  * #GDBusProxy:g-interface-info) and @property_name is referenced by
785  * it, then @value is checked against the type of the property.
786  *
787  * If the @value #GVariant is floating, it is consumed. This allows
788  * convenient 'inline' use of g_variant_new(), e.g.
789  * |[
790  *  g_dbus_proxy_set_cached_property (proxy,
791  *                                    "SomeProperty",
792  *                                    g_variant_new ("(si)",
793  *                                                  "A String",
794  *                                                  42));
795  * ]|
796  *
797  * Normally you will not need to use this method since @proxy is
798  * tracking changes using the
799  * <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
800  * D-Bus signal. However, for performance reasons an object may decide
801  * to not use this signal for some properties and instead use a
802  * proprietary out-of-band mechanism to transmit changes.
803  *
804  * As a concrete example, consider an object with a property
805  * <literal>ChatroomParticipants</literal> which is an array of
806  * strings. Instead of transmitting the same (long) array every time
807  * the property changes, it is more efficient to only transmit the
808  * delta using e.g. signals <literal>ChatroomParticipantJoined(String
809  * name)</literal> and <literal>ChatroomParticipantParted(String
810  * name)</literal>.
811  *
812  * Since: 2.26
813  */
814 void
815 g_dbus_proxy_set_cached_property (GDBusProxy   *proxy,
816                                   const gchar  *property_name,
817                                   GVariant     *value)
818 {
819   const GDBusPropertyInfo *info;
820
821   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
822   g_return_if_fail (property_name != NULL);
823
824   G_LOCK (properties_lock);
825
826   if (value != NULL)
827     {
828       info = lookup_property_info (proxy, property_name);
829       if (info != NULL)
830         {
831           if (g_strcmp0 (info->signature, g_variant_get_type_string (value)) != 0)
832             {
833               g_warning ("Trying to set property %s of type %s but according to the expected "
834                          "interface the type is %s",
835                          property_name,
836                          g_variant_get_type_string (value),
837                          info->signature);
838               goto out;
839             }
840         }
841       g_hash_table_insert (proxy->priv->properties,
842                            g_strdup (property_name),
843                            g_variant_ref_sink (value));
844     }
845   else
846     {
847       g_hash_table_remove (proxy->priv->properties, property_name);
848     }
849
850  out:
851   G_UNLOCK (properties_lock);
852 }
853
854 /* ---------------------------------------------------------------------------------------------------- */
855
856 static void
857 on_signal_received (GDBusConnection *connection,
858                     const gchar     *sender_name,
859                     const gchar     *object_path,
860                     const gchar     *interface_name,
861                     const gchar     *signal_name,
862                     GVariant        *parameters,
863                     gpointer         user_data)
864 {
865   SignalSubscriptionData *data = user_data;
866   GDBusProxy *proxy;
867
868   G_LOCK (signal_subscription_lock);
869   proxy = data->proxy;
870   if (proxy == NULL)
871     {
872       G_UNLOCK (signal_subscription_lock);
873       return;
874     }
875   else
876     {
877       g_object_ref (proxy);
878       G_UNLOCK (signal_subscription_lock);
879     }
880
881   if (!proxy->priv->initialized)
882     goto out;
883
884   G_LOCK (properties_lock);
885
886   if (proxy->priv->name_owner != NULL && g_strcmp0 (sender_name, proxy->priv->name_owner) != 0)
887     {
888       G_UNLOCK (properties_lock);
889       goto out;
890     }
891
892   if (proxy->priv->expected_interface != NULL)
893     {
894       const GDBusSignalInfo *info;
895       info = g_dbus_interface_info_lookup_signal (proxy->priv->expected_interface, signal_name);
896       if (info != NULL)
897         {
898           GVariantType *expected_type;
899           expected_type = _g_dbus_compute_complete_signature (info->args);
900           if (!g_variant_type_equal (expected_type, g_variant_get_type (parameters)))
901             {
902               gchar *expected_type_string = g_variant_type_dup_string (expected_type);
903               g_warning ("Dropping signal %s of type %s since the type from the expected interface is %s",
904                          info->name,
905                          g_variant_get_type_string (parameters),
906                          expected_type_string);
907               g_free (expected_type_string);
908               g_variant_type_free (expected_type);
909               G_UNLOCK (properties_lock);
910               goto out;
911             }
912           g_variant_type_free (expected_type);
913         }
914     }
915
916   G_UNLOCK (properties_lock);
917
918   g_signal_emit (proxy,
919                  signals[SIGNAL_SIGNAL],
920                  0,
921                  sender_name,
922                  signal_name,
923                  parameters);
924
925  out:
926   if (proxy != NULL)
927     g_object_unref (proxy);
928 }
929
930 /* ---------------------------------------------------------------------------------------------------- */
931
932 /* must hold properties_lock */
933 static void
934 insert_property_checked (GDBusProxy  *proxy,
935                          gchar *property_name,
936                          GVariant *value)
937 {
938   if (proxy->priv->expected_interface != NULL)
939     {
940       const GDBusPropertyInfo *info;
941       info = g_dbus_interface_info_lookup_property (proxy->priv->expected_interface, property_name);
942       /* Only check known properties */
943       if (info != NULL)
944         {
945           /* Warn about properties with the wrong type */
946           if (g_strcmp0 (info->signature, g_variant_get_type_string (value)) != 0)
947             {
948               g_warning ("Received property %s with type %s does not match expected type "
949                          "%s in the expected interface",
950                          property_name,
951                          g_variant_get_type_string (value),
952                          info->signature);
953               goto invalid;
954             }
955         }
956     }
957
958   g_hash_table_insert (proxy->priv->properties,
959                        property_name, /* adopts string */
960                        value); /* adopts value */
961
962   return;
963
964  invalid:
965   g_variant_unref (value);
966   g_free (property_name);
967 }
968
969 typedef struct
970 {
971   GDBusProxy *proxy;
972   gchar *prop_name;
973 } InvalidatedPropGetData;
974
975 static void
976 invalidated_property_get_cb (GDBusConnection *connection,
977                              GAsyncResult    *res,
978                              gpointer         user_data)
979 {
980   InvalidatedPropGetData *data = user_data;
981   const gchar *invalidated_properties[] = {NULL};
982   GVariantBuilder builder;
983   GVariant *value = NULL;
984   GVariant *unpacked_value = NULL;
985
986   /* errors are fine, the other end could have disconnected */
987   value = g_dbus_connection_call_finish (connection, res, NULL);
988   if (value == NULL)
989     {
990       goto out;
991     }
992
993   if (!g_variant_is_of_type (value, G_VARIANT_TYPE ("(v)")))
994     {
995       g_warning ("Expected type '(v)' for Get() reply, got '%s'", g_variant_get_type_string (value));
996       goto out;
997     }
998
999   g_variant_get (value, "(v)", &unpacked_value);
1000
1001   /* synthesize the a{sv} in the PropertiesChanged signal */
1002   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
1003   g_variant_builder_add (&builder, "{sv}", data->prop_name, unpacked_value);
1004
1005   G_LOCK (properties_lock);
1006   insert_property_checked (data->proxy,
1007                            data->prop_name,  /* adopts string */
1008                            unpacked_value);  /* adopts value */
1009   data->prop_name = NULL;
1010   G_UNLOCK (properties_lock);
1011
1012   g_signal_emit (data->proxy,
1013                  signals[PROPERTIES_CHANGED_SIGNAL], 0,
1014                  g_variant_builder_end (&builder), /* consumed */
1015                  invalidated_properties);
1016
1017
1018  out:
1019   if (value != NULL)
1020     g_variant_unref (value);
1021   g_object_unref (data->proxy);
1022   g_free (data->prop_name);
1023   g_slice_free (InvalidatedPropGetData, data);
1024 }
1025
1026 static void
1027 on_properties_changed (GDBusConnection *connection,
1028                        const gchar     *sender_name,
1029                        const gchar     *object_path,
1030                        const gchar     *interface_name,
1031                        const gchar     *signal_name,
1032                        GVariant        *parameters,
1033                        gpointer         user_data)
1034 {
1035   SignalSubscriptionData *data = user_data;
1036   gboolean emit_g_signal = FALSE;
1037   GDBusProxy *proxy;
1038   const gchar *interface_name_for_signal;
1039   GVariant *changed_properties;
1040   gchar **invalidated_properties;
1041   GVariantIter iter;
1042   gchar *key;
1043   GVariant *value;
1044   guint n;
1045
1046   changed_properties = NULL;
1047   invalidated_properties = NULL;
1048
1049   G_LOCK (signal_subscription_lock);
1050   proxy = data->proxy;
1051   if (proxy == NULL)
1052     {
1053       G_UNLOCK (signal_subscription_lock);
1054       goto out;
1055     }
1056   else
1057     {
1058       g_object_ref (proxy);
1059       G_UNLOCK (signal_subscription_lock);
1060     }
1061
1062   if (!proxy->priv->initialized)
1063     goto out;
1064
1065   G_LOCK (properties_lock);
1066
1067   if (proxy->priv->name_owner != NULL && g_strcmp0 (sender_name, proxy->priv->name_owner) != 0)
1068     {
1069       G_UNLOCK (properties_lock);
1070       goto out;
1071     }
1072
1073   if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
1074     {
1075       g_warning ("Value for PropertiesChanged signal with type '%s' does not match '(sa{sv}as)'",
1076                  g_variant_get_type_string (parameters));
1077       G_UNLOCK (properties_lock);
1078       goto out;
1079     }
1080
1081   g_variant_get (parameters,
1082                  "(&s@a{sv}^a&s)",
1083                  &interface_name_for_signal,
1084                  &changed_properties,
1085                  &invalidated_properties);
1086
1087   if (g_strcmp0 (interface_name_for_signal, proxy->priv->interface_name) != 0)
1088     {
1089       G_UNLOCK (properties_lock);
1090       goto out;
1091     }
1092
1093   g_variant_iter_init (&iter, changed_properties);
1094   while (g_variant_iter_next (&iter, "{sv}", &key, &value))
1095     {
1096       insert_property_checked (proxy,
1097                                key, /* adopts string */
1098                                value); /* adopts value */
1099       emit_g_signal = TRUE;
1100     }
1101
1102   if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES)
1103     {
1104       if (proxy->priv->name_owner != NULL)
1105         {
1106           for (n = 0; invalidated_properties[n] != NULL; n++)
1107             {
1108               InvalidatedPropGetData *data;
1109               data = g_slice_new0 (InvalidatedPropGetData);
1110               data->proxy = g_object_ref (proxy);
1111               data->prop_name = g_strdup (invalidated_properties[n]);
1112               g_dbus_connection_call (proxy->priv->connection,
1113                                       proxy->priv->name_owner,
1114                                       proxy->priv->object_path,
1115                                       "org.freedesktop.DBus.Properties",
1116                                       "Get",
1117                                       g_variant_new ("(ss)", proxy->priv->interface_name, data->prop_name),
1118                                       G_VARIANT_TYPE ("(v)"),
1119                                       G_DBUS_CALL_FLAGS_NONE,
1120                                       -1,           /* timeout */
1121                                       NULL,         /* GCancellable */
1122                                       (GAsyncReadyCallback) invalidated_property_get_cb,
1123                                       data);
1124             }
1125         }
1126     }
1127   else
1128     {
1129       emit_g_signal = TRUE;
1130       for (n = 0; invalidated_properties[n] != NULL; n++)
1131         {
1132           g_hash_table_remove (proxy->priv->properties, invalidated_properties[n]);
1133         }
1134     }
1135
1136   G_UNLOCK (properties_lock);
1137
1138   if (emit_g_signal)
1139     {
1140       g_signal_emit (proxy, signals[PROPERTIES_CHANGED_SIGNAL],
1141                      0,
1142                      changed_properties,
1143                      invalidated_properties);
1144     }
1145
1146  out:
1147   if (changed_properties != NULL)
1148     g_variant_unref (changed_properties);
1149   g_free (invalidated_properties);
1150   if (proxy != NULL)
1151     g_object_unref (proxy);
1152 }
1153
1154 /* ---------------------------------------------------------------------------------------------------- */
1155
1156 static void
1157 process_get_all_reply (GDBusProxy *proxy,
1158                        GVariant   *result)
1159 {
1160   GVariantIter *iter;
1161   gchar *key;
1162   GVariant *value;
1163   guint num_properties;
1164
1165   if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1166     {
1167       g_warning ("Value for GetAll reply with type '%s' does not match '(a{sv})'",
1168                  g_variant_get_type_string (result));
1169       goto out;
1170     }
1171
1172   G_LOCK (properties_lock);
1173
1174   g_variant_get (result, "(a{sv})", &iter);
1175   while (g_variant_iter_next (iter, "{sv}", &key, &value))
1176     {
1177       insert_property_checked (proxy,
1178                                key, /* adopts string */
1179                                value); /* adopts value */
1180     }
1181   g_variant_iter_free (iter);
1182
1183   num_properties = g_hash_table_size (proxy->priv->properties);
1184   G_UNLOCK (properties_lock);
1185
1186   /* Synthesize ::g-properties-changed changed */
1187   if (num_properties > 0)
1188     {
1189       GVariant *changed_properties;
1190       const gchar *invalidated_properties[1] = {NULL};
1191
1192       g_variant_get (result,
1193                      "(@a{sv})",
1194                      &changed_properties);
1195       g_signal_emit (proxy, signals[PROPERTIES_CHANGED_SIGNAL],
1196                      0,
1197                      changed_properties,
1198                      invalidated_properties);
1199       g_variant_unref (changed_properties);
1200     }
1201
1202  out:
1203   ;
1204 }
1205
1206 typedef struct
1207 {
1208   GDBusProxy *proxy;
1209   GCancellable *cancellable;
1210   gchar *name_owner;
1211 } LoadPropertiesOnNameOwnerChangedData;
1212
1213 static void
1214 on_name_owner_changed_get_all_cb (GDBusConnection *connection,
1215                                   GAsyncResult    *res,
1216                                   gpointer         user_data)
1217 {
1218   LoadPropertiesOnNameOwnerChangedData *data = user_data;
1219   GVariant *result;
1220   GError *error;
1221   gboolean cancelled;
1222
1223   cancelled = FALSE;
1224
1225   error = NULL;
1226   result = g_dbus_connection_call_finish (connection,
1227                                           res,
1228                                           &error);
1229   if (result == NULL)
1230     {
1231       if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED)
1232         cancelled = TRUE;
1233       /* We just ignore if GetAll() is failing. Because this might happen
1234        * if the object has no properties at all. Or if the caller is
1235        * not authorized to see the properties.
1236        *
1237        * Either way, apps can know about this by using
1238        * get_cached_property_names() or get_cached_property().
1239        *
1240        * TODO: handle G_DBUS_DEBUG flag 'proxy' and, if enabled, log the
1241        * fact that GetAll() failed
1242        */
1243       //g_debug ("error: %d %d %s", error->domain, error->code, error->message);
1244       g_error_free (error);
1245     }
1246
1247   /* and finally we can notify */
1248   if (!cancelled)
1249     {
1250       G_LOCK (properties_lock);
1251       g_free (data->proxy->priv->name_owner);
1252       data->proxy->priv->name_owner = data->name_owner;
1253       data->name_owner = NULL; /* to avoid an extra copy, we steal the string */
1254       g_hash_table_remove_all (data->proxy->priv->properties);
1255       G_UNLOCK (properties_lock);
1256       if (result != NULL)
1257         {
1258           process_get_all_reply (data->proxy, result);
1259           g_variant_unref (result);
1260         }
1261
1262       g_object_notify (G_OBJECT (data->proxy), "g-name-owner");
1263     }
1264
1265   if (data->cancellable == data->proxy->priv->get_all_cancellable)
1266     data->proxy->priv->get_all_cancellable = NULL;
1267
1268   g_object_unref (data->proxy);
1269   g_object_unref (data->cancellable);
1270   g_free (data->name_owner);
1271   g_free (data);
1272 }
1273
1274 static void
1275 on_name_owner_changed (GDBusConnection *connection,
1276                        const gchar      *sender_name,
1277                        const gchar      *object_path,
1278                        const gchar      *interface_name,
1279                        const gchar      *signal_name,
1280                        GVariant         *parameters,
1281                        gpointer          user_data)
1282 {
1283   SignalSubscriptionData *data = user_data;
1284   GDBusProxy *proxy;
1285   const gchar *old_owner;
1286   const gchar *new_owner;
1287
1288   G_LOCK (signal_subscription_lock);
1289   proxy = data->proxy;
1290   if (proxy == NULL)
1291     {
1292       G_UNLOCK (signal_subscription_lock);
1293       goto out;
1294     }
1295   else
1296     {
1297       g_object_ref (proxy);
1298       G_UNLOCK (signal_subscription_lock);
1299     }
1300
1301   /* if we are already trying to load properties, cancel that */
1302   if (proxy->priv->get_all_cancellable != NULL)
1303     {
1304       g_cancellable_cancel (proxy->priv->get_all_cancellable);
1305       proxy->priv->get_all_cancellable = NULL;
1306     }
1307
1308   g_variant_get (parameters,
1309                  "(&s&s&s)",
1310                  NULL,
1311                  &old_owner,
1312                  &new_owner);
1313
1314   if (strlen (new_owner) == 0)
1315     {
1316       G_LOCK (properties_lock);
1317       g_free (proxy->priv->name_owner);
1318       proxy->priv->name_owner = NULL;
1319
1320       /* Synthesize ::g-properties-changed changed */
1321       if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES) &&
1322           g_hash_table_size (proxy->priv->properties) > 0)
1323         {
1324           GVariantBuilder builder;
1325           GPtrArray *invalidated_properties;
1326           GHashTableIter iter;
1327           const gchar *key;
1328
1329           /* Build changed_properties (always empty) and invalidated_properties ... */
1330           g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
1331
1332           invalidated_properties = g_ptr_array_new_with_free_func (g_free);
1333           g_hash_table_iter_init (&iter, proxy->priv->properties);
1334           while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL))
1335             g_ptr_array_add (invalidated_properties, g_strdup (key));
1336           g_ptr_array_add (invalidated_properties, NULL);
1337
1338           /* ... throw out the properties ... */
1339           g_hash_table_remove_all (proxy->priv->properties);
1340
1341           G_UNLOCK (properties_lock);
1342
1343           /* ... and finally emit the ::g-properties-changed signal */
1344           g_signal_emit (proxy, signals[PROPERTIES_CHANGED_SIGNAL],
1345                          0,
1346                          g_variant_builder_end (&builder) /* consumed */,
1347                          (const gchar* const *) invalidated_properties->pdata);
1348           g_ptr_array_unref (invalidated_properties);
1349         }
1350       else
1351         {
1352           G_UNLOCK (properties_lock);
1353         }
1354       g_object_notify (G_OBJECT (proxy), "g-name-owner");
1355     }
1356   else
1357     {
1358       G_LOCK (properties_lock);
1359
1360       /* ignore duplicates - this can happen when activating the service */
1361       if (g_strcmp0 (new_owner, proxy->priv->name_owner) == 0)
1362         {
1363           G_UNLOCK (properties_lock);
1364           goto out;
1365         }
1366
1367       if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
1368         {
1369           g_free (proxy->priv->name_owner);
1370           proxy->priv->name_owner = g_strdup (new_owner);
1371
1372           g_hash_table_remove_all (proxy->priv->properties);
1373           G_UNLOCK (properties_lock);
1374           g_object_notify (G_OBJECT (proxy), "g-name-owner");
1375         }
1376       else
1377         {
1378           LoadPropertiesOnNameOwnerChangedData *data;
1379
1380           G_UNLOCK (properties_lock);
1381
1382           /* start loading properties.. only then emit notify::g-name-owner .. we
1383            * need to be able to cancel this in the event another NameOwnerChanged
1384            * signal suddenly happens
1385            */
1386
1387           g_assert (proxy->priv->get_all_cancellable == NULL);
1388           proxy->priv->get_all_cancellable = g_cancellable_new ();
1389           data = g_new0 (LoadPropertiesOnNameOwnerChangedData, 1);
1390           data->proxy = g_object_ref (proxy);
1391           data->cancellable = proxy->priv->get_all_cancellable;
1392           data->name_owner = g_strdup (new_owner);
1393           g_dbus_connection_call (proxy->priv->connection,
1394                                   data->name_owner,
1395                                   proxy->priv->object_path,
1396                                   "org.freedesktop.DBus.Properties",
1397                                   "GetAll",
1398                                   g_variant_new ("(s)", proxy->priv->interface_name),
1399                                   G_VARIANT_TYPE ("(a{sv})"),
1400                                   G_DBUS_CALL_FLAGS_NONE,
1401                                   -1,           /* timeout */
1402                                   proxy->priv->get_all_cancellable,
1403                                   (GAsyncReadyCallback) on_name_owner_changed_get_all_cb,
1404                                   data);
1405         }
1406     }
1407
1408  out:
1409   if (proxy != NULL)
1410     g_object_unref (proxy);
1411 }
1412
1413 /* ---------------------------------------------------------------------------------------------------- */
1414
1415 typedef struct
1416 {
1417   GDBusProxy *proxy;
1418   GCancellable *cancellable;
1419   GSimpleAsyncResult *simple;
1420 } AsyncInitData;
1421
1422 static void
1423 async_init_data_free (AsyncInitData *data)
1424 {
1425   g_object_unref (data->proxy);
1426   if (data->cancellable != NULL)
1427     g_object_unref (data->cancellable);
1428   g_object_unref (data->simple);
1429   g_free (data);
1430 }
1431
1432 static void
1433 async_init_get_all_cb (GDBusConnection *connection,
1434                        GAsyncResult    *res,
1435                        gpointer         user_data)
1436 {
1437   AsyncInitData *data = user_data;
1438   GVariant *result;
1439   GError *error;
1440
1441   error = NULL;
1442   result = g_dbus_connection_call_finish (connection,
1443                                           res,
1444                                           &error);
1445   if (result == NULL)
1446     {
1447       /* We just ignore if GetAll() is failing. Because this might happen
1448        * if the object has no properties at all. Or if the caller is
1449        * not authorized to see the properties.
1450        *
1451        * Either way, apps can know about this by using
1452        * get_cached_property_names() or get_cached_property().
1453        *
1454        * TODO: handle G_DBUS_DEBUG flag 'proxy' and, if enabled, log the
1455        * fact that GetAll() failed
1456        */
1457       //g_debug ("error: %d %d %s", error->domain, error->code, error->message);
1458       g_error_free (error);
1459     }
1460   else
1461     {
1462       g_simple_async_result_set_op_res_gpointer (data->simple,
1463                                                  result,
1464                                                  (GDestroyNotify) g_variant_unref);
1465     }
1466
1467   g_simple_async_result_complete_in_idle (data->simple);
1468   async_init_data_free (data);
1469 }
1470
1471 static void
1472 async_init_data_set_name_owner (AsyncInitData *data,
1473                                 const gchar   *name_owner)
1474 {
1475   gboolean get_all;
1476
1477
1478   if (name_owner != NULL)
1479     {
1480       /* it starts as NULL anyway */
1481       G_LOCK (properties_lock);
1482       data->proxy->priv->name_owner = g_strdup (name_owner);
1483       G_UNLOCK (properties_lock);
1484     }
1485
1486   get_all = TRUE;
1487
1488   if (data->proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
1489     {
1490       /* Don't load properties if the API user doesn't want them */
1491       get_all = FALSE;
1492     }
1493   else if (name_owner == NULL && data->proxy->priv->name != NULL)
1494     {
1495       /* Don't attempt to load properties if the name_owner is NULL (which
1496        * usually means the name isn't owned), unless name is also NULL (which
1497        * means we actually wanted to talk to the directly-connected process -
1498        * either dbus-daemon or a peer - instead of going via dbus-daemon)
1499        */
1500         get_all = FALSE;
1501     }
1502
1503   if (get_all)
1504     {
1505       /* load all properties asynchronously */
1506       g_dbus_connection_call (data->proxy->priv->connection,
1507                               name_owner,
1508                               data->proxy->priv->object_path,
1509                               "org.freedesktop.DBus.Properties",
1510                               "GetAll",
1511                               g_variant_new ("(s)", data->proxy->priv->interface_name),
1512                               G_VARIANT_TYPE ("(a{sv})"),
1513                               G_DBUS_CALL_FLAGS_NONE,
1514                               -1,           /* timeout */
1515                               data->cancellable,
1516                               (GAsyncReadyCallback) async_init_get_all_cb,
1517                               data);
1518     }
1519   else
1520     {
1521       g_simple_async_result_complete_in_idle (data->simple);
1522       async_init_data_free (data);
1523     }
1524 }
1525
1526 static void
1527 async_init_get_name_owner_cb (GDBusConnection *connection,
1528                               GAsyncResult    *res,
1529                               gpointer         user_data)
1530 {
1531   AsyncInitData *data = user_data;
1532   GError *error;
1533   GVariant *result;
1534
1535   error = NULL;
1536   result = g_dbus_connection_call_finish (connection,
1537                                           res,
1538                                           &error);
1539   if (result == NULL)
1540     {
1541       if (error->domain == G_DBUS_ERROR &&
1542           error->code == G_DBUS_ERROR_NAME_HAS_NO_OWNER)
1543         {
1544           g_error_free (error);
1545           async_init_data_set_name_owner (data, NULL);
1546         }
1547       else
1548         {
1549           g_simple_async_result_take_error (data->simple, error);
1550           g_simple_async_result_complete_in_idle (data->simple);
1551           async_init_data_free (data);
1552         }
1553     }
1554   else
1555     {
1556       /* borrowed from result to avoid an extra copy */
1557       const gchar *name_owner;
1558
1559       g_variant_get (result, "(&s)", &name_owner);
1560       async_init_data_set_name_owner (data, name_owner);
1561       g_variant_unref (result);
1562     }
1563 }
1564
1565 static void
1566 async_init_call_get_name_owner (AsyncInitData *data)
1567 {
1568   g_dbus_connection_call (data->proxy->priv->connection,
1569                           "org.freedesktop.DBus",  /* name */
1570                           "/org/freedesktop/DBus", /* object path */
1571                           "org.freedesktop.DBus",  /* interface */
1572                           "GetNameOwner",
1573                           g_variant_new ("(s)",
1574                                          data->proxy->priv->name),
1575                           G_VARIANT_TYPE ("(s)"),
1576                           G_DBUS_CALL_FLAGS_NONE,
1577                           -1,           /* timeout */
1578                           data->cancellable,
1579                           (GAsyncReadyCallback) async_init_get_name_owner_cb,
1580                           data);
1581 }
1582
1583 static void
1584 async_init_start_service_by_name_cb (GDBusConnection *connection,
1585                                      GAsyncResult    *res,
1586                                      gpointer         user_data)
1587 {
1588   AsyncInitData *data = user_data;
1589   GError *error;
1590   GVariant *result;
1591
1592   error = NULL;
1593   result = g_dbus_connection_call_finish (connection,
1594                                           res,
1595                                           &error);
1596   if (result == NULL)
1597     {
1598       /* Errors are not unexpected; the bus will reply e.g.
1599        *
1600        *   org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.Epiphany2
1601        *   was not provided by any .service files
1602        *
1603        * or (see #677718)
1604        *
1605        *   org.freedesktop.systemd1.Masked: Unit polkit.service is masked.
1606        *
1607        * This doesn't mean that the name doesn't have an owner, just
1608        * that it's not provided by a .service file or can't currently
1609        * be started.
1610        *
1611        * In particular, in both cases, it could be that a service
1612        * owner will actually appear later. So instead of erroring out,
1613        * we just proceed to invoke GetNameOwner() if dealing with the
1614        * kind of errors above.
1615        */
1616       if (error->domain == G_DBUS_ERROR && error->code == G_DBUS_ERROR_SERVICE_UNKNOWN)
1617         {
1618           g_error_free (error);
1619         }
1620       else
1621         {
1622           gchar *remote_error = g_dbus_error_get_remote_error (error);
1623           if (g_strcmp0 (remote_error, "org.freedesktop.systemd1.Masked") == 0)
1624             {
1625               g_error_free (error);
1626               g_free (remote_error);
1627             }
1628           else
1629             {
1630               g_prefix_error (&error,
1631                               _("Error calling StartServiceByName for %s: "),
1632                               data->proxy->priv->name);
1633               g_free (remote_error);
1634               goto failed;
1635             }
1636         }
1637     }
1638   else
1639     {
1640       guint32 start_service_result;
1641       g_variant_get (result,
1642                      "(u)",
1643                      &start_service_result);
1644       g_variant_unref (result);
1645       if (start_service_result == 1 ||  /* DBUS_START_REPLY_SUCCESS */
1646           start_service_result == 2)    /* DBUS_START_REPLY_ALREADY_RUNNING */
1647         {
1648           /* continue to invoke GetNameOwner() */
1649         }
1650       else
1651         {
1652           error = g_error_new (G_IO_ERROR,
1653                                G_IO_ERROR_FAILED,
1654                                _("Unexpected reply %d from StartServiceByName(\"%s\") method"),
1655                                start_service_result,
1656                                data->proxy->priv->name);
1657           goto failed;
1658         }
1659     }
1660
1661   async_init_call_get_name_owner (data);
1662   return;
1663
1664  failed:
1665   g_warn_if_fail (error != NULL);
1666   g_simple_async_result_take_error (data->simple, error);
1667   g_simple_async_result_complete_in_idle (data->simple);
1668   async_init_data_free (data);
1669 }
1670
1671 static void
1672 async_init_call_start_service_by_name (AsyncInitData *data)
1673 {
1674   g_dbus_connection_call (data->proxy->priv->connection,
1675                           "org.freedesktop.DBus",  /* name */
1676                           "/org/freedesktop/DBus", /* object path */
1677                           "org.freedesktop.DBus",  /* interface */
1678                           "StartServiceByName",
1679                           g_variant_new ("(su)",
1680                                          data->proxy->priv->name,
1681                                          0),
1682                           G_VARIANT_TYPE ("(u)"),
1683                           G_DBUS_CALL_FLAGS_NONE,
1684                           -1,           /* timeout */
1685                           data->cancellable,
1686                           (GAsyncReadyCallback) async_init_start_service_by_name_cb,
1687                           data);
1688 }
1689
1690 static void
1691 async_initable_init_second_async (GAsyncInitable      *initable,
1692                                   gint                 io_priority,
1693                                   GCancellable        *cancellable,
1694                                   GAsyncReadyCallback  callback,
1695                                   gpointer             user_data)
1696 {
1697   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1698   AsyncInitData *data;
1699
1700   data = g_new0 (AsyncInitData, 1);
1701   data->proxy = g_object_ref (proxy);
1702   data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
1703   data->simple = g_simple_async_result_new (G_OBJECT (proxy),
1704                                             callback,
1705                                             user_data,
1706                                             NULL);
1707   g_simple_async_result_set_check_cancellable (data->simple, cancellable);
1708
1709   /* Check name ownership asynchronously - possibly also start the service */
1710   if (proxy->priv->name == NULL)
1711     {
1712       /* Do nothing */
1713       async_init_data_set_name_owner (data, NULL);
1714     }
1715   else if (g_dbus_is_unique_name (proxy->priv->name))
1716     {
1717       async_init_data_set_name_owner (data, proxy->priv->name);
1718     }
1719   else
1720     {
1721       if ((proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START) ||
1722           (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION))
1723         {
1724           async_init_call_get_name_owner (data);
1725         }
1726       else
1727         {
1728           async_init_call_start_service_by_name (data);
1729         }
1730     }
1731 }
1732
1733 static gboolean
1734 async_initable_init_second_finish (GAsyncInitable  *initable,
1735                                    GAsyncResult    *res,
1736                                    GError         **error)
1737 {
1738   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1739   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
1740   GVariant *result;
1741   gboolean ret;
1742
1743   ret = FALSE;
1744
1745   if (g_simple_async_result_propagate_error (simple, error))
1746     goto out;
1747
1748   result = g_simple_async_result_get_op_res_gpointer (simple);
1749   if (result != NULL)
1750     {
1751       process_get_all_reply (proxy, result);
1752     }
1753
1754   ret = TRUE;
1755
1756  out:
1757   proxy->priv->initialized = TRUE;
1758   return ret;
1759 }
1760
1761 /* ---------------------------------------------------------------------------------------------------- */
1762
1763 static void
1764 async_initable_init_first (GAsyncInitable *initable)
1765 {
1766   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1767
1768   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
1769     {
1770       /* subscribe to PropertiesChanged() */
1771       proxy->priv->properties_changed_subscription_id =
1772         g_dbus_connection_signal_subscribe (proxy->priv->connection,
1773                                             proxy->priv->name,
1774                                             "org.freedesktop.DBus.Properties",
1775                                             "PropertiesChanged",
1776                                             proxy->priv->object_path,
1777                                             proxy->priv->interface_name,
1778                                             G_DBUS_SIGNAL_FLAGS_NONE,
1779                                             on_properties_changed,
1780                                             signal_subscription_ref (proxy->priv->signal_subscription_data),
1781                                             (GDestroyNotify) signal_subscription_unref);
1782     }
1783
1784   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS))
1785     {
1786       /* subscribe to all signals for the object */
1787       proxy->priv->signals_subscription_id =
1788         g_dbus_connection_signal_subscribe (proxy->priv->connection,
1789                                             proxy->priv->name,
1790                                             proxy->priv->interface_name,
1791                                             NULL,                        /* member */
1792                                             proxy->priv->object_path,
1793                                             NULL,                        /* arg0 */
1794                                             G_DBUS_SIGNAL_FLAGS_NONE,
1795                                             on_signal_received,
1796                                             signal_subscription_ref (proxy->priv->signal_subscription_data),
1797                                             (GDestroyNotify) signal_subscription_unref);
1798     }
1799
1800   if (proxy->priv->name != NULL && !g_dbus_is_unique_name (proxy->priv->name))
1801     {
1802       proxy->priv->name_owner_changed_subscription_id =
1803         g_dbus_connection_signal_subscribe (proxy->priv->connection,
1804                                             "org.freedesktop.DBus",  /* name */
1805                                             "org.freedesktop.DBus",  /* interface */
1806                                             "NameOwnerChanged",      /* signal name */
1807                                             "/org/freedesktop/DBus", /* path */
1808                                             proxy->priv->name,       /* arg0 */
1809                                             G_DBUS_SIGNAL_FLAGS_NONE,
1810                                             on_name_owner_changed,
1811                                             signal_subscription_ref (proxy->priv->signal_subscription_data),
1812                                             (GDestroyNotify) signal_subscription_unref);
1813     }
1814 }
1815
1816 /* ---------------------------------------------------------------------------------------------------- */
1817
1818 /* initialization is split into two parts - the first is the
1819  * non-blocing part that requires the callers GMainContext - the
1820  * second is a blocking part async part that doesn't require the
1821  * callers GMainContext.. we do this split so the code can be reused
1822  * in the GInitable implementation below.
1823  *
1824  * Note that obtaining a GDBusConnection is not shared between the two
1825  * paths.
1826  */
1827
1828 typedef struct
1829 {
1830   GDBusProxy          *proxy;
1831   gint                 io_priority;
1832   GCancellable        *cancellable;
1833   GAsyncReadyCallback  callback;
1834   gpointer             user_data;
1835 } GetConnectionData;
1836
1837 static void
1838 get_connection_cb (GObject       *source_object,
1839                    GAsyncResult  *res,
1840                    gpointer       user_data)
1841 {
1842   GetConnectionData *data = user_data;
1843   GError *error;
1844
1845   error = NULL;
1846   data->proxy->priv->connection = g_bus_get_finish (res, &error);
1847   if (data->proxy->priv->connection == NULL)
1848     {
1849       GSimpleAsyncResult *simple;
1850       simple = g_simple_async_result_new (G_OBJECT (data->proxy),
1851                                           data->callback,
1852                                           data->user_data,
1853                                           NULL);
1854       g_simple_async_result_set_check_cancellable (simple, data->cancellable);
1855       g_simple_async_result_take_error (simple, error);
1856       g_simple_async_result_complete_in_idle (simple);
1857       g_object_unref (simple);
1858     }
1859   else
1860     {
1861       async_initable_init_first (G_ASYNC_INITABLE (data->proxy));
1862       async_initable_init_second_async (G_ASYNC_INITABLE (data->proxy),
1863                                         data->io_priority,
1864                                         data->cancellable,
1865                                         data->callback,
1866                                         data->user_data);
1867     }
1868
1869   if (data->cancellable != NULL)
1870     g_object_unref (data->cancellable);
1871
1872   g_object_unref (data->proxy);
1873   g_free (data);
1874 }
1875
1876 static void
1877 async_initable_init_async (GAsyncInitable      *initable,
1878                            gint                 io_priority,
1879                            GCancellable        *cancellable,
1880                            GAsyncReadyCallback  callback,
1881                            gpointer             user_data)
1882 {
1883   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1884
1885   if (proxy->priv->bus_type != G_BUS_TYPE_NONE)
1886     {
1887       GetConnectionData *data;
1888
1889       g_assert (proxy->priv->connection == NULL);
1890
1891       data = g_new0 (GetConnectionData, 1);
1892       data->proxy = g_object_ref (proxy);
1893       data->io_priority = io_priority;
1894       data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
1895       data->callback = callback;
1896       data->user_data = user_data;
1897       g_bus_get (proxy->priv->bus_type,
1898                  cancellable,
1899                  get_connection_cb,
1900                  data);
1901     }
1902   else
1903     {
1904       async_initable_init_first (initable);
1905       async_initable_init_second_async (initable, io_priority, cancellable, callback, user_data);
1906     }
1907 }
1908
1909 static gboolean
1910 async_initable_init_finish (GAsyncInitable  *initable,
1911                             GAsyncResult    *res,
1912                             GError         **error)
1913 {
1914   return async_initable_init_second_finish (initable, res, error);
1915 }
1916
1917 static void
1918 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
1919 {
1920   async_initable_iface->init_async = async_initable_init_async;
1921   async_initable_iface->init_finish = async_initable_init_finish;
1922 }
1923
1924 /* ---------------------------------------------------------------------------------------------------- */
1925
1926 typedef struct
1927 {
1928   GMainContext *context;
1929   GMainLoop *loop;
1930   GAsyncResult *res;
1931 } InitableAsyncInitableData;
1932
1933 static void
1934 async_initable_init_async_cb (GObject      *source_object,
1935                               GAsyncResult *res,
1936                               gpointer      user_data)
1937 {
1938   InitableAsyncInitableData *data = user_data;
1939   data->res = g_object_ref (res);
1940   g_main_loop_quit (data->loop);
1941 }
1942
1943 /* Simply reuse the GAsyncInitable implementation but run the first
1944  * part (that is non-blocking and requires the callers GMainContext)
1945  * with the callers GMainContext.. and the second with a private
1946  * GMainContext (bug 621310 is slightly related).
1947  *
1948  * Note that obtaining a GDBusConnection is not shared between the two
1949  * paths.
1950  */
1951 static gboolean
1952 initable_init (GInitable     *initable,
1953                GCancellable  *cancellable,
1954                GError       **error)
1955 {
1956   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1957   InitableAsyncInitableData *data;
1958   gboolean ret;
1959
1960   ret = FALSE;
1961
1962   if (proxy->priv->bus_type != G_BUS_TYPE_NONE)
1963     {
1964       g_assert (proxy->priv->connection == NULL);
1965       proxy->priv->connection = g_bus_get_sync (proxy->priv->bus_type,
1966                                                 cancellable,
1967                                                 error);
1968       if (proxy->priv->connection == NULL)
1969         goto out;
1970     }
1971
1972   async_initable_init_first (G_ASYNC_INITABLE (initable));
1973
1974   data = g_new0 (InitableAsyncInitableData, 1);
1975   data->context = g_main_context_new ();
1976   data->loop = g_main_loop_new (data->context, FALSE);
1977
1978   g_main_context_push_thread_default (data->context);
1979
1980   async_initable_init_second_async (G_ASYNC_INITABLE (initable),
1981                                     G_PRIORITY_DEFAULT,
1982                                     cancellable,
1983                                     async_initable_init_async_cb,
1984                                     data);
1985
1986   g_main_loop_run (data->loop);
1987
1988   ret = async_initable_init_second_finish (G_ASYNC_INITABLE (initable),
1989                                            data->res,
1990                                            error);
1991
1992   g_main_context_pop_thread_default (data->context);
1993
1994   g_main_context_unref (data->context);
1995   g_main_loop_unref (data->loop);
1996   g_object_unref (data->res);
1997   g_free (data);
1998
1999  out:
2000
2001   return ret;
2002 }
2003
2004 static void
2005 initable_iface_init (GInitableIface *initable_iface)
2006 {
2007   initable_iface->init = initable_init;
2008 }
2009
2010 /* ---------------------------------------------------------------------------------------------------- */
2011
2012 /**
2013  * g_dbus_proxy_new:
2014  * @connection: A #GDBusConnection.
2015  * @flags: Flags used when constructing the proxy.
2016  * @info: (allow-none): A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
2017  * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
2018  * @object_path: An object path.
2019  * @interface_name: A D-Bus interface name.
2020  * @cancellable: (allow-none): A #GCancellable or %NULL.
2021  * @callback: Callback function to invoke when the proxy is ready.
2022  * @user_data: User data to pass to @callback.
2023  *
2024  * Creates a proxy for accessing @interface_name on the remote object
2025  * at @object_path owned by @name at @connection and asynchronously
2026  * loads D-Bus properties unless the
2027  * %G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used. Connect to
2028  * the #GDBusProxy::g-properties-changed signal to get notified about
2029  * property changes.
2030  *
2031  * If the %G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
2032  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
2033  * to handle signals from the remote object.
2034  *
2035  * If @name is a well-known name and the
2036  * %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START and %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION
2037  * flags aren't set and no name owner currently exists, the message bus
2038  * will be requested to launch a name owner for the name.
2039  *
2040  * This is a failable asynchronous constructor - when the proxy is
2041  * ready, @callback will be invoked and you can use
2042  * g_dbus_proxy_new_finish() to get the result.
2043  *
2044  * See g_dbus_proxy_new_sync() and for a synchronous version of this constructor.
2045  *
2046  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
2047  *
2048  * Since: 2.26
2049  */
2050 void
2051 g_dbus_proxy_new (GDBusConnection     *connection,
2052                   GDBusProxyFlags      flags,
2053                   GDBusInterfaceInfo  *info,
2054                   const gchar         *name,
2055                   const gchar         *object_path,
2056                   const gchar         *interface_name,
2057                   GCancellable        *cancellable,
2058                   GAsyncReadyCallback  callback,
2059                   gpointer             user_data)
2060 {
2061   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2062   g_return_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) || g_dbus_is_name (name));
2063   g_return_if_fail (g_variant_is_object_path (object_path));
2064   g_return_if_fail (g_dbus_is_interface_name (interface_name));
2065
2066   g_async_initable_new_async (G_TYPE_DBUS_PROXY,
2067                               G_PRIORITY_DEFAULT,
2068                               cancellable,
2069                               callback,
2070                               user_data,
2071                               "g-flags", flags,
2072                               "g-interface-info", info,
2073                               "g-name", name,
2074                               "g-connection", connection,
2075                               "g-object-path", object_path,
2076                               "g-interface-name", interface_name,
2077                               NULL);
2078 }
2079
2080 /**
2081  * g_dbus_proxy_new_finish:
2082  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new().
2083  * @error: Return location for error or %NULL.
2084  *
2085  * Finishes creating a #GDBusProxy.
2086  *
2087  * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
2088  *
2089  * Since: 2.26
2090  */
2091 GDBusProxy *
2092 g_dbus_proxy_new_finish (GAsyncResult  *res,
2093                          GError       **error)
2094 {
2095   GObject *object;
2096   GObject *source_object;
2097
2098   source_object = g_async_result_get_source_object (res);
2099   g_assert (source_object != NULL);
2100
2101   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2102                                         res,
2103                                         error);
2104   g_object_unref (source_object);
2105
2106   if (object != NULL)
2107     return G_DBUS_PROXY (object);
2108   else
2109     return NULL;
2110 }
2111
2112 /**
2113  * g_dbus_proxy_new_sync:
2114  * @connection: A #GDBusConnection.
2115  * @flags: Flags used when constructing the proxy.
2116  * @info: (allow-none): A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
2117  * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
2118  * @object_path: An object path.
2119  * @interface_name: A D-Bus interface name.
2120  * @cancellable: (allow-none): A #GCancellable or %NULL.
2121  * @error: (allow-none): Return location for error or %NULL.
2122  *
2123  * Creates a proxy for accessing @interface_name on the remote object
2124  * at @object_path owned by @name at @connection and synchronously
2125  * loads D-Bus properties unless the
2126  * %G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used.
2127  *
2128  * If the %G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
2129  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
2130  * to handle signals from the remote object.
2131  *
2132  * If @name is a well-known name and the
2133  * %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START and %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION
2134  * flags aren't set and no name owner currently exists, the message bus
2135  * will be requested to launch a name owner for the name.
2136  *
2137  * This is a synchronous failable constructor. See g_dbus_proxy_new()
2138  * and g_dbus_proxy_new_finish() for the asynchronous version.
2139  *
2140  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
2141  *
2142  * Returns: A #GDBusProxy or %NULL if error is set. Free with g_object_unref().
2143  *
2144  * Since: 2.26
2145  */
2146 GDBusProxy *
2147 g_dbus_proxy_new_sync (GDBusConnection     *connection,
2148                        GDBusProxyFlags      flags,
2149                        GDBusInterfaceInfo  *info,
2150                        const gchar         *name,
2151                        const gchar         *object_path,
2152                        const gchar         *interface_name,
2153                        GCancellable        *cancellable,
2154                        GError             **error)
2155 {
2156   GInitable *initable;
2157
2158   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2159   g_return_val_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
2160                         g_dbus_is_name (name), NULL);
2161   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
2162   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
2163
2164   initable = g_initable_new (G_TYPE_DBUS_PROXY,
2165                              cancellable,
2166                              error,
2167                              "g-flags", flags,
2168                              "g-interface-info", info,
2169                              "g-name", name,
2170                              "g-connection", connection,
2171                              "g-object-path", object_path,
2172                              "g-interface-name", interface_name,
2173                              NULL);
2174   if (initable != NULL)
2175     return G_DBUS_PROXY (initable);
2176   else
2177     return NULL;
2178 }
2179
2180 /* ---------------------------------------------------------------------------------------------------- */
2181
2182 /**
2183  * g_dbus_proxy_new_for_bus:
2184  * @bus_type: A #GBusType.
2185  * @flags: Flags used when constructing the proxy.
2186  * @info: (allow-none): A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
2187  * @name: A bus name (well-known or unique).
2188  * @object_path: An object path.
2189  * @interface_name: A D-Bus interface name.
2190  * @cancellable: (allow-none): A #GCancellable or %NULL.
2191  * @callback: Callback function to invoke when the proxy is ready.
2192  * @user_data: User data to pass to @callback.
2193  *
2194  * Like g_dbus_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
2195  *
2196  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
2197  *
2198  * Since: 2.26
2199  */
2200 void
2201 g_dbus_proxy_new_for_bus (GBusType             bus_type,
2202                           GDBusProxyFlags      flags,
2203                           GDBusInterfaceInfo  *info,
2204                           const gchar         *name,
2205                           const gchar         *object_path,
2206                           const gchar         *interface_name,
2207                           GCancellable        *cancellable,
2208                           GAsyncReadyCallback  callback,
2209                           gpointer             user_data)
2210 {
2211   g_return_if_fail (g_dbus_is_name (name));
2212   g_return_if_fail (g_variant_is_object_path (object_path));
2213   g_return_if_fail (g_dbus_is_interface_name (interface_name));
2214
2215   g_async_initable_new_async (G_TYPE_DBUS_PROXY,
2216                               G_PRIORITY_DEFAULT,
2217                               cancellable,
2218                               callback,
2219                               user_data,
2220                               "g-flags", flags,
2221                               "g-interface-info", info,
2222                               "g-name", name,
2223                               "g-bus-type", bus_type,
2224                               "g-object-path", object_path,
2225                               "g-interface-name", interface_name,
2226                               NULL);
2227 }
2228
2229 /**
2230  * g_dbus_proxy_new_for_bus_finish:
2231  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new_for_bus().
2232  * @error: Return location for error or %NULL.
2233  *
2234  * Finishes creating a #GDBusProxy.
2235  *
2236  * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
2237  *
2238  * Since: 2.26
2239  */
2240 GDBusProxy *
2241 g_dbus_proxy_new_for_bus_finish (GAsyncResult  *res,
2242                                  GError       **error)
2243 {
2244   return g_dbus_proxy_new_finish (res, error);
2245 }
2246
2247 /**
2248  * g_dbus_proxy_new_for_bus_sync:
2249  * @bus_type: A #GBusType.
2250  * @flags: Flags used when constructing the proxy.
2251  * @info: (allow-none): A #GDBusInterfaceInfo specifying the minimal interface
2252  *        that @proxy conforms to or %NULL.
2253  * @name: A bus name (well-known or unique).
2254  * @object_path: An object path.
2255  * @interface_name: A D-Bus interface name.
2256  * @cancellable: (allow-none): A #GCancellable or %NULL.
2257  * @error: Return location for error or %NULL.
2258  *
2259  * Like g_dbus_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
2260  *
2261  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
2262  *
2263  * Returns: A #GDBusProxy or %NULL if error is set. Free with g_object_unref().
2264  *
2265  * Since: 2.26
2266  */
2267 GDBusProxy *
2268 g_dbus_proxy_new_for_bus_sync (GBusType             bus_type,
2269                                GDBusProxyFlags      flags,
2270                                GDBusInterfaceInfo  *info,
2271                                const gchar         *name,
2272                                const gchar         *object_path,
2273                                const gchar         *interface_name,
2274                                GCancellable        *cancellable,
2275                                GError             **error)
2276 {
2277   GInitable *initable;
2278
2279   g_return_val_if_fail (g_dbus_is_name (name), NULL);
2280   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
2281   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
2282
2283   initable = g_initable_new (G_TYPE_DBUS_PROXY,
2284                              cancellable,
2285                              error,
2286                              "g-flags", flags,
2287                              "g-interface-info", info,
2288                              "g-name", name,
2289                              "g-bus-type", bus_type,
2290                              "g-object-path", object_path,
2291                              "g-interface-name", interface_name,
2292                              NULL);
2293   if (initable != NULL)
2294     return G_DBUS_PROXY (initable);
2295   else
2296     return NULL;
2297 }
2298
2299 /* ---------------------------------------------------------------------------------------------------- */
2300
2301 /**
2302  * g_dbus_proxy_get_connection:
2303  * @proxy: A #GDBusProxy.
2304  *
2305  * Gets the connection @proxy is for.
2306  *
2307  * Returns: (transfer none): A #GDBusConnection owned by @proxy. Do not free.
2308  *
2309  * Since: 2.26
2310  */
2311 GDBusConnection *
2312 g_dbus_proxy_get_connection (GDBusProxy *proxy)
2313 {
2314   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2315   return proxy->priv->connection;
2316 }
2317
2318 /**
2319  * g_dbus_proxy_get_flags:
2320  * @proxy: A #GDBusProxy.
2321  *
2322  * Gets the flags that @proxy was constructed with.
2323  *
2324  * Returns: Flags from the #GDBusProxyFlags enumeration.
2325  *
2326  * Since: 2.26
2327  */
2328 GDBusProxyFlags
2329 g_dbus_proxy_get_flags (GDBusProxy *proxy)
2330 {
2331   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
2332   return proxy->priv->flags;
2333 }
2334
2335 /**
2336  * g_dbus_proxy_get_name:
2337  * @proxy: A #GDBusProxy.
2338  *
2339  * Gets the name that @proxy was constructed for.
2340  *
2341  * Returns: A string owned by @proxy. Do not free.
2342  *
2343  * Since: 2.26
2344  */
2345 const gchar *
2346 g_dbus_proxy_get_name (GDBusProxy *proxy)
2347 {
2348   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2349   return proxy->priv->name;
2350 }
2351
2352 /**
2353  * g_dbus_proxy_get_name_owner:
2354  * @proxy: A #GDBusProxy.
2355  *
2356  * The unique name that owns the name that @proxy is for or %NULL if
2357  * no-one currently owns that name. You may connect to the
2358  * #GObject::notify signal to track changes to the
2359  * #GDBusProxy:g-name-owner property.
2360  *
2361  * Returns: The name owner or %NULL if no name owner exists. Free with g_free().
2362  *
2363  * Since: 2.26
2364  */
2365 gchar *
2366 g_dbus_proxy_get_name_owner (GDBusProxy *proxy)
2367 {
2368   gchar *ret;
2369
2370   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2371
2372   G_LOCK (properties_lock);
2373   ret = g_strdup (proxy->priv->name_owner);
2374   G_UNLOCK (properties_lock);
2375   return ret;
2376 }
2377
2378 /**
2379  * g_dbus_proxy_get_object_path:
2380  * @proxy: A #GDBusProxy.
2381  *
2382  * Gets the object path @proxy is for.
2383  *
2384  * Returns: A string owned by @proxy. Do not free.
2385  *
2386  * Since: 2.26
2387  */
2388 const gchar *
2389 g_dbus_proxy_get_object_path (GDBusProxy *proxy)
2390 {
2391   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2392   return proxy->priv->object_path;
2393 }
2394
2395 /**
2396  * g_dbus_proxy_get_interface_name:
2397  * @proxy: A #GDBusProxy.
2398  *
2399  * Gets the D-Bus interface name @proxy is for.
2400  *
2401  * Returns: A string owned by @proxy. Do not free.
2402  *
2403  * Since: 2.26
2404  */
2405 const gchar *
2406 g_dbus_proxy_get_interface_name (GDBusProxy *proxy)
2407 {
2408   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2409   return proxy->priv->interface_name;
2410 }
2411
2412 /**
2413  * g_dbus_proxy_get_default_timeout:
2414  * @proxy: A #GDBusProxy.
2415  *
2416  * Gets the timeout to use if -1 (specifying default timeout) is
2417  * passed as @timeout_msec in the g_dbus_proxy_call() and
2418  * g_dbus_proxy_call_sync() functions.
2419  *
2420  * See the #GDBusProxy:g-default-timeout property for more details.
2421  *
2422  * Returns: Timeout to use for @proxy.
2423  *
2424  * Since: 2.26
2425  */
2426 gint
2427 g_dbus_proxy_get_default_timeout (GDBusProxy *proxy)
2428 {
2429   gint ret;
2430
2431   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), -1);
2432
2433   G_LOCK (properties_lock);
2434   ret = proxy->priv->timeout_msec;
2435   G_UNLOCK (properties_lock);
2436   return ret;
2437 }
2438
2439 /**
2440  * g_dbus_proxy_set_default_timeout:
2441  * @proxy: A #GDBusProxy.
2442  * @timeout_msec: Timeout in milliseconds.
2443  *
2444  * Sets the timeout to use if -1 (specifying default timeout) is
2445  * passed as @timeout_msec in the g_dbus_proxy_call() and
2446  * g_dbus_proxy_call_sync() functions.
2447  *
2448  * See the #GDBusProxy:g-default-timeout property for more details.
2449  *
2450  * Since: 2.26
2451  */
2452 void
2453 g_dbus_proxy_set_default_timeout (GDBusProxy *proxy,
2454                                   gint        timeout_msec)
2455 {
2456   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
2457   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
2458
2459   G_LOCK (properties_lock);
2460
2461   if (proxy->priv->timeout_msec != timeout_msec)
2462     {
2463       proxy->priv->timeout_msec = timeout_msec;
2464       G_UNLOCK (properties_lock);
2465
2466       g_object_notify (G_OBJECT (proxy), "g-default-timeout");
2467     }
2468   else
2469     {
2470       G_UNLOCK (properties_lock);
2471     }
2472 }
2473
2474 /**
2475  * g_dbus_proxy_get_interface_info:
2476  * @proxy: A #GDBusProxy
2477  *
2478  * Returns the #GDBusInterfaceInfo, if any, specifying the interface
2479  * that @proxy conforms to. See the #GDBusProxy:g-interface-info
2480  * property for more details.
2481  *
2482  * Returns: A #GDBusInterfaceInfo or %NULL. Do not unref the returned
2483  * object, it is owned by @proxy.
2484  *
2485  * Since: 2.26
2486  */
2487 GDBusInterfaceInfo *
2488 g_dbus_proxy_get_interface_info (GDBusProxy *proxy)
2489 {
2490   GDBusInterfaceInfo *ret;
2491
2492   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2493
2494   G_LOCK (properties_lock);
2495   ret = proxy->priv->expected_interface;
2496   G_UNLOCK (properties_lock);
2497   /* FIXME: returning a borrowed ref with no guarantee that nobody will
2498    * call g_dbus_proxy_set_interface_info() and make it invalid...
2499    */
2500   return ret;
2501 }
2502
2503 /**
2504  * g_dbus_proxy_set_interface_info:
2505  * @proxy: A #GDBusProxy
2506  * @info: (allow-none): Minimum interface this proxy conforms to or %NULL to unset.
2507  *
2508  * Ensure that interactions with @proxy conform to the given
2509  * interface. See the #GDBusProxy:g-interface-info property for more
2510  * details.
2511  *
2512  * Since: 2.26
2513  */
2514 void
2515 g_dbus_proxy_set_interface_info (GDBusProxy         *proxy,
2516                                  GDBusInterfaceInfo *info)
2517 {
2518   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
2519   G_LOCK (properties_lock);
2520
2521   if (proxy->priv->expected_interface != NULL)
2522     {
2523       g_dbus_interface_info_cache_release (proxy->priv->expected_interface);
2524       g_dbus_interface_info_unref (proxy->priv->expected_interface);
2525     }
2526   proxy->priv->expected_interface = info != NULL ? g_dbus_interface_info_ref (info) : NULL;
2527   if (proxy->priv->expected_interface != NULL)
2528     g_dbus_interface_info_cache_build (proxy->priv->expected_interface);
2529
2530   G_UNLOCK (properties_lock);
2531 }
2532
2533 /* ---------------------------------------------------------------------------------------------------- */
2534
2535 static gboolean
2536 maybe_split_method_name (const gchar  *method_name,
2537                          gchar       **out_interface_name,
2538                          const gchar **out_method_name)
2539 {
2540   gboolean was_split;
2541
2542   was_split = FALSE;
2543   g_assert (out_interface_name != NULL);
2544   g_assert (out_method_name != NULL);
2545   *out_interface_name = NULL;
2546   *out_method_name = NULL;
2547
2548   if (strchr (method_name, '.') != NULL)
2549     {
2550       gchar *p;
2551       gchar *last_dot;
2552
2553       p = g_strdup (method_name);
2554       last_dot = strrchr (p, '.');
2555       *last_dot = '\0';
2556
2557       *out_interface_name = p;
2558       *out_method_name = last_dot + 1;
2559
2560       was_split = TRUE;
2561     }
2562
2563   return was_split;
2564 }
2565
2566 typedef struct
2567 {
2568   GVariant *value;
2569 #ifdef G_OS_UNIX
2570   GUnixFDList *fd_list;
2571 #endif
2572 } ReplyData;
2573
2574 static void
2575 reply_data_free (ReplyData *data)
2576 {
2577   g_variant_unref (data->value);
2578 #ifdef G_OS_UNIX
2579   if (data->fd_list != NULL)
2580     g_object_unref (data->fd_list);
2581 #endif
2582   g_slice_free (ReplyData, data);
2583 }
2584
2585 static void
2586 reply_cb (GDBusConnection *connection,
2587           GAsyncResult    *res,
2588           gpointer         user_data)
2589 {
2590   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
2591   GVariant *value;
2592   GError *error;
2593 #ifdef G_OS_UNIX
2594   GUnixFDList *fd_list;
2595 #endif
2596
2597   error = NULL;
2598 #ifdef G_OS_UNIX
2599   value = g_dbus_connection_call_with_unix_fd_list_finish (connection,
2600                                                            &fd_list,
2601                                                            res,
2602                                                            &error);
2603 #else
2604   value = g_dbus_connection_call_finish (connection,
2605                                          res,
2606                                          &error);
2607 #endif
2608   if (error != NULL)
2609     {
2610       g_simple_async_result_take_error (simple, error);
2611     }
2612   else
2613     {
2614       ReplyData *data;
2615       data = g_slice_new0 (ReplyData);
2616       data->value = value;
2617 #ifdef G_OS_UNIX
2618       data->fd_list = fd_list;
2619 #endif
2620       g_simple_async_result_set_op_res_gpointer (simple, data, (GDestroyNotify) reply_data_free);
2621     }
2622
2623   /* no need to complete in idle since the method GDBusConnection already does */
2624   g_simple_async_result_complete (simple);
2625   g_object_unref (simple);
2626 }
2627
2628 /* properties_lock must be held for as long as you will keep the
2629  * returned value
2630  */
2631 static const GDBusMethodInfo *
2632 lookup_method_info (GDBusProxy  *proxy,
2633                     const gchar *method_name)
2634 {
2635   const GDBusMethodInfo *info = NULL;
2636
2637   if (proxy->priv->expected_interface == NULL)
2638     goto out;
2639
2640   info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, method_name);
2641
2642 out:
2643   return info;
2644 }
2645
2646 /* properties_lock must be held for as long as you will keep the
2647  * returned value
2648  */
2649 static const gchar *
2650 get_destination_for_call (GDBusProxy *proxy)
2651 {
2652   const gchar *ret;
2653
2654   ret = NULL;
2655
2656   /* If proxy->priv->name is a unique name, then proxy->priv->name_owner
2657    * is never NULL and always the same as proxy->priv->name. We use this
2658    * knowledge to avoid checking if proxy->priv->name is a unique or
2659    * well-known name.
2660    */
2661   ret = proxy->priv->name_owner;
2662   if (ret != NULL)
2663     goto out;
2664
2665   if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)
2666     goto out;
2667
2668   ret = proxy->priv->name;
2669
2670  out:
2671   return ret;
2672 }
2673
2674 /* ---------------------------------------------------------------------------------------------------- */
2675
2676 static void
2677 g_dbus_proxy_call_internal (GDBusProxy          *proxy,
2678                             const gchar         *method_name,
2679                             GVariant            *parameters,
2680                             GDBusCallFlags       flags,
2681                             gint                 timeout_msec,
2682                             GUnixFDList         *fd_list,
2683                             GCancellable        *cancellable,
2684                             GAsyncReadyCallback  callback,
2685                             gpointer             user_data)
2686 {
2687   GSimpleAsyncResult *simple;
2688   gboolean was_split;
2689   gchar *split_interface_name;
2690   const gchar *split_method_name;
2691   const gchar *target_method_name;
2692   const gchar *target_interface_name;
2693   gchar *destination;
2694   GVariantType *reply_type;
2695   GAsyncReadyCallback my_callback;
2696
2697   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
2698   g_return_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name));
2699   g_return_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
2700   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
2701 #ifdef G_OS_UNIX
2702   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
2703 #else
2704   g_return_if_fail (fd_list == NULL);
2705 #endif
2706
2707   reply_type = NULL;
2708   split_interface_name = NULL;
2709
2710   /* g_dbus_connection_call() is optimised for the case of a NULL
2711    * callback.  If we get a NULL callback from our user then make sure
2712    * we pass along a NULL callback for ourselves as well.
2713    */
2714   if (callback != NULL)
2715     {
2716       my_callback = (GAsyncReadyCallback) reply_cb;
2717       simple = g_simple_async_result_new (G_OBJECT (proxy),
2718                                           callback,
2719                                           user_data,
2720                                           g_dbus_proxy_call_internal);
2721       g_simple_async_result_set_check_cancellable (simple, cancellable);
2722     }
2723   else
2724     {
2725       my_callback = NULL;
2726       simple = NULL;
2727     }
2728
2729   G_LOCK (properties_lock);
2730
2731   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
2732   target_method_name = was_split ? split_method_name : method_name;
2733   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
2734
2735   /* Warn if method is unexpected (cf. :g-interface-info) */
2736   if (!was_split)
2737     {
2738       const GDBusMethodInfo *expected_method_info;
2739       expected_method_info = lookup_method_info (proxy, target_method_name);
2740       if (expected_method_info != NULL)
2741         reply_type = _g_dbus_compute_complete_signature (expected_method_info->out_args);
2742     }
2743
2744   destination = NULL;
2745   if (proxy->priv->name != NULL)
2746     {
2747       destination = g_strdup (get_destination_for_call (proxy));
2748       if (destination == NULL)
2749         {
2750           if (simple != NULL)
2751             {
2752               g_simple_async_result_set_error (simple,
2753                                                G_IO_ERROR,
2754                                                G_IO_ERROR_FAILED,
2755                                                _("Cannot invoke method; proxy is for a well-known name without an owner and proxy was constructed with the G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag"));
2756               g_simple_async_result_complete_in_idle (simple);
2757               g_object_unref (simple);
2758             }
2759           G_UNLOCK (properties_lock);
2760           goto out;
2761         }
2762     }
2763
2764   G_UNLOCK (properties_lock);
2765
2766 #ifdef G_OS_UNIX
2767   g_dbus_connection_call_with_unix_fd_list (proxy->priv->connection,
2768                                             destination,
2769                                             proxy->priv->object_path,
2770                                             target_interface_name,
2771                                             target_method_name,
2772                                             parameters,
2773                                             reply_type,
2774                                             flags,
2775                                             timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2776                                             fd_list,
2777                                             cancellable,
2778                                             my_callback,
2779                                             simple);
2780 #else
2781   g_dbus_connection_call (proxy->priv->connection,
2782                           destination,
2783                           proxy->priv->object_path,
2784                           target_interface_name,
2785                           target_method_name,
2786                           parameters,
2787                           reply_type,
2788                           flags,
2789                           timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2790                           cancellable,
2791                           my_callback,
2792                           simple);
2793 #endif
2794
2795  out:
2796   if (reply_type != NULL)
2797     g_variant_type_free (reply_type);
2798
2799   g_free (destination);
2800   g_free (split_interface_name);
2801 }
2802
2803 static GVariant *
2804 g_dbus_proxy_call_finish_internal (GDBusProxy    *proxy,
2805                                    GUnixFDList  **out_fd_list,
2806                                    GAsyncResult  *res,
2807                                    GError       **error)
2808 {
2809   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
2810   GVariant *value;
2811   ReplyData *data;
2812
2813   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2814   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2815   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2816
2817   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_proxy_call_internal);
2818
2819   value = NULL;
2820
2821   if (g_simple_async_result_propagate_error (simple, error))
2822     goto out;
2823
2824   data = g_simple_async_result_get_op_res_gpointer (simple);
2825   value = g_variant_ref (data->value);
2826 #ifdef G_OS_UNIX
2827   if (out_fd_list != NULL)
2828     *out_fd_list = data->fd_list != NULL ? g_object_ref (data->fd_list) : NULL;
2829 #endif
2830
2831  out:
2832   return value;
2833 }
2834
2835 static GVariant *
2836 g_dbus_proxy_call_sync_internal (GDBusProxy      *proxy,
2837                                  const gchar     *method_name,
2838                                  GVariant        *parameters,
2839                                  GDBusCallFlags   flags,
2840                                  gint             timeout_msec,
2841                                  GUnixFDList     *fd_list,
2842                                  GUnixFDList    **out_fd_list,
2843                                  GCancellable    *cancellable,
2844                                  GError         **error)
2845 {
2846   GVariant *ret;
2847   gboolean was_split;
2848   gchar *split_interface_name;
2849   const gchar *split_method_name;
2850   const gchar *target_method_name;
2851   const gchar *target_interface_name;
2852   gchar *destination;
2853   GVariantType *reply_type;
2854
2855   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2856   g_return_val_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name), NULL);
2857   g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
2858   g_return_val_if_fail (timeout_msec == -1 || timeout_msec >= 0, NULL);
2859 #ifdef G_OS_UNIX
2860   g_return_val_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list), NULL);
2861 #else
2862   g_return_val_if_fail (fd_list == NULL, NULL);
2863 #endif
2864   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2865
2866   reply_type = NULL;
2867
2868   G_LOCK (properties_lock);
2869
2870   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
2871   target_method_name = was_split ? split_method_name : method_name;
2872   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
2873
2874   /* Warn if method is unexpected (cf. :g-interface-info) */
2875   if (!was_split)
2876     {
2877       const GDBusMethodInfo *expected_method_info;
2878       expected_method_info = lookup_method_info (proxy, target_method_name);
2879       if (expected_method_info != NULL)
2880         reply_type = _g_dbus_compute_complete_signature (expected_method_info->out_args);
2881     }
2882
2883   destination = NULL;
2884   if (proxy->priv->name != NULL)
2885     {
2886       destination = g_strdup (get_destination_for_call (proxy));
2887       if (destination == NULL)
2888         {
2889           g_set_error_literal (error,
2890                                G_IO_ERROR,
2891                                G_IO_ERROR_FAILED,
2892                                _("Cannot invoke method; proxy is for a well-known name without an owner and proxy was constructed with the G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag"));
2893           ret = NULL;
2894           G_UNLOCK (properties_lock);
2895           goto out;
2896         }
2897     }
2898
2899   G_UNLOCK (properties_lock);
2900
2901 #ifdef G_OS_UNIX
2902   ret = g_dbus_connection_call_with_unix_fd_list_sync (proxy->priv->connection,
2903                                                        destination,
2904                                                        proxy->priv->object_path,
2905                                                        target_interface_name,
2906                                                        target_method_name,
2907                                                        parameters,
2908                                                        reply_type,
2909                                                        flags,
2910                                                        timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2911                                                        fd_list,
2912                                                        out_fd_list,
2913                                                        cancellable,
2914                                                        error);
2915 #else
2916   ret = g_dbus_connection_call_sync (proxy->priv->connection,
2917                                      destination,
2918                                      proxy->priv->object_path,
2919                                      target_interface_name,
2920                                      target_method_name,
2921                                      parameters,
2922                                      reply_type,
2923                                      flags,
2924                                      timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2925                                      cancellable,
2926                                      error);
2927 #endif
2928
2929  out:
2930   if (reply_type != NULL)
2931     g_variant_type_free (reply_type);
2932
2933   g_free (destination);
2934   g_free (split_interface_name);
2935
2936   return ret;
2937 }
2938
2939 /* ---------------------------------------------------------------------------------------------------- */
2940
2941 /**
2942  * g_dbus_proxy_call:
2943  * @proxy: A #GDBusProxy.
2944  * @method_name: Name of method to invoke.
2945  * @parameters: (allow-none): A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
2946  * @flags: Flags from the #GDBusCallFlags enumeration.
2947  * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
2948  *                "infinite") or -1 to use the proxy default timeout.
2949  * @cancellable: (allow-none): A #GCancellable or %NULL.
2950  * @callback: (allow-none): A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
2951  * care about the result of the method invocation.
2952  * @user_data: The data to pass to @callback.
2953  *
2954  * Asynchronously invokes the @method_name method on @proxy.
2955  *
2956  * If @method_name contains any dots, then @name is split into interface and
2957  * method name parts. This allows using @proxy for invoking methods on
2958  * other interfaces.
2959  *
2960  * If the #GDBusConnection associated with @proxy is closed then
2961  * the operation will fail with %G_IO_ERROR_CLOSED. If
2962  * @cancellable is canceled, the operation will fail with
2963  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
2964  * compatible with the D-Bus protocol, the operation fails with
2965  * %G_IO_ERROR_INVALID_ARGUMENT.
2966  *
2967  * If the @parameters #GVariant is floating, it is consumed. This allows
2968  * convenient 'inline' use of g_variant_new(), e.g.:
2969  * |[
2970  *  g_dbus_proxy_call (proxy,
2971  *                     "TwoStrings",
2972  *                     g_variant_new ("(ss)",
2973  *                                    "Thing One",
2974  *                                    "Thing Two"),
2975  *                     G_DBUS_CALL_FLAGS_NONE,
2976  *                     -1,
2977  *                     NULL,
2978  *                     (GAsyncReadyCallback) two_strings_done,
2979  *                     &data);
2980  * ]|
2981  *
2982  * If @proxy has an expected interface (see
2983  * #GDBusProxy:g-interface-info) and @method_name is referenced by it,
2984  * then the return value is checked against the return type.
2985  *
2986  * This is an asynchronous method. When the operation is finished,
2987  * @callback will be invoked in the
2988  * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
2989  * of the thread you are calling this method from.
2990  * You can then call g_dbus_proxy_call_finish() to get the result of
2991  * the operation. See g_dbus_proxy_call_sync() for the synchronous
2992  * version of this method.
2993  *
2994  * If @callback is %NULL then the D-Bus method call message will be sent with
2995  * the %G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED flag set.
2996  *
2997  * Since: 2.26
2998  */
2999 void
3000 g_dbus_proxy_call (GDBusProxy          *proxy,
3001                    const gchar         *method_name,
3002                    GVariant            *parameters,
3003                    GDBusCallFlags       flags,
3004                    gint                 timeout_msec,
3005                    GCancellable        *cancellable,
3006                    GAsyncReadyCallback  callback,
3007                    gpointer             user_data)
3008 {
3009   g_dbus_proxy_call_internal (proxy, method_name, parameters, flags, timeout_msec, NULL, cancellable, callback, user_data);
3010 }
3011
3012 /**
3013  * g_dbus_proxy_call_finish:
3014  * @proxy: A #GDBusProxy.
3015  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call().
3016  * @error: Return location for error or %NULL.
3017  *
3018  * Finishes an operation started with g_dbus_proxy_call().
3019  *
3020  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
3021  * return values. Free with g_variant_unref().
3022  *
3023  * Since: 2.26
3024  */
3025 GVariant *
3026 g_dbus_proxy_call_finish (GDBusProxy    *proxy,
3027                           GAsyncResult  *res,
3028                           GError       **error)
3029 {
3030   return g_dbus_proxy_call_finish_internal (proxy, NULL, res, error);
3031 }
3032
3033 /**
3034  * g_dbus_proxy_call_sync:
3035  * @proxy: A #GDBusProxy.
3036  * @method_name: Name of method to invoke.
3037  * @parameters: (allow-none): A #GVariant tuple with parameters for the signal
3038  *              or %NULL if not passing parameters.
3039  * @flags: Flags from the #GDBusCallFlags enumeration.
3040  * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
3041  *                "infinite") or -1 to use the proxy default timeout.
3042  * @cancellable: (allow-none): A #GCancellable or %NULL.
3043  * @error: Return location for error or %NULL.
3044  *
3045  * Synchronously invokes the @method_name method on @proxy.
3046  *
3047  * If @method_name contains any dots, then @name is split into interface and
3048  * method name parts. This allows using @proxy for invoking methods on
3049  * other interfaces.
3050  *
3051  * If the #GDBusConnection associated with @proxy is disconnected then
3052  * the operation will fail with %G_IO_ERROR_CLOSED. If
3053  * @cancellable is canceled, the operation will fail with
3054  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
3055  * compatible with the D-Bus protocol, the operation fails with
3056  * %G_IO_ERROR_INVALID_ARGUMENT.
3057  *
3058  * If the @parameters #GVariant is floating, it is consumed. This allows
3059  * convenient 'inline' use of g_variant_new(), e.g.:
3060  * |[
3061  *  g_dbus_proxy_call_sync (proxy,
3062  *                          "TwoStrings",
3063  *                          g_variant_new ("(ss)",
3064  *                                         "Thing One",
3065  *                                         "Thing Two"),
3066  *                          G_DBUS_CALL_FLAGS_NONE,
3067  *                          -1,
3068  *                          NULL,
3069  *                          &error);
3070  * ]|
3071  *
3072  * The calling thread is blocked until a reply is received. See
3073  * g_dbus_proxy_call() for the asynchronous version of this
3074  * method.
3075  *
3076  * If @proxy has an expected interface (see
3077  * #GDBusProxy:g-interface-info) and @method_name is referenced by it,
3078  * then the return value is checked against the return type.
3079  *
3080  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
3081  * return values. Free with g_variant_unref().
3082  *
3083  * Since: 2.26
3084  */
3085 GVariant *
3086 g_dbus_proxy_call_sync (GDBusProxy      *proxy,
3087                         const gchar     *method_name,
3088                         GVariant        *parameters,
3089                         GDBusCallFlags   flags,
3090                         gint             timeout_msec,
3091                         GCancellable    *cancellable,
3092                         GError         **error)
3093 {
3094   return g_dbus_proxy_call_sync_internal (proxy, method_name, parameters, flags, timeout_msec, NULL, NULL, cancellable, error);
3095 }
3096
3097 /* ---------------------------------------------------------------------------------------------------- */
3098
3099 #ifdef G_OS_UNIX
3100
3101 /**
3102  * g_dbus_proxy_call_with_unix_fd_list:
3103  * @proxy: A #GDBusProxy.
3104  * @method_name: Name of method to invoke.
3105  * @parameters: (allow-none): A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
3106  * @flags: Flags from the #GDBusCallFlags enumeration.
3107  * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
3108  *                "infinite") or -1 to use the proxy default timeout.
3109  * @fd_list: (allow-none): A #GUnixFDList or %NULL.
3110  * @cancellable: (allow-none): A #GCancellable or %NULL.
3111  * @callback: (allow-none): A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
3112  * care about the result of the method invocation.
3113  * @user_data: The data to pass to @callback.
3114  *
3115  * Like g_dbus_proxy_call() but also takes a #GUnixFDList object.
3116  *
3117  * This method is only available on UNIX.
3118  *
3119  * Since: 2.30
3120  */
3121 void
3122 g_dbus_proxy_call_with_unix_fd_list (GDBusProxy          *proxy,
3123                                      const gchar         *method_name,
3124                                      GVariant            *parameters,
3125                                      GDBusCallFlags       flags,
3126                                      gint                 timeout_msec,
3127                                      GUnixFDList         *fd_list,
3128                                      GCancellable        *cancellable,
3129                                      GAsyncReadyCallback  callback,
3130                                      gpointer             user_data)
3131 {
3132   g_dbus_proxy_call_internal (proxy, method_name, parameters, flags, timeout_msec, fd_list, cancellable, callback, user_data);
3133 }
3134
3135 /**
3136  * g_dbus_proxy_call_with_unix_fd_list_finish:
3137  * @proxy: A #GDBusProxy.
3138  * @out_fd_list: (out) (allow-none): Return location for a #GUnixFDList or %NULL.
3139  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call_with_unix_fd_list().
3140  * @error: Return location for error or %NULL.
3141  *
3142  * Finishes an operation started with g_dbus_proxy_call_with_unix_fd_list().
3143  *
3144  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
3145  * return values. Free with g_variant_unref().
3146  *
3147  * Since: 2.30
3148  */
3149 GVariant *
3150 g_dbus_proxy_call_with_unix_fd_list_finish (GDBusProxy    *proxy,
3151                                             GUnixFDList  **out_fd_list,
3152                                             GAsyncResult  *res,
3153                                             GError       **error)
3154 {
3155   return g_dbus_proxy_call_finish_internal (proxy, out_fd_list, res, error);
3156 }
3157
3158 /**
3159  * g_dbus_proxy_call_with_unix_fd_list_sync:
3160  * @proxy: A #GDBusProxy.
3161  * @method_name: Name of method to invoke.
3162  * @parameters: (allow-none): A #GVariant tuple with parameters for the signal
3163  *              or %NULL if not passing parameters.
3164  * @flags: Flags from the #GDBusCallFlags enumeration.
3165  * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
3166  *                "infinite") or -1 to use the proxy default timeout.
3167  * @fd_list: (allow-none): A #GUnixFDList or %NULL.
3168  * @out_fd_list: (out) (allow-none): Return location for a #GUnixFDList or %NULL.
3169  * @cancellable: (allow-none): A #GCancellable or %NULL.
3170  * @error: Return location for error or %NULL.
3171  *
3172  * Like g_dbus_proxy_call_sync() but also takes and returns #GUnixFDList objects.
3173  *
3174  * This method is only available on UNIX.
3175  *
3176  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
3177  * return values. Free with g_variant_unref().
3178  *
3179  * Since: 2.30
3180  */
3181 GVariant *
3182 g_dbus_proxy_call_with_unix_fd_list_sync (GDBusProxy      *proxy,
3183                                           const gchar     *method_name,
3184                                           GVariant        *parameters,
3185                                           GDBusCallFlags   flags,
3186                                           gint             timeout_msec,
3187                                           GUnixFDList     *fd_list,
3188                                           GUnixFDList    **out_fd_list,
3189                                           GCancellable    *cancellable,
3190                                           GError         **error)
3191 {
3192   return g_dbus_proxy_call_sync_internal (proxy, method_name, parameters, flags, timeout_msec, fd_list, out_fd_list, cancellable, error);
3193 }
3194
3195 #endif /* G_OS_UNIX */
3196
3197 /* ---------------------------------------------------------------------------------------------------- */
3198
3199 static GDBusInterfaceInfo *
3200 _g_dbus_proxy_get_info (GDBusInterface *interface)
3201 {
3202   GDBusProxy *proxy = G_DBUS_PROXY (interface);
3203   return g_dbus_proxy_get_interface_info (proxy);
3204 }
3205
3206 static GDBusObject *
3207 _g_dbus_proxy_get_object (GDBusInterface *interface)
3208 {
3209   GDBusProxy *proxy = G_DBUS_PROXY (interface);
3210   return proxy->priv->object;
3211 }
3212
3213 static GDBusObject *
3214 _g_dbus_proxy_dup_object (GDBusInterface *interface)
3215 {
3216   GDBusProxy *proxy = G_DBUS_PROXY (interface);
3217   GDBusObject *ret = NULL;
3218
3219   G_LOCK (properties_lock);
3220   if (proxy->priv->object != NULL)
3221     ret = g_object_ref (proxy->priv->object);
3222   G_UNLOCK (properties_lock);
3223   return ret;
3224 }
3225
3226 static void
3227 _g_dbus_proxy_set_object (GDBusInterface *interface,
3228                           GDBusObject    *object)
3229 {
3230   GDBusProxy *proxy = G_DBUS_PROXY (interface);
3231   G_LOCK (properties_lock);
3232   if (proxy->priv->object != NULL)
3233     g_object_remove_weak_pointer (G_OBJECT (proxy->priv->object), (gpointer *) &proxy->priv->object);
3234   proxy->priv->object = object;
3235   if (proxy->priv->object != NULL)
3236     g_object_add_weak_pointer (G_OBJECT (proxy->priv->object), (gpointer *) &proxy->priv->object);
3237   G_UNLOCK (properties_lock);
3238 }
3239
3240 static void
3241 dbus_interface_iface_init (GDBusInterfaceIface *dbus_interface_iface)
3242 {
3243   dbus_interface_iface->get_info   = _g_dbus_proxy_get_info;
3244   dbus_interface_iface->get_object = _g_dbus_proxy_get_object;
3245   dbus_interface_iface->dup_object = _g_dbus_proxy_dup_object;
3246   dbus_interface_iface->set_object = _g_dbus_proxy_set_object;
3247 }
3248
3249 /* ---------------------------------------------------------------------------------------------------- */