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