Bug 621213 – GDBusProxy and well-known names
[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, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "gdbusutils.h"
29 #include "gdbusproxy.h"
30 #include "gioenumtypes.h"
31 #include "gdbusconnection.h"
32 #include "gdbuserror.h"
33 #include "gdbusprivate.h"
34 #include "gio-marshal.h"
35 #include "ginitable.h"
36 #include "gasyncinitable.h"
37 #include "gioerror.h"
38 #include "gasyncresult.h"
39 #include "gsimpleasyncresult.h"
40 #include "gcancellable.h"
41
42 #include "glibintl.h"
43 #include "gioalias.h"
44
45 /**
46  * SECTION:gdbusproxy
47  * @short_description: Client-side proxies
48  * @include: gio/gio.h
49  *
50  * #GDBusProxy is a base class used for proxies to access a D-Bus
51  * interface on a remote object. A #GDBusProxy can be constructed for
52  * both well-known and unique names.
53  *
54  * By default, #GDBusProxy will cache all properties (and listen to
55  * changes) of the remote object, and proxy all signals that gets
56  * emitted. This behaviour can be changed by passing suitable
57  * #GDBusProxyFlags when the proxy is created. If the proxy is for a
58  * well-known name, the property cache is flushed when the name owner
59  * vanishes and reloaded when a name owner appears.
60  *
61  * If a #GDBusProxy is used for a well-known name, the owner of the
62  * name is tracked and can be read from
63  * #GDBusProxy:g-name-owner. Connect to the #GObject::notify signal to
64  * get notified of changes. Additionally, only signals and property
65  * changes emitted from the current name owner are considered. This
66  * avoids a number of race conditions when the name is lost by one
67  * owner and claimed by another.
68  *
69  * The generic #GDBusProxy::g-properties-changed and #GDBusProxy::g-signal
70  * signals are not very convenient to work with. Therefore, the recommended
71  * way of working with proxies is to subclass #GDBusProxy, and have
72  * more natural properties and signals in your derived class.
73  *
74  * See <xref linkend="gdbus-example-proxy-subclass"/> for an example.
75  *
76  * <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>
77  */
78
79 struct _GDBusProxyPrivate
80 {
81   GBusType bus_type;
82   GDBusConnection *connection;
83
84   GDBusProxyFlags flags;
85   gchar *name;
86   gchar *name_owner;
87   gchar *object_path;
88   gchar *interface_name;
89   gint timeout_msec;
90
91   guint name_owner_changed_subscription_id;
92
93   GCancellable *get_all_cancellable;
94
95   /* gchar* -> GVariant* */
96   GHashTable *properties;
97
98   GDBusInterfaceInfo *expected_interface;
99
100   guint properties_changed_subscriber_id;
101   guint signals_subscriber_id;
102
103   gboolean initialized;
104 };
105
106 enum
107 {
108   PROP_0,
109   PROP_G_CONNECTION,
110   PROP_G_BUS_TYPE,
111   PROP_G_NAME,
112   PROP_G_NAME_OWNER,
113   PROP_G_FLAGS,
114   PROP_G_OBJECT_PATH,
115   PROP_G_INTERFACE_NAME,
116   PROP_G_DEFAULT_TIMEOUT,
117   PROP_G_INTERFACE_INFO
118 };
119
120 enum
121 {
122   PROPERTIES_CHANGED_SIGNAL,
123   SIGNAL_SIGNAL,
124   LAST_SIGNAL,
125 };
126
127 guint signals[LAST_SIGNAL] = {0};
128
129 static void initable_iface_init       (GInitableIface *initable_iface);
130 static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
131
132 G_DEFINE_TYPE_WITH_CODE (GDBusProxy, g_dbus_proxy, G_TYPE_OBJECT,
133                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
134                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
135                          );
136
137 static void
138 g_dbus_proxy_finalize (GObject *object)
139 {
140   GDBusProxy *proxy = G_DBUS_PROXY (object);
141
142   g_warn_if_fail (proxy->priv->get_all_cancellable == NULL);
143
144   if (proxy->priv->name_owner_changed_subscription_id > 0)
145     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
146                                           proxy->priv->name_owner_changed_subscription_id);
147
148   if (proxy->priv->properties_changed_subscriber_id > 0)
149     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
150                                           proxy->priv->properties_changed_subscriber_id);
151
152   if (proxy->priv->signals_subscriber_id > 0)
153     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
154                                           proxy->priv->signals_subscriber_id);
155
156   g_object_unref (proxy->priv->connection);
157   g_free (proxy->priv->name);
158   g_free (proxy->priv->name_owner);
159   g_free (proxy->priv->object_path);
160   g_free (proxy->priv->interface_name);
161   if (proxy->priv->properties != NULL)
162     g_hash_table_unref (proxy->priv->properties);
163
164   if (proxy->priv->expected_interface != NULL)
165     g_dbus_interface_info_unref (proxy->priv->expected_interface);
166
167   G_OBJECT_CLASS (g_dbus_proxy_parent_class)->finalize (object);
168 }
169
170 static void
171 g_dbus_proxy_get_property (GObject    *object,
172                            guint       prop_id,
173                            GValue     *value,
174                            GParamSpec *pspec)
175 {
176   GDBusProxy *proxy = G_DBUS_PROXY (object);
177
178   switch (prop_id)
179     {
180     case PROP_G_CONNECTION:
181       g_value_set_object (value, proxy->priv->connection);
182       break;
183
184     case PROP_G_FLAGS:
185       g_value_set_flags (value, proxy->priv->flags);
186       break;
187
188     case PROP_G_NAME:
189       g_value_set_string (value, proxy->priv->name);
190       break;
191
192     case PROP_G_NAME_OWNER:
193       g_value_set_string (value, proxy->priv->name_owner);
194       break;
195
196     case PROP_G_OBJECT_PATH:
197       g_value_set_string (value, proxy->priv->object_path);
198       break;
199
200     case PROP_G_INTERFACE_NAME:
201       g_value_set_string (value, proxy->priv->interface_name);
202       break;
203
204     case PROP_G_DEFAULT_TIMEOUT:
205       g_value_set_int (value, proxy->priv->timeout_msec);
206       break;
207
208     case PROP_G_INTERFACE_INFO:
209       g_value_set_boxed (value, g_dbus_proxy_get_interface_info (proxy));
210       break;
211
212     default:
213       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
214       break;
215     }
216 }
217
218 static void
219 g_dbus_proxy_set_property (GObject      *object,
220                            guint         prop_id,
221                            const GValue *value,
222                            GParamSpec   *pspec)
223 {
224   GDBusProxy *proxy = G_DBUS_PROXY (object);
225
226   switch (prop_id)
227     {
228     case PROP_G_CONNECTION:
229       proxy->priv->connection = g_value_dup_object (value);
230       break;
231
232     case PROP_G_FLAGS:
233       proxy->priv->flags = g_value_get_flags (value);
234       break;
235
236     case PROP_G_NAME:
237       proxy->priv->name = g_value_dup_string (value);
238       break;
239
240     case PROP_G_OBJECT_PATH:
241       proxy->priv->object_path = g_value_dup_string (value);
242       break;
243
244     case PROP_G_INTERFACE_NAME:
245       proxy->priv->interface_name = g_value_dup_string (value);
246       break;
247
248     case PROP_G_DEFAULT_TIMEOUT:
249       g_dbus_proxy_set_default_timeout (proxy, g_value_get_int (value));
250       break;
251
252     case PROP_G_INTERFACE_INFO:
253       g_dbus_proxy_set_interface_info (proxy, g_value_get_boxed (value));
254       break;
255
256     case PROP_G_BUS_TYPE:
257       proxy->priv->bus_type = g_value_get_enum (value);
258       break;
259
260     default:
261       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
262       break;
263     }
264 }
265
266 static void
267 g_dbus_proxy_class_init (GDBusProxyClass *klass)
268 {
269   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
270
271   gobject_class->finalize     = g_dbus_proxy_finalize;
272   gobject_class->set_property = g_dbus_proxy_set_property;
273   gobject_class->get_property = g_dbus_proxy_get_property;
274
275   /* Note that all property names are prefixed to avoid collisions with D-Bus property names
276    * in derived classes */
277
278   /**
279    * GDBusProxy:g-interface-info:
280    *
281    * Ensure that interactions with this proxy conform to the given
282    * interface.  For example, when completing a method call, if the
283    * type signature of the message isn't what's expected, the given
284    * #GError is set.  Signals that have a type signature mismatch are
285    * simply dropped.
286    *
287    * Since: 2.26
288    */
289   g_object_class_install_property (gobject_class,
290                                    PROP_G_INTERFACE_INFO,
291                                    g_param_spec_boxed ("g-interface-info",
292                                                        P_("Interface Information"),
293                                                        P_("Interface Information"),
294                                                        G_TYPE_DBUS_INTERFACE_INFO,
295                                                        G_PARAM_READABLE |
296                                                        G_PARAM_WRITABLE |
297                                                        G_PARAM_STATIC_NAME |
298                                                        G_PARAM_STATIC_BLURB |
299                                                        G_PARAM_STATIC_NICK));
300
301   /**
302    * GDBusProxy:g-connection:
303    *
304    * The #GDBusConnection the proxy is for.
305    *
306    * Since: 2.26
307    */
308   g_object_class_install_property (gobject_class,
309                                    PROP_G_CONNECTION,
310                                    g_param_spec_object ("g-connection",
311                                                         P_("g-connection"),
312                                                         P_("The connection the proxy is for"),
313                                                         G_TYPE_DBUS_CONNECTION,
314                                                         G_PARAM_READABLE |
315                                                         G_PARAM_WRITABLE |
316                                                         G_PARAM_CONSTRUCT_ONLY |
317                                                         G_PARAM_STATIC_NAME |
318                                                         G_PARAM_STATIC_BLURB |
319                                                         G_PARAM_STATIC_NICK));
320
321   /**
322    * GDBusProxy:g-bus-type:
323    *
324    * If this property is not %G_BUS_TYPE_NONE, then
325    * #GDBusProxy:g-connection must be %NULL and will be set to the
326    * #GDBusConnection obtained by calling g_bus_get() with the value
327    * of this property.
328    *
329    * Since: 2.26
330    */
331   g_object_class_install_property (gobject_class,
332                                    PROP_G_BUS_TYPE,
333                                    g_param_spec_enum ("g-bus-type",
334                                                       P_("Bus Type"),
335                                                       P_("The bus to connect to, if any"),
336                                                       G_TYPE_BUS_TYPE,
337                                                       G_BUS_TYPE_NONE,
338                                                       G_PARAM_WRITABLE |
339                                                       G_PARAM_CONSTRUCT_ONLY |
340                                                       G_PARAM_STATIC_NAME |
341                                                       G_PARAM_STATIC_BLURB |
342                                                       G_PARAM_STATIC_NICK));
343
344   /**
345    * GDBusProxy:g-flags:
346    *
347    * Flags from the #GDBusProxyFlags enumeration.
348    *
349    * Since: 2.26
350    */
351   g_object_class_install_property (gobject_class,
352                                    PROP_G_FLAGS,
353                                    g_param_spec_flags ("g-flags",
354                                                        P_("g-flags"),
355                                                        P_("Flags for the proxy"),
356                                                        G_TYPE_DBUS_PROXY_FLAGS,
357                                                        G_DBUS_PROXY_FLAGS_NONE,
358                                                        G_PARAM_READABLE |
359                                                        G_PARAM_WRITABLE |
360                                                        G_PARAM_CONSTRUCT_ONLY |
361                                                        G_PARAM_STATIC_NAME |
362                                                        G_PARAM_STATIC_BLURB |
363                                                        G_PARAM_STATIC_NICK));
364
365   /**
366    * GDBusProxy:g-name:
367    *
368    * The well-known or unique name that the proxy is for.
369    *
370    * Since: 2.26
371    */
372   g_object_class_install_property (gobject_class,
373                                    PROP_G_NAME,
374                                    g_param_spec_string ("g-name",
375                                                         P_("g-name"),
376                                                         P_("The well-known or unique name that the proxy is for"),
377                                                         NULL,
378                                                         G_PARAM_READABLE |
379                                                         G_PARAM_WRITABLE |
380                                                         G_PARAM_CONSTRUCT_ONLY |
381                                                         G_PARAM_STATIC_NAME |
382                                                         G_PARAM_STATIC_BLURB |
383                                                         G_PARAM_STATIC_NICK));
384
385   /**
386    * GDBusProxy:g-name-owner:
387    *
388    * The unique name that owns #GDBusProxy:name or %NULL if no-one
389    * currently owns that name. You may connect to #GObject::notify signal to
390    * track changes to this property.
391    *
392    * Since: 2.26
393    */
394   g_object_class_install_property (gobject_class,
395                                    PROP_G_NAME_OWNER,
396                                    g_param_spec_string ("g-name-owner",
397                                                         P_("g-name-owner"),
398                                                         P_("The unique name for the owner"),
399                                                         NULL,
400                                                         G_PARAM_READABLE |
401                                                         G_PARAM_STATIC_NAME |
402                                                         G_PARAM_STATIC_BLURB |
403                                                         G_PARAM_STATIC_NICK));
404
405   /**
406    * GDBusProxy:g-object-path:
407    *
408    * The object path the proxy is for.
409    *
410    * Since: 2.26
411    */
412   g_object_class_install_property (gobject_class,
413                                    PROP_G_OBJECT_PATH,
414                                    g_param_spec_string ("g-object-path",
415                                                         P_("g-object-path"),
416                                                         P_("The object path the proxy is for"),
417                                                         NULL,
418                                                         G_PARAM_READABLE |
419                                                         G_PARAM_WRITABLE |
420                                                         G_PARAM_CONSTRUCT_ONLY |
421                                                         G_PARAM_STATIC_NAME |
422                                                         G_PARAM_STATIC_BLURB |
423                                                         G_PARAM_STATIC_NICK));
424
425   /**
426    * GDBusProxy:g-interface-name:
427    *
428    * The D-Bus interface name the proxy is for.
429    *
430    * Since: 2.26
431    */
432   g_object_class_install_property (gobject_class,
433                                    PROP_G_INTERFACE_NAME,
434                                    g_param_spec_string ("g-interface-name",
435                                                         P_("g-interface-name"),
436                                                         P_("The D-Bus interface name the proxy is for"),
437                                                         NULL,
438                                                         G_PARAM_READABLE |
439                                                         G_PARAM_WRITABLE |
440                                                         G_PARAM_CONSTRUCT_ONLY |
441                                                         G_PARAM_STATIC_NAME |
442                                                         G_PARAM_STATIC_BLURB |
443                                                         G_PARAM_STATIC_NICK));
444
445   /**
446    * GDBusProxy:g-default-timeout:
447    *
448    * The timeout to use if -1 (specifying default timeout) is passed
449    * as @timeout_msec in the g_dbus_proxy_call() and
450    * g_dbus_proxy_call_sync() functions.
451    *
452    * This allows applications to set a proxy-wide timeout for all
453    * remote method invocations on the proxy. If this property is -1,
454    * the default timeout (typically 25 seconds) is used. If set to
455    * %G_MAXINT, then no timeout is used.
456    *
457    * Since: 2.26
458    */
459   g_object_class_install_property (gobject_class,
460                                    PROP_G_DEFAULT_TIMEOUT,
461                                    g_param_spec_int ("g-default-timeout",
462                                                      P_("Default Timeout"),
463                                                      P_("Timeout for remote method invocation"),
464                                                      -1,
465                                                      G_MAXINT,
466                                                      -1,
467                                                      G_PARAM_READABLE |
468                                                      G_PARAM_WRITABLE |
469                                                      G_PARAM_CONSTRUCT |
470                                                      G_PARAM_STATIC_NAME |
471                                                      G_PARAM_STATIC_BLURB |
472                                                      G_PARAM_STATIC_NICK));
473
474   /**
475    * GDBusProxy::g-properties-changed:
476    * @proxy: The #GDBusProxy emitting the signal.
477    * @changed_properties: A #GVariant containing the properties that changed
478    * @invalidated_properties: A %NULL terminated array of properties that was invalidated
479    *
480    * Emitted when one or more D-Bus properties on @proxy changes. The
481    * local cache has already been updated when this signal fires. Note
482    * that both @changed_properties and @invalidated_properties are
483    * guaranteed to never be %NULL (either may be empty though).
484    *
485    * This signal corresponds to the
486    * <literal>PropertiesChanged</literal> D-Bus signal on the
487    * <literal>org.freedesktop.DBus.Properties</literal> interface.
488    *
489    * Since: 2.26
490    */
491   signals[PROPERTIES_CHANGED_SIGNAL] = g_signal_new ("g-properties-changed",
492                                                      G_TYPE_DBUS_PROXY,
493                                                      G_SIGNAL_RUN_LAST,
494                                                      G_STRUCT_OFFSET (GDBusProxyClass, g_properties_changed),
495                                                      NULL,
496                                                      NULL,
497                                                      _gio_marshal_VOID__BOXED_BOXED,
498                                                      G_TYPE_NONE,
499                                                      2,
500                                                      G_TYPE_VARIANT,
501                                                      G_TYPE_STRV | G_SIGNAL_TYPE_STATIC_SCOPE);
502
503   /**
504    * GDBusProxy::g-signal:
505    * @proxy: The #GDBusProxy emitting the signal.
506    * @sender_name: The sender of the signal or %NULL if the connection is not a bus connection.
507    * @signal_name: The name of the signal.
508    * @parameters: A #GVariant tuple with parameters for the signal.
509    *
510    * Emitted when a signal from the remote object and interface that @proxy is for, has been received.
511    *
512    * Since: 2.26
513    */
514   signals[SIGNAL_SIGNAL] = g_signal_new ("g-signal",
515                                          G_TYPE_DBUS_PROXY,
516                                          G_SIGNAL_RUN_LAST,
517                                          G_STRUCT_OFFSET (GDBusProxyClass, g_signal),
518                                          NULL,
519                                          NULL,
520                                          _gio_marshal_VOID__STRING_STRING_BOXED,
521                                          G_TYPE_NONE,
522                                          3,
523                                          G_TYPE_STRING,
524                                          G_TYPE_STRING,
525                                          G_TYPE_VARIANT);
526
527
528   g_type_class_add_private (klass, sizeof (GDBusProxyPrivate));
529 }
530
531 static void
532 g_dbus_proxy_init (GDBusProxy *proxy)
533 {
534   proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, G_TYPE_DBUS_PROXY, GDBusProxyPrivate);
535   proxy->priv->properties = g_hash_table_new_full (g_str_hash,
536                                                    g_str_equal,
537                                                    g_free,
538                                                    (GDestroyNotify) g_variant_unref);
539 }
540
541 /* ---------------------------------------------------------------------------------------------------- */
542
543 /**
544  * g_dbus_proxy_get_cached_property_names:
545  * @proxy: A #GDBusProxy.
546  *
547  * Gets the names of all cached properties on @proxy.
548  *
549  * Returns: A %NULL-terminated array of strings or %NULL if @proxy has
550  * no cached properties. Free the returned array with g_strfreev().
551  *
552  * Since: 2.26
553  */
554 gchar **
555 g_dbus_proxy_get_cached_property_names (GDBusProxy  *proxy)
556 {
557   gchar **names;
558   GPtrArray *p;
559   GHashTableIter iter;
560   const gchar *key;
561
562   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
563
564   names = NULL;
565   if (g_hash_table_size (proxy->priv->properties) == 0)
566     goto out;
567
568   p = g_ptr_array_new ();
569
570   g_hash_table_iter_init (&iter, proxy->priv->properties);
571   while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL))
572     g_ptr_array_add (p, g_strdup (key));
573   g_ptr_array_sort (p, (GCompareFunc) g_strcmp0);
574   g_ptr_array_add (p, NULL);
575
576   names = (gchar **) g_ptr_array_free (p, FALSE);
577
578  out:
579   return names;
580 }
581
582 static const GDBusPropertyInfo *
583 lookup_property_info_or_warn (GDBusProxy  *proxy,
584                               const gchar *property_name)
585 {
586   const GDBusPropertyInfo *info;
587
588   if (proxy->priv->expected_interface == NULL)
589     return NULL;
590
591   info = g_dbus_interface_info_lookup_property (proxy->priv->expected_interface, property_name);
592   if (info == NULL)
593     {
594       g_warning ("Trying to lookup property %s which isn't in expected interface %s",
595                  property_name,
596                  proxy->priv->expected_interface->name);
597     }
598
599   return info;
600 }
601
602 /**
603  * g_dbus_proxy_get_cached_property:
604  * @proxy: A #GDBusProxy.
605  * @property_name: Property name.
606  *
607  * Looks up the value for a property from the cache. This call does no
608  * blocking IO.
609  *
610  * If @proxy has an expected interface (see
611  * #GDBusProxy:g-interface-info), then @property_name (for existence)
612  * is checked against it.
613  *
614  * Returns: A reference to the #GVariant instance that holds the value
615  * for @property_name or %NULL if the value is not in the cache. The
616  * returned reference must be freed with g_variant_unref().
617  *
618  * Since: 2.26
619  */
620 GVariant *
621 g_dbus_proxy_get_cached_property (GDBusProxy   *proxy,
622                                   const gchar  *property_name)
623 {
624   GVariant *value;
625
626   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
627   g_return_val_if_fail (property_name != NULL, NULL);
628
629   value = g_hash_table_lookup (proxy->priv->properties, property_name);
630   if (value == NULL)
631     {
632       const GDBusPropertyInfo *info;
633       info = lookup_property_info_or_warn (proxy, property_name);
634       /* no difference */
635       goto out;
636     }
637
638   g_variant_ref (value);
639
640  out:
641   return value;
642 }
643
644 /**
645  * g_dbus_proxy_set_cached_property:
646  * @proxy: A #GDBusProxy
647  * @property_name: Property name.
648  * @value: Value for the property or %NULL to remove it from the cache.
649  *
650  * If @value is not %NULL, sets the cached value for the property with
651  * name @property_name to the value in @value.
652  *
653  * If @value is %NULL, then the cached value is removed from the
654  * property cache.
655  *
656  * If @proxy has an expected interface (see
657  * #GDBusProxy:g-interface-info), then @property_name (for existence)
658  * and @value (for the type) is checked against it.
659  *
660  * If the @value #GVariant is floating, it is consumed. This allows
661  * convenient 'inline' use of g_variant_new(), e.g.
662  * |[
663  *  g_dbus_proxy_set_cached_property (proxy,
664  *                                    "SomeProperty",
665  *                                    g_variant_new ("(si)",
666  *                                                  "A String",
667  *                                                  42));
668  * ]|
669  *
670  * Normally you will not need to use this method since @proxy is
671  * tracking changes using the
672  * <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
673  * D-Bus signal. However, for performance reasons an object may decide
674  * to not use this signal for some properties and instead use a
675  * proprietary out-of-band mechanism to transmit changes.
676  *
677  * As a concrete example, consider an object with a property
678  * <literal>ChatroomParticipants</literal> which is an array of
679  * strings. Instead of transmitting the same (long) array every time
680  * the property changes, it is more efficient to only transmit the
681  * delta using e.g. signals <literal>ChatroomParticipantJoined(String
682  * name)</literal> and <literal>ChatroomParticipantParted(String
683  * name)</literal>.
684  *
685  * Since: 2.26
686  */
687 void
688 g_dbus_proxy_set_cached_property (GDBusProxy   *proxy,
689                                   const gchar  *property_name,
690                                   GVariant     *value)
691 {
692   const GDBusPropertyInfo *info;
693
694   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
695   g_return_if_fail (property_name != NULL);
696
697   if (value != NULL)
698     {
699       info = lookup_property_info_or_warn (proxy, property_name);
700       if (info != NULL)
701         {
702           if (g_strcmp0 (info->signature, g_variant_get_type_string (value)) != 0)
703             {
704               g_warning (_("Trying to set property %s of type %s but according to the expected "
705                            "interface the type is %s"),
706                          property_name,
707                          g_variant_get_type_string (value),
708                          info->signature);
709               goto out;
710             }
711         }
712       g_hash_table_insert (proxy->priv->properties,
713                            g_strdup (property_name),
714                            g_variant_ref_sink (value));
715     }
716   else
717     {
718       g_hash_table_remove (proxy->priv->properties, property_name);
719     }
720
721  out:
722   ;
723 }
724
725 /* ---------------------------------------------------------------------------------------------------- */
726
727 static void
728 on_signal_received (GDBusConnection *connection,
729                     const gchar     *sender_name,
730                     const gchar     *object_path,
731                     const gchar     *interface_name,
732                     const gchar     *signal_name,
733                     GVariant        *parameters,
734                     gpointer         user_data)
735 {
736   GDBusProxy *proxy = G_DBUS_PROXY (user_data);
737
738   if (!proxy->priv->initialized)
739     goto out;
740
741   if (g_strcmp0 (sender_name, proxy->priv->name_owner) != 0)
742     goto out;
743
744   g_signal_emit (proxy,
745                  signals[SIGNAL_SIGNAL],
746                  0,
747                  sender_name,
748                  signal_name,
749                  parameters);
750  out:
751   ;
752 }
753
754 /* ---------------------------------------------------------------------------------------------------- */
755
756 static void
757 on_properties_changed (GDBusConnection *connection,
758                        const gchar     *sender_name,
759                        const gchar     *object_path,
760                        const gchar     *interface_name,
761                        const gchar     *signal_name,
762                        GVariant        *parameters,
763                        gpointer         user_data)
764 {
765   GDBusProxy *proxy = G_DBUS_PROXY (user_data);
766   GError *error;
767   const gchar *interface_name_for_signal;
768   GVariant *changed_properties;
769   gchar **invalidated_properties;
770   GVariantIter iter;
771   gchar *key;
772   GVariant *value;
773   guint n;
774
775   error = NULL;
776   changed_properties = NULL;
777   invalidated_properties = NULL;
778
779   if (!proxy->priv->initialized)
780     goto out;
781
782   if (g_strcmp0 (sender_name, proxy->priv->name_owner) != 0)
783     goto out;
784
785   if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
786     {
787       g_warning ("Value for PropertiesChanged signal with type `%s' does not match `(sa{sv}as)'",
788                  g_variant_get_type_string (parameters));
789       goto out;
790     }
791
792   g_variant_get (parameters,
793                  "(&s@a{sv}^a&s)",
794                  &interface_name_for_signal,
795                  &changed_properties,
796                  &invalidated_properties);
797
798   if (g_strcmp0 (interface_name_for_signal, proxy->priv->interface_name) != 0)
799     goto out;
800
801   g_variant_iter_init (&iter, changed_properties);
802   while (g_variant_iter_next (&iter, "{sv}", &key, &value))
803     {
804       g_hash_table_insert (proxy->priv->properties,
805                            key, /* adopts string */
806                            value); /* adopts value */
807     }
808
809   for (n = 0; invalidated_properties[n] != NULL; n++)
810     {
811       g_hash_table_remove (proxy->priv->properties, invalidated_properties[n]);
812     }
813
814   /* emit signal */
815   g_signal_emit (proxy, signals[PROPERTIES_CHANGED_SIGNAL],
816                  0,
817                  changed_properties,
818                  invalidated_properties);
819
820  out:
821   if (changed_properties != NULL)
822     g_variant_unref (changed_properties);
823   g_free (invalidated_properties);
824 }
825
826 /* ---------------------------------------------------------------------------------------------------- */
827
828 static void
829 process_get_all_reply (GDBusProxy *proxy,
830                        GVariant   *result)
831 {
832   GVariantIter *iter;
833   gchar *key;
834   GVariant *value;
835
836   if (strcmp (g_variant_get_type_string (result), "(a{sv})") != 0)
837     {
838       g_warning ("Value for GetAll reply with type `%s' does not match `(a{sv})'",
839                  g_variant_get_type_string (result));
840       goto out;
841     }
842
843   g_variant_get (result, "(a{sv})", &iter);
844   while (g_variant_iter_next (iter, "{sv}", &key, &value))
845     {
846       /*g_print ("got %s -> %s\n", key, g_variant_print (value, FALSE));*/
847
848       g_hash_table_insert (proxy->priv->properties,
849                            key, /* adopts string */
850                            value); /* adopts value */
851     }
852   g_variant_iter_free (iter);
853
854  out:
855   ;
856 }
857
858 typedef struct
859 {
860   GDBusProxy *proxy;
861   GCancellable *cancellable;
862   gchar *name_owner;
863 } LoadPropertiesOnNameOwnerChangedData;
864
865 static void
866 on_name_owner_changed_get_all_cb (GDBusConnection *connection,
867                                   GAsyncResult    *res,
868                                   gpointer         user_data)
869 {
870   LoadPropertiesOnNameOwnerChangedData *data = user_data;
871   GVariant *result;
872   GError *error;
873   gboolean cancelled;
874
875   cancelled = FALSE;
876
877   error = NULL;
878   result = g_dbus_connection_call_finish (connection,
879                                           res,
880                                           &error);
881   if (result == NULL)
882     {
883       if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED)
884         cancelled = TRUE;
885       /* We just ignore if GetAll() is failing. Because this might happen
886        * if the object has no properties at all. Or if the caller is
887        * not authorized to see the properties.
888        *
889        * Either way, apps can know about this by using
890        * get_cached_property_names() or get_cached_property().
891        *
892        * TODO: handle G_DBUS_DEBUG flag 'proxy' and, if enabled, log the
893        * fact that GetAll() failed
894        */
895       //g_debug ("error: %d %d %s", error->domain, error->code, error->message);
896       g_error_free (error);
897     }
898
899   /* and finally we can notify */
900   if (!cancelled)
901     {
902       g_free (data->proxy->priv->name_owner);
903       data->proxy->priv->name_owner = data->name_owner;
904       data->name_owner = NULL; /* to avoid an extra copy, we steal the string */
905
906       g_hash_table_remove_all (data->proxy->priv->properties);
907       if (result != NULL)
908         {
909           process_get_all_reply (data->proxy, result);
910           g_variant_unref (result);
911         }
912
913       g_object_notify (G_OBJECT (data->proxy), "g-name-owner");
914     }
915
916   if (data->cancellable == data->proxy->priv->get_all_cancellable)
917     data->proxy->priv->get_all_cancellable = NULL;
918
919   g_object_unref (data->proxy);
920   g_object_unref (data->cancellable);
921   g_free (data->name_owner);
922   g_free (data);
923 }
924
925 static void
926 on_name_owner_changed (GDBusConnection *connection,
927                        const gchar      *sender_name,
928                        const gchar      *object_path,
929                        const gchar      *interface_name,
930                        const gchar      *signal_name,
931                        GVariant         *parameters,
932                        gpointer          user_data)
933 {
934   GDBusProxy *proxy = G_DBUS_PROXY (user_data);
935   const gchar *name;
936   const gchar *old_owner;
937   const gchar *new_owner;
938
939   /* if we are already trying to load properties, cancel that */
940   if (proxy->priv->get_all_cancellable != NULL)
941     {
942       g_cancellable_cancel (proxy->priv->get_all_cancellable);
943       proxy->priv->get_all_cancellable = NULL;
944     }
945
946   g_variant_get (parameters,
947                  "(&s&s&s)",
948                  &name,
949                  &old_owner,
950                  &new_owner);
951
952   /* we only care about a specific name */
953   if (g_strcmp0 (name, proxy->priv->name) != 0)
954     goto out;
955
956   if (strlen (new_owner) == 0)
957     {
958       g_free (proxy->priv->name_owner);
959       proxy->priv->name_owner = NULL;
960       g_hash_table_remove_all (proxy->priv->properties);
961       g_object_notify (G_OBJECT (proxy), "g-name-owner");
962     }
963   else
964     {
965       /* ignore duplicates - this can happen when activating the service */
966       if (g_strcmp0 (new_owner, proxy->priv->name_owner) == 0)
967         goto out;
968
969       if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
970         {
971           g_free (proxy->priv->name_owner);
972           proxy->priv->name_owner = g_strdup (new_owner);
973           g_hash_table_remove_all (proxy->priv->properties);
974           g_object_notify (G_OBJECT (proxy), "g-name-owner");
975         }
976       else
977         {
978           LoadPropertiesOnNameOwnerChangedData *data;
979
980           /* start loading properties.. only then emit notify::g-name-owner .. we
981            * need to be able to cancel this in the event another NameOwnerChanged
982            * signal suddenly happens
983            */
984
985           g_assert (proxy->priv->get_all_cancellable == NULL);
986           proxy->priv->get_all_cancellable = g_cancellable_new ();
987           data = g_new0 (LoadPropertiesOnNameOwnerChangedData, 1);
988           data->proxy = g_object_ref (proxy);
989           data->cancellable = proxy->priv->get_all_cancellable;
990           data->name_owner = g_strdup (new_owner);
991           g_dbus_connection_call (proxy->priv->connection,
992                                   data->name_owner,
993                                   proxy->priv->object_path,
994                                   "org.freedesktop.DBus.Properties",
995                                   "GetAll",
996                                   g_variant_new ("(s)", proxy->priv->interface_name),
997                                   G_VARIANT_TYPE ("(a{sv})"),
998                                   G_DBUS_CALL_FLAGS_NONE,
999                                   -1,           /* timeout */
1000                                   proxy->priv->get_all_cancellable,
1001                                   (GAsyncReadyCallback) on_name_owner_changed_get_all_cb,
1002                                   data);
1003         }
1004     }
1005
1006  out:
1007   ;
1008 }
1009
1010 /* ---------------------------------------------------------------------------------------------------- */
1011
1012 typedef struct
1013 {
1014   GDBusProxy *proxy;
1015   GCancellable *cancellable;
1016   GSimpleAsyncResult *simple;
1017 } AsyncInitData;
1018
1019 static void
1020 async_init_data_free (AsyncInitData *data)
1021 {
1022   g_object_unref (data->proxy);
1023   if (data->cancellable != NULL)
1024     g_object_unref (data->cancellable);
1025   g_object_unref (data->simple);
1026   g_free (data);
1027 }
1028
1029 static void
1030 async_init_get_all_cb (GDBusConnection *connection,
1031                        GAsyncResult    *res,
1032                        gpointer         user_data)
1033 {
1034   AsyncInitData *data = user_data;
1035   GVariant *result;
1036   GError *error;
1037
1038   error = NULL;
1039   result = g_dbus_connection_call_finish (connection,
1040                                           res,
1041                                           &error);
1042   if (result == NULL)
1043     {
1044       /* We just ignore if GetAll() is failing. Because this might happen
1045        * if the object has no properties at all. Or if the caller is
1046        * not authorized to see the properties.
1047        *
1048        * Either way, apps can know about this by using
1049        * get_cached_property_names() or get_cached_property().
1050        *
1051        * TODO: handle G_DBUS_DEBUG flag 'proxy' and, if enabled, log the
1052        * fact that GetAll() failed
1053        */
1054       //g_debug ("error: %d %d %s", error->domain, error->code, error->message);
1055       g_error_free (error);
1056     }
1057   else
1058     {
1059       g_simple_async_result_set_op_res_gpointer (data->simple,
1060                                                  result,
1061                                                  (GDestroyNotify) g_variant_unref);
1062     }
1063
1064   g_simple_async_result_complete_in_idle (data->simple);
1065   async_init_data_free (data);
1066 }
1067
1068
1069 static void
1070 async_init_get_name_owner_cb (GDBusConnection *connection,
1071                               GAsyncResult    *res,
1072                               gpointer         user_data)
1073 {
1074   AsyncInitData *data = user_data;
1075
1076   if (res != NULL)
1077     {
1078       GError *error;
1079       GVariant *result;
1080
1081       error = NULL;
1082       result = g_dbus_connection_call_finish (connection,
1083                                               res,
1084                                               &error);
1085       if (result == NULL)
1086         {
1087           if (error->domain == G_DBUS_ERROR &&
1088               error->code == G_DBUS_ERROR_NAME_HAS_NO_OWNER)
1089             {
1090               g_error_free (error);
1091             }
1092           else
1093             {
1094               g_simple_async_result_set_from_error (data->simple, error);
1095               g_error_free (error);
1096               g_simple_async_result_complete_in_idle (data->simple);
1097               async_init_data_free (data);
1098               goto out;
1099             }
1100         }
1101       else
1102         {
1103           g_variant_get (result,
1104                          "(s)",
1105                          &data->proxy->priv->name_owner);
1106           g_variant_unref (result);
1107         }
1108     }
1109
1110   if (!(data->proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
1111     {
1112       /* load all properties asynchronously */
1113       g_dbus_connection_call (data->proxy->priv->connection,
1114                               data->proxy->priv->name_owner,
1115                               data->proxy->priv->object_path,
1116                               "org.freedesktop.DBus.Properties",
1117                               "GetAll",
1118                               g_variant_new ("(s)", data->proxy->priv->interface_name),
1119                               G_VARIANT_TYPE ("(a{sv})"),
1120                               G_DBUS_CALL_FLAGS_NONE,
1121                               -1,           /* timeout */
1122                               data->cancellable,
1123                               (GAsyncReadyCallback) async_init_get_all_cb,
1124                               data);
1125     }
1126   else
1127     {
1128       g_simple_async_result_complete_in_idle (data->simple);
1129       async_init_data_free (data);
1130     }
1131
1132  out:
1133   ;
1134 }
1135
1136 static void
1137 async_init_call_get_name_owner (AsyncInitData *data)
1138 {
1139   g_dbus_connection_call (data->proxy->priv->connection,
1140                           "org.freedesktop.DBus",  /* name */
1141                           "/org/freedesktop/DBus", /* object path */
1142                           "org.freedesktop.DBus",  /* interface */
1143                           "GetNameOwner",
1144                           g_variant_new ("(s)",
1145                                          data->proxy->priv->name),
1146                           G_VARIANT_TYPE ("(s)"),
1147                           G_DBUS_CALL_FLAGS_NONE,
1148                           -1,           /* timeout */
1149                           data->cancellable,
1150                           (GAsyncReadyCallback) async_init_get_name_owner_cb,
1151                           data);
1152 }
1153
1154 static void
1155 async_init_start_service_by_name_cb (GDBusConnection *connection,
1156                                      GAsyncResult    *res,
1157                                      gpointer         user_data)
1158 {
1159   AsyncInitData *data = user_data;
1160   GError *error;
1161   GVariant *result;
1162
1163   error = NULL;
1164   result = g_dbus_connection_call_finish (connection,
1165                                           res,
1166                                           &error);
1167   if (result == NULL)
1168     {
1169       /* Errors are not unexpected; the bus will reply e.g.
1170        *
1171        *   org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.Epiphany2
1172        *   was not provided by any .service files
1173        *
1174        * This doesn't mean that the name doesn't have an owner, just
1175        * that it's not provided by a .service file. So just proceed to
1176        * invoke GetNameOwner() if dealing with that error.
1177        */
1178       if (error->domain == G_DBUS_ERROR &&
1179           error->code == G_DBUS_ERROR_SERVICE_UNKNOWN)
1180         {
1181           g_error_free (error);
1182         }
1183       else
1184         {
1185           g_prefix_error (&error,
1186                           _("Error calling StartServiceByName for %s: "),
1187                           data->proxy->priv->name);
1188           goto failed;
1189         }
1190     }
1191   else
1192     {
1193       guint32 start_service_result;
1194       g_variant_get (result,
1195                      "(u)",
1196                      &start_service_result);
1197       g_variant_unref (result);
1198       if (start_service_result == 1 ||  /* DBUS_START_REPLY_SUCCESS */
1199           start_service_result == 2)    /* DBUS_START_REPLY_ALREADY_RUNNING */
1200         {
1201           /* continue to invoke GetNameOwner() */
1202         }
1203       else
1204         {
1205           error = g_error_new (G_IO_ERROR,
1206                                G_IO_ERROR_FAILED,
1207                                _("Unexpected reply %d from StartServiceByName(\"%s\") method"),
1208                                start_service_result,
1209                                data->proxy->priv->name);
1210           goto failed;
1211         }
1212     }
1213
1214   async_init_call_get_name_owner (data);
1215   return;
1216
1217  failed:
1218   g_warn_if_fail (error != NULL);
1219   g_simple_async_result_set_from_error (data->simple, error);
1220   g_error_free (error);
1221   g_simple_async_result_complete_in_idle (data->simple);
1222   async_init_data_free (data);
1223 }
1224
1225 static void
1226 async_init_call_start_service_by_name (AsyncInitData *data)
1227 {
1228   g_dbus_connection_call (data->proxy->priv->connection,
1229                           "org.freedesktop.DBus",  /* name */
1230                           "/org/freedesktop/DBus", /* object path */
1231                           "org.freedesktop.DBus",  /* interface */
1232                           "StartServiceByName",
1233                           g_variant_new ("(su)",
1234                                          data->proxy->priv->name,
1235                                          0),
1236                           G_VARIANT_TYPE ("(u)"),
1237                           G_DBUS_CALL_FLAGS_NONE,
1238                           -1,           /* timeout */
1239                           data->cancellable,
1240                           (GAsyncReadyCallback) async_init_start_service_by_name_cb,
1241                           data);
1242 }
1243
1244 static void
1245 async_initable_init_second_async (GAsyncInitable      *initable,
1246                                   gint                 io_priority,
1247                                   GCancellable        *cancellable,
1248                                   GAsyncReadyCallback  callback,
1249                                   gpointer             user_data)
1250 {
1251   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1252   AsyncInitData *data;
1253
1254   data = g_new0 (AsyncInitData, 1);
1255   data->proxy = g_object_ref (proxy);
1256   data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
1257   data->simple = g_simple_async_result_new (G_OBJECT (proxy),
1258                                             callback,
1259                                             user_data,
1260                                             NULL);
1261
1262   /* Check name ownership asynchronously - possibly also start the service */
1263   if (proxy->priv->name == NULL)
1264     {
1265       /* Do nothing */
1266       async_init_get_name_owner_cb (proxy->priv->connection, NULL, data);
1267     }
1268   else if (g_dbus_is_unique_name (proxy->priv->name))
1269     {
1270       proxy->priv->name_owner = g_strdup (proxy->priv->name);
1271       async_init_get_name_owner_cb (proxy->priv->connection, NULL, data);
1272     }
1273   else
1274     {
1275       if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)
1276         {
1277           async_init_call_get_name_owner (data);
1278         }
1279       else
1280         {
1281           async_init_call_start_service_by_name (data);
1282         }
1283     }
1284 }
1285
1286 static gboolean
1287 async_initable_init_second_finish (GAsyncInitable  *initable,
1288                                    GAsyncResult    *res,
1289                                    GError         **error)
1290 {
1291   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1292   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
1293   GVariant *result;
1294   gboolean ret;
1295
1296   ret = FALSE;
1297
1298   if (g_simple_async_result_propagate_error (simple, error))
1299     goto out;
1300
1301   result = g_simple_async_result_get_op_res_gpointer (simple);
1302   if (result != NULL)
1303     {
1304       process_get_all_reply (proxy, result);
1305     }
1306
1307   ret = TRUE;
1308
1309  out:
1310   proxy->priv->initialized = TRUE;
1311   return ret;
1312 }
1313
1314 /* ---------------------------------------------------------------------------------------------------- */
1315
1316 static void
1317 async_initable_init_first (GAsyncInitable *initable)
1318 {
1319   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1320
1321   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
1322     {
1323       /* subscribe to PropertiesChanged() */
1324       proxy->priv->properties_changed_subscriber_id =
1325         g_dbus_connection_signal_subscribe (proxy->priv->connection,
1326                                             proxy->priv->name,
1327                                             "org.freedesktop.DBus.Properties",
1328                                             "PropertiesChanged",
1329                                             proxy->priv->object_path,
1330                                             proxy->priv->interface_name,
1331                                             on_properties_changed,
1332                                             proxy,
1333                                             NULL);
1334     }
1335
1336   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS))
1337     {
1338       /* subscribe to all signals for the object */
1339       proxy->priv->signals_subscriber_id =
1340         g_dbus_connection_signal_subscribe (proxy->priv->connection,
1341                                             proxy->priv->name,
1342                                             proxy->priv->interface_name,
1343                                             NULL,                        /* member */
1344                                             proxy->priv->object_path,
1345                                             NULL,                        /* arg0 */
1346                                             on_signal_received,
1347                                             proxy,
1348                                             NULL);
1349     }
1350
1351   if (proxy->priv->name != NULL && !g_dbus_is_unique_name (proxy->priv->name))
1352     {
1353       proxy->priv->name_owner_changed_subscription_id =
1354         g_dbus_connection_signal_subscribe (proxy->priv->connection,
1355                                             "org.freedesktop.DBus",  /* name */
1356                                             "org.freedesktop.DBus",  /* interface */
1357                                             "NameOwnerChanged",      /* signal name */
1358                                             "/org/freedesktop/DBus", /* path */
1359                                             proxy->priv->name,       /* arg0 */
1360                                             on_name_owner_changed,
1361                                             proxy,
1362                                             NULL);
1363     }
1364 }
1365
1366 /* ---------------------------------------------------------------------------------------------------- */
1367
1368 /* initialization is split into two parts - the first is the
1369  * non-blocing part that requires the callers GMainContext - the
1370  * second is a blocking part async part that doesn't require the
1371  * callers GMainContext.. we do this split so the code can be reused
1372  * in the GInitable implementation below.
1373  *
1374  * Note that obtaining a GDBusConnection is not shared between the two
1375  * paths.
1376  */
1377
1378 typedef struct
1379 {
1380   GDBusProxy          *proxy;
1381   gint                 io_priority;
1382   GCancellable        *cancellable;
1383   GAsyncReadyCallback  callback;
1384   gpointer             user_data;
1385 } GetConnectionData;
1386
1387 static void
1388 get_connection_cb (GObject       *source_object,
1389                    GAsyncResult  *res,
1390                    gpointer       user_data)
1391 {
1392   GetConnectionData *data = user_data;
1393   GError *error;
1394
1395   data->proxy->priv->connection = g_bus_get_finish (res, &error);
1396   if (data->proxy->priv->connection == NULL)
1397     {
1398       GSimpleAsyncResult *simple;
1399       simple = g_simple_async_result_new (G_OBJECT (data->proxy),
1400                                           data->callback,
1401                                           data->user_data,
1402                                           NULL);
1403       g_simple_async_result_set_from_error (simple, error);
1404       g_error_free (error);
1405       g_simple_async_result_complete_in_idle (simple);
1406       g_object_unref (simple);
1407     }
1408   else
1409     {
1410       async_initable_init_first (G_ASYNC_INITABLE (data->proxy));
1411       async_initable_init_second_async (G_ASYNC_INITABLE (data->proxy),
1412                                         data->io_priority,
1413                                         data->cancellable,
1414                                         data->callback,
1415                                         data->user_data);
1416     }
1417
1418   if (data->cancellable != NULL)
1419     g_object_unref (data->cancellable);
1420   g_free (data);
1421 }
1422
1423 static void
1424 async_initable_init_async (GAsyncInitable      *initable,
1425                            gint                 io_priority,
1426                            GCancellable        *cancellable,
1427                            GAsyncReadyCallback  callback,
1428                            gpointer             user_data)
1429 {
1430   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1431
1432   if (proxy->priv->bus_type != G_BUS_TYPE_NONE)
1433     {
1434       GetConnectionData *data;
1435
1436       g_assert (proxy->priv->connection == NULL);
1437
1438       data = g_new0 (GetConnectionData, 1);
1439       data->proxy = proxy;
1440       data->io_priority = io_priority;
1441       data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
1442       data->callback = callback;
1443       data->user_data = user_data;
1444       g_bus_get (proxy->priv->bus_type,
1445                  cancellable,
1446                  get_connection_cb,
1447                  data);
1448     }
1449   else
1450     {
1451       async_initable_init_first (initable);
1452       async_initable_init_second_async (initable, io_priority, cancellable, callback, user_data);
1453     }
1454 }
1455
1456 static gboolean
1457 async_initable_init_finish (GAsyncInitable  *initable,
1458                             GAsyncResult    *res,
1459                             GError         **error)
1460 {
1461   return async_initable_init_second_finish (initable, res, error);
1462 }
1463
1464 static void
1465 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
1466 {
1467   async_initable_iface->init_async = async_initable_init_async;
1468   async_initable_iface->init_finish = async_initable_init_finish;
1469 }
1470
1471 /* ---------------------------------------------------------------------------------------------------- */
1472
1473 typedef struct
1474 {
1475   GMainContext *context;
1476   GMainLoop *loop;
1477   GAsyncResult *res;
1478 } InitableAsyncInitableData;
1479
1480 static void
1481 async_initable_init_async_cb (GObject      *source_object,
1482                               GAsyncResult *res,
1483                               gpointer      user_data)
1484 {
1485   InitableAsyncInitableData *data = user_data;
1486   data->res = g_object_ref (res);
1487   g_main_loop_quit (data->loop);
1488 }
1489
1490 /* Simply reuse the GAsyncInitable implementation but run the first
1491  * part (that is non-blocking and requires the callers GMainContext)
1492  * with the callers GMainContext.. and the second with a private
1493  * GMainContext (bug 621310 is slightly related).
1494  *
1495  * Note that obtaining a GDBusConnection is not shared between the two
1496  * paths.
1497  */
1498 static gboolean
1499 initable_init (GInitable     *initable,
1500                GCancellable  *cancellable,
1501                GError       **error)
1502 {
1503   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1504   InitableAsyncInitableData *data;
1505   gboolean ret;
1506
1507   ret = FALSE;
1508
1509   if (proxy->priv->bus_type != G_BUS_TYPE_NONE)
1510     {
1511       g_assert (proxy->priv->connection == NULL);
1512       proxy->priv->connection = g_bus_get_sync (proxy->priv->bus_type,
1513                                                 cancellable,
1514                                                 error);
1515       if (proxy->priv->connection == NULL)
1516         goto out;
1517     }
1518
1519   async_initable_init_first (G_ASYNC_INITABLE (initable));
1520
1521   data = g_new0 (InitableAsyncInitableData, 1);
1522   data->context = g_main_context_new ();
1523   data->loop = g_main_loop_new (data->context, FALSE);
1524
1525   g_main_context_push_thread_default (data->context);
1526
1527   async_initable_init_second_async (G_ASYNC_INITABLE (initable),
1528                                     G_PRIORITY_DEFAULT,
1529                                     cancellable,
1530                                     async_initable_init_async_cb,
1531                                     data);
1532
1533   g_main_loop_run (data->loop);
1534
1535   ret = async_initable_init_second_finish (G_ASYNC_INITABLE (initable),
1536                                            data->res,
1537                                            error);
1538
1539   g_main_context_pop_thread_default (data->context);
1540
1541   g_main_context_unref (data->context);
1542   g_main_loop_unref (data->loop);
1543   g_object_unref (data->res);
1544   g_free (data);
1545
1546  out:
1547
1548   return ret;
1549 }
1550
1551 static void
1552 initable_iface_init (GInitableIface *initable_iface)
1553 {
1554   initable_iface->init = initable_init;
1555 }
1556
1557 /* ---------------------------------------------------------------------------------------------------- */
1558
1559 /**
1560  * g_dbus_proxy_new:
1561  * @connection: A #GDBusConnection.
1562  * @flags: Flags used when constructing the proxy.
1563  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1564  * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
1565  * @object_path: An object path.
1566  * @interface_name: A D-Bus interface name.
1567  * @cancellable: A #GCancellable or %NULL.
1568  * @callback: Callback function to invoke when the proxy is ready.
1569  * @user_data: User data to pass to @callback.
1570  *
1571  * Creates a proxy for accessing @interface_name on the remote object
1572  * at @object_path owned by @name at @connection and asynchronously
1573  * loads D-Bus properties unless the
1574  * #G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used. Connect to
1575  * the #GDBusProxy::g-properties-changed signal to get notified about
1576  * property changes.
1577  *
1578  * If the #G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
1579  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
1580  * to handle signals from the remote object.
1581  *
1582  * If @name is a well-known name and the
1583  * #G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag isn't set and no name
1584  * owner currently exists, the message bus will be requested to launch
1585  * a name owner for the name.
1586  *
1587  * This is a failable asynchronous constructor - when the proxy is
1588  * ready, @callback will be invoked and you can use
1589  * g_dbus_proxy_new_finish() to get the result.
1590  *
1591  * See g_dbus_proxy_new_sync() and for a synchronous version of this constructor.
1592  *
1593  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1594  *
1595  * Since: 2.26
1596  */
1597 void
1598 g_dbus_proxy_new (GDBusConnection     *connection,
1599                   GDBusProxyFlags      flags,
1600                   GDBusInterfaceInfo  *info,
1601                   const gchar         *name,
1602                   const gchar         *object_path,
1603                   const gchar         *interface_name,
1604                   GCancellable        *cancellable,
1605                   GAsyncReadyCallback  callback,
1606                   gpointer             user_data)
1607 {
1608   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1609   g_return_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) || g_dbus_is_name (name));
1610   g_return_if_fail (g_variant_is_object_path (object_path));
1611   g_return_if_fail (g_dbus_is_interface_name (interface_name));
1612
1613   g_async_initable_new_async (G_TYPE_DBUS_PROXY,
1614                               G_PRIORITY_DEFAULT,
1615                               cancellable,
1616                               callback,
1617                               user_data,
1618                               "g-flags", flags,
1619                               "g-interface-info", info,
1620                               "g-name", name,
1621                               "g-connection", connection,
1622                               "g-object-path", object_path,
1623                               "g-interface-name", interface_name,
1624                               NULL);
1625 }
1626
1627 /**
1628  * g_dbus_proxy_new_finish:
1629  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new().
1630  * @error: Return location for error or %NULL.
1631  *
1632  * Finishes creating a #GDBusProxy.
1633  *
1634  * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
1635  *
1636  * Since: 2.26
1637  */
1638 GDBusProxy *
1639 g_dbus_proxy_new_finish (GAsyncResult  *res,
1640                          GError       **error)
1641 {
1642   GObject *object;
1643   GObject *source_object;
1644
1645   source_object = g_async_result_get_source_object (res);
1646   g_assert (source_object != NULL);
1647
1648   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
1649                                         res,
1650                                         error);
1651   g_object_unref (source_object);
1652
1653   if (object != NULL)
1654     return G_DBUS_PROXY (object);
1655   else
1656     return NULL;
1657 }
1658
1659 /**
1660  * g_dbus_proxy_new_sync:
1661  * @connection: A #GDBusConnection.
1662  * @flags: Flags used when constructing the proxy.
1663  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1664  * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
1665  * @object_path: An object path.
1666  * @interface_name: A D-Bus interface name.
1667  * @cancellable: A #GCancellable or %NULL.
1668  * @error: Return location for error or %NULL.
1669  *
1670  * Creates a proxy for accessing @interface_name on the remote object
1671  * at @object_path owned by @name at @connection and synchronously
1672  * loads D-Bus properties unless the
1673  * #G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used.
1674  *
1675  * If the #G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
1676  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
1677  * to handle signals from the remote object.
1678  *
1679  * If @name is a well-known name and the
1680  * #G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag isn't set and no name
1681  * owner currently exists, the message bus will be requested to launch
1682  * a name owner for the name.
1683  *
1684  * This is a synchronous failable constructor. See g_dbus_proxy_new()
1685  * and g_dbus_proxy_new_finish() for the asynchronous version.
1686  *
1687  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1688  *
1689  * Returns: A #GDBusProxy or %NULL if error is set. Free with g_object_unref().
1690  *
1691  * Since: 2.26
1692  */
1693 GDBusProxy *
1694 g_dbus_proxy_new_sync (GDBusConnection     *connection,
1695                        GDBusProxyFlags      flags,
1696                        GDBusInterfaceInfo  *info,
1697                        const gchar         *name,
1698                        const gchar         *object_path,
1699                        const gchar         *interface_name,
1700                        GCancellable        *cancellable,
1701                        GError             **error)
1702 {
1703   GInitable *initable;
1704
1705   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1706   g_return_val_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
1707                         g_dbus_is_name (name), NULL);
1708   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
1709   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
1710
1711   initable = g_initable_new (G_TYPE_DBUS_PROXY,
1712                              cancellable,
1713                              error,
1714                              "g-flags", flags,
1715                              "g-interface-info", info,
1716                              "g-name", name,
1717                              "g-connection", connection,
1718                              "g-object-path", object_path,
1719                              "g-interface-name", interface_name,
1720                              NULL);
1721   if (initable != NULL)
1722     return G_DBUS_PROXY (initable);
1723   else
1724     return NULL;
1725 }
1726
1727 /* ---------------------------------------------------------------------------------------------------- */
1728
1729 /**
1730  * g_dbus_proxy_new_for_bus:
1731  * @bus_type: A #GBusType.
1732  * @flags: Flags used when constructing the proxy.
1733  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1734  * @name: A bus name (well-known or unique).
1735  * @object_path: An object path.
1736  * @interface_name: A D-Bus interface name.
1737  * @cancellable: A #GCancellable or %NULL.
1738  * @callback: Callback function to invoke when the proxy is ready.
1739  * @user_data: User data to pass to @callback.
1740  *
1741  * Like g_dbus_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
1742  *
1743  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1744  *
1745  * Since: 2.26
1746  */
1747 void
1748 g_dbus_proxy_new_for_bus (GBusType             bus_type,
1749                           GDBusProxyFlags      flags,
1750                           GDBusInterfaceInfo  *info,
1751                           const gchar         *name,
1752                           const gchar         *object_path,
1753                           const gchar         *interface_name,
1754                           GCancellable        *cancellable,
1755                           GAsyncReadyCallback  callback,
1756                           gpointer             user_data)
1757 {
1758   g_return_if_fail (g_dbus_is_name (name));
1759   g_return_if_fail (g_variant_is_object_path (object_path));
1760   g_return_if_fail (g_dbus_is_interface_name (interface_name));
1761
1762   g_async_initable_new_async (G_TYPE_DBUS_PROXY,
1763                               G_PRIORITY_DEFAULT,
1764                               cancellable,
1765                               callback,
1766                               user_data,
1767                               "g-flags", flags,
1768                               "g-interface-info", info,
1769                               "g-name", name,
1770                               "g-bus-type", bus_type,
1771                               "g-object-path", object_path,
1772                               "g-interface-name", interface_name,
1773                               NULL);
1774 }
1775
1776 /**
1777  * g_dbus_proxy_new_for_bus_finish:
1778  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new_for_bus().
1779  * @error: Return location for error or %NULL.
1780  *
1781  * Finishes creating a #GDBusProxy.
1782  *
1783  * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
1784  *
1785  * Since: 2.26
1786  */
1787 GDBusProxy *
1788 g_dbus_proxy_new_for_bus_finish (GAsyncResult  *res,
1789                                  GError       **error)
1790 {
1791   return g_dbus_proxy_new_finish (res, error);
1792 }
1793
1794 /**
1795  * g_dbus_proxy_new_for_bus_sync:
1796  * @bus_type: A #GBusType.
1797  * @flags: Flags used when constructing the proxy.
1798  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1799  * @name: A bus name (well-known or unique).
1800  * @object_path: An object path.
1801  * @interface_name: A D-Bus interface name.
1802  * @cancellable: A #GCancellable or %NULL.
1803  * @error: Return location for error or %NULL.
1804  *
1805  * Like g_dbus_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
1806  *
1807  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1808  *
1809  * Returns: A #GDBusProxy or %NULL if error is set. Free with g_object_unref().
1810  *
1811  * Since: 2.26
1812  */
1813 GDBusProxy *
1814 g_dbus_proxy_new_for_bus_sync (GBusType             bus_type,
1815                                GDBusProxyFlags      flags,
1816                                GDBusInterfaceInfo  *info,
1817                                const gchar         *name,
1818                                const gchar         *object_path,
1819                                const gchar         *interface_name,
1820                                GCancellable        *cancellable,
1821                                GError             **error)
1822 {
1823   GInitable *initable;
1824
1825   g_return_val_if_fail (g_dbus_is_name (name), NULL);
1826   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
1827   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
1828
1829   initable = g_initable_new (G_TYPE_DBUS_PROXY,
1830                              cancellable,
1831                              error,
1832                              "g-flags", flags,
1833                              "g-interface-info", info,
1834                              "g-name", name,
1835                              "g-bus-type", bus_type,
1836                              "g-object-path", object_path,
1837                              "g-interface-name", interface_name,
1838                              NULL);
1839   if (initable != NULL)
1840     return G_DBUS_PROXY (initable);
1841   else
1842     return NULL;
1843 }
1844
1845 /* ---------------------------------------------------------------------------------------------------- */
1846
1847 /**
1848  * g_dbus_proxy_get_connection:
1849  * @proxy: A #GDBusProxy.
1850  *
1851  * Gets the connection @proxy is for.
1852  *
1853  * Returns: A #GDBusConnection owned by @proxy. Do not free.
1854  *
1855  * Since: 2.26
1856  */
1857 GDBusConnection *
1858 g_dbus_proxy_get_connection (GDBusProxy *proxy)
1859 {
1860   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1861   return proxy->priv->connection;
1862 }
1863
1864 /**
1865  * g_dbus_proxy_get_flags:
1866  * @proxy: A #GDBusProxy.
1867  *
1868  * Gets the flags that @proxy was constructed with.
1869  *
1870  * Returns: Flags from the #GDBusProxyFlags enumeration.
1871  *
1872  * Since: 2.26
1873  */
1874 GDBusProxyFlags
1875 g_dbus_proxy_get_flags (GDBusProxy *proxy)
1876 {
1877   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
1878   return proxy->priv->flags;
1879 }
1880
1881 /**
1882  * g_dbus_proxy_get_name:
1883  * @proxy: A #GDBusProxy.
1884  *
1885  * Gets the name that @proxy was constructed for.
1886  *
1887  * Returns: A string owned by @proxy. Do not free.
1888  *
1889  * Since: 2.26
1890  */
1891 const gchar *
1892 g_dbus_proxy_get_name (GDBusProxy *proxy)
1893 {
1894   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1895   return proxy->priv->name;
1896 }
1897
1898 /**
1899  * g_dbus_proxy_get_name_owner:
1900  * @proxy: A #GDBusProxy.
1901  *
1902  * The unique name that owns the name that @proxy is for or %NULL if
1903  * no-one currently owns that name. You may connect to the
1904  * #GObject::notify signal to track changes to the
1905  * #GDBusProxy:g-name-owner property.
1906  *
1907  * Returns: The name owner or %NULL if no name owner exists. Free with g_free().
1908  *
1909  * Since: 2.26
1910  */
1911 gchar *
1912 g_dbus_proxy_get_name_owner (GDBusProxy *proxy)
1913 {
1914   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1915   return g_strdup (proxy->priv->name_owner);
1916 }
1917
1918 /**
1919  * g_dbus_proxy_get_object_path:
1920  * @proxy: A #GDBusProxy.
1921  *
1922  * Gets the object path @proxy is for.
1923  *
1924  * Returns: A string owned by @proxy. Do not free.
1925  *
1926  * Since: 2.26
1927  */
1928 const gchar *
1929 g_dbus_proxy_get_object_path (GDBusProxy *proxy)
1930 {
1931   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1932   return proxy->priv->object_path;
1933 }
1934
1935 /**
1936  * g_dbus_proxy_get_interface_name:
1937  * @proxy: A #GDBusProxy.
1938  *
1939  * Gets the D-Bus interface name @proxy is for.
1940  *
1941  * Returns: A string owned by @proxy. Do not free.
1942  *
1943  * Since: 2.26
1944  */
1945 const gchar *
1946 g_dbus_proxy_get_interface_name (GDBusProxy *proxy)
1947 {
1948   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1949   return proxy->priv->interface_name;
1950 }
1951
1952 /**
1953  * g_dbus_proxy_get_default_timeout:
1954  * @proxy: A #GDBusProxy.
1955  *
1956  * Gets the timeout to use if -1 (specifying default timeout) is
1957  * passed as @timeout_msec in the g_dbus_proxy_call() and
1958  * g_dbus_proxy_call_sync() functions.
1959  *
1960  * See the #GDBusProxy:g-default-timeout property for more details.
1961  *
1962  * Returns: Timeout to use for @proxy.
1963  *
1964  * Since: 2.26
1965  */
1966 gint
1967 g_dbus_proxy_get_default_timeout (GDBusProxy *proxy)
1968 {
1969   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), -1);
1970   return proxy->priv->timeout_msec;
1971 }
1972
1973 /**
1974  * g_dbus_proxy_set_default_timeout:
1975  * @proxy: A #GDBusProxy.
1976  * @timeout_msec: Timeout in milliseconds.
1977  *
1978  * Sets the timeout to use if -1 (specifying default timeout) is
1979  * passed as @timeout_msec in the g_dbus_proxy_call() and
1980  * g_dbus_proxy_call_sync() functions.
1981  *
1982  * See the #GDBusProxy:g-default-timeout property for more details.
1983  *
1984  * Since: 2.26
1985  */
1986 void
1987 g_dbus_proxy_set_default_timeout (GDBusProxy *proxy,
1988                                   gint        timeout_msec)
1989 {
1990   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
1991   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
1992
1993   /* TODO: locking? */
1994   if (proxy->priv->timeout_msec != timeout_msec)
1995     {
1996       proxy->priv->timeout_msec = timeout_msec;
1997       g_object_notify (G_OBJECT (proxy), "g-default-timeout");
1998     }
1999 }
2000
2001 /**
2002  * g_dbus_proxy_get_interface_info:
2003  * @proxy: A #GDBusProxy
2004  *
2005  * Returns the #GDBusInterfaceInfo, if any, specifying the minimal
2006  * interface that @proxy conforms to.
2007  *
2008  * See the #GDBusProxy:g-interface-info property for more details.
2009  *
2010  * Returns: A #GDBusInterfaceInfo or %NULL. Do not unref the returned
2011  * object, it is owned by @proxy.
2012  *
2013  * Since: 2.26
2014  */
2015 GDBusInterfaceInfo *
2016 g_dbus_proxy_get_interface_info (GDBusProxy *proxy)
2017 {
2018   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2019   return proxy->priv->expected_interface;
2020 }
2021
2022 /**
2023  * g_dbus_proxy_set_interface_info:
2024  * @proxy: A #GDBusProxy
2025  * @info: Minimum interface this proxy conforms to or %NULL to unset.
2026  *
2027  * Ensure that interactions with @proxy conform to the given
2028  * interface.  For example, when completing a method call, if the type
2029  * signature of the message isn't what's expected, the given #GError
2030  * is set.  Signals that have a type signature mismatch are simply
2031  * dropped.
2032  *
2033  * See the #GDBusProxy:g-interface-info property for more details.
2034  *
2035  * Since: 2.26
2036  */
2037 void
2038 g_dbus_proxy_set_interface_info (GDBusProxy         *proxy,
2039                                  GDBusInterfaceInfo *info)
2040 {
2041   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
2042   if (proxy->priv->expected_interface != NULL)
2043     g_dbus_interface_info_unref (proxy->priv->expected_interface);
2044   proxy->priv->expected_interface = info != NULL ? g_dbus_interface_info_ref (info) : NULL;
2045 }
2046
2047 /* ---------------------------------------------------------------------------------------------------- */
2048
2049 static gboolean
2050 maybe_split_method_name (const gchar  *method_name,
2051                          gchar       **out_interface_name,
2052                          const gchar **out_method_name)
2053 {
2054   gboolean was_split;
2055
2056   was_split = FALSE;
2057   g_assert (out_interface_name != NULL);
2058   g_assert (out_method_name != NULL);
2059   *out_interface_name = NULL;
2060   *out_method_name = NULL;
2061
2062   if (strchr (method_name, '.') != NULL)
2063     {
2064       gchar *p;
2065       gchar *last_dot;
2066
2067       p = g_strdup (method_name);
2068       last_dot = strrchr (p, '.');
2069       *last_dot = '\0';
2070
2071       *out_interface_name = p;
2072       *out_method_name = last_dot + 1;
2073
2074       was_split = TRUE;
2075     }
2076
2077   return was_split;
2078 }
2079
2080
2081 static void
2082 reply_cb (GDBusConnection *connection,
2083           GAsyncResult    *res,
2084           gpointer         user_data)
2085 {
2086   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
2087   GVariant *value;
2088   GError *error;
2089
2090   error = NULL;
2091   value = g_dbus_connection_call_finish (connection,
2092                                          res,
2093                                          &error);
2094   if (error != NULL)
2095     {
2096       g_simple_async_result_set_from_error (simple,
2097                                             error);
2098       g_error_free (error);
2099     }
2100   else
2101     {
2102       g_simple_async_result_set_op_res_gpointer (simple,
2103                                                  value,
2104                                                  (GDestroyNotify) g_variant_unref);
2105     }
2106
2107   /* no need to complete in idle since the method GDBusConnection already does */
2108   g_simple_async_result_complete (simple);
2109 }
2110
2111 static const GDBusMethodInfo *
2112 lookup_method_info_or_warn (GDBusProxy  *proxy,
2113                             const gchar *method_name)
2114 {
2115   const GDBusMethodInfo *info;
2116
2117   if (proxy->priv->expected_interface == NULL)
2118     return NULL;
2119
2120   info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, method_name);
2121   if (info == NULL)
2122     {
2123       g_warning ("Trying to invoke method %s which isn't in expected interface %s",
2124                  method_name, proxy->priv->expected_interface->name);
2125     }
2126
2127   return info;
2128 }
2129
2130 /**
2131  * g_dbus_proxy_call:
2132  * @proxy: A #GDBusProxy.
2133  * @method_name: Name of method to invoke.
2134  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
2135  * @flags: Flags from the #GDBusCallFlags enumeration.
2136  * @timeout_msec: The timeout in milliseconds or -1 to use the proxy default timeout.
2137  * @cancellable: A #GCancellable or %NULL.
2138  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
2139  * care about the result of the method invocation.
2140  * @user_data: The data to pass to @callback.
2141  *
2142  * Asynchronously invokes the @method_name method on @proxy.
2143  *
2144  * If @method_name contains any dots, then @name is split into interface and
2145  * method name parts. This allows using @proxy for invoking methods on
2146  * other interfaces.
2147  *
2148  * If the #GDBusConnection associated with @proxy is closed then
2149  * the operation will fail with %G_IO_ERROR_CLOSED. If
2150  * @cancellable is canceled, the operation will fail with
2151  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
2152  * compatible with the D-Bus protocol, the operation fails with
2153  * %G_IO_ERROR_INVALID_ARGUMENT.
2154  *
2155  * If the @parameters #GVariant is floating, it is consumed. This allows
2156  * convenient 'inline' use of g_variant_new(), e.g.:
2157  * |[
2158  *  g_dbus_proxy_call (proxy,
2159  *                     "TwoStrings",
2160  *                     g_variant_new ("(ss)",
2161  *                                    "Thing One",
2162  *                                    "Thing Two"),
2163  *                     G_DBUS_CALL_FLAGS_NONE,
2164  *                     -1,
2165  *                     NULL,
2166  *                     (GAsyncReadyCallback) two_strings_done,
2167  *                     &amp;data);
2168  * ]|
2169  *
2170  * This is an asynchronous method. When the operation is finished,
2171  * @callback will be invoked in the
2172  * <link linkend="g-main-context-push-thread-default">thread-default
2173  * main loop</link> of the thread you are calling this method from.
2174  * You can then call g_dbus_proxy_call_finish() to get the result of
2175  * the operation. See g_dbus_proxy_call_sync() for the synchronous
2176  * version of this method.
2177  *
2178  * Since: 2.26
2179  */
2180 void
2181 g_dbus_proxy_call (GDBusProxy          *proxy,
2182                    const gchar         *method_name,
2183                    GVariant            *parameters,
2184                    GDBusCallFlags       flags,
2185                    gint                 timeout_msec,
2186                    GCancellable        *cancellable,
2187                    GAsyncReadyCallback  callback,
2188                    gpointer             user_data)
2189 {
2190   GSimpleAsyncResult *simple;
2191   gboolean was_split;
2192   gchar *split_interface_name;
2193   const gchar *split_method_name;
2194   const GDBusMethodInfo *expected_method_info;
2195   const gchar *target_method_name;
2196   const gchar *target_interface_name;
2197   GVariantType *reply_type;
2198
2199   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
2200   g_return_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name));
2201   g_return_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
2202   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
2203
2204   simple = g_simple_async_result_new (G_OBJECT (proxy),
2205                                       callback,
2206                                       user_data,
2207                                       g_dbus_proxy_call);
2208
2209   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
2210   target_method_name = was_split ? split_method_name : method_name;
2211   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
2212
2213   g_object_set_data_full (G_OBJECT (simple), "-gdbus-proxy-method-name", g_strdup (target_method_name), g_free);
2214
2215   /* Just warn here */
2216   expected_method_info = lookup_method_info_or_warn (proxy, target_method_name);
2217
2218   if (expected_method_info)
2219     reply_type = _g_dbus_compute_complete_signature (expected_method_info->out_args);
2220   else
2221     reply_type = NULL;
2222
2223   g_dbus_connection_call (proxy->priv->connection,
2224                           proxy->priv->name_owner,
2225                           proxy->priv->object_path,
2226                           target_interface_name,
2227                           target_method_name,
2228                           parameters,
2229                           reply_type,
2230                           flags,
2231                           timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2232                           cancellable,
2233                           (GAsyncReadyCallback) reply_cb,
2234                           simple);
2235
2236   if (reply_type != NULL)
2237     g_variant_type_free (reply_type);
2238
2239   g_free (split_interface_name);
2240 }
2241
2242 /**
2243  * g_dbus_proxy_call_finish:
2244  * @proxy: A #GDBusProxy.
2245  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call().
2246  * @error: Return location for error or %NULL.
2247  *
2248  * Finishes an operation started with g_dbus_proxy_call().
2249  *
2250  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
2251  * return values. Free with g_variant_unref().
2252  *
2253  * Since: 2.26
2254  */
2255 GVariant *
2256 g_dbus_proxy_call_finish (GDBusProxy    *proxy,
2257                           GAsyncResult  *res,
2258                           GError       **error)
2259 {
2260   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
2261   GVariant *value;
2262   const char *method_name;
2263
2264   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2265   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2266   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2267
2268   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_proxy_call);
2269
2270   value = NULL;
2271
2272   if (g_simple_async_result_propagate_error (simple, error))
2273     goto out;
2274
2275   value = g_simple_async_result_get_op_res_gpointer (simple);
2276   method_name = g_object_get_data (G_OBJECT (simple), "-gdbus-proxy-method-name");
2277
2278  out:
2279   return value;
2280 }
2281
2282 /**
2283  * g_dbus_proxy_call_sync:
2284  * @proxy: A #GDBusProxy.
2285  * @method_name: Name of method to invoke.
2286  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
2287  * @flags: Flags from the #GDBusCallFlags enumeration.
2288  * @timeout_msec: The timeout in milliseconds or -1 to use the proxy default timeout.
2289  * @cancellable: A #GCancellable or %NULL.
2290  * @error: Return location for error or %NULL.
2291  *
2292  * Synchronously invokes the @method_name method on @proxy.
2293  *
2294  * If @method_name contains any dots, then @name is split into interface and
2295  * method name parts. This allows using @proxy for invoking methods on
2296  * other interfaces.
2297  *
2298  * If the #GDBusConnection associated with @proxy is disconnected then
2299  * the operation will fail with %G_IO_ERROR_CLOSED. If
2300  * @cancellable is canceled, the operation will fail with
2301  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
2302  * compatible with the D-Bus protocol, the operation fails with
2303  * %G_IO_ERROR_INVALID_ARGUMENT.
2304  *
2305  * If the @parameters #GVariant is floating, it is consumed. This allows
2306  * convenient 'inline' use of g_variant_new(), e.g.:
2307  * |[
2308  *  g_dbus_proxy_call_sync (proxy,
2309  *                          "TwoStrings",
2310  *                          g_variant_new ("(ss)",
2311  *                                         "Thing One",
2312  *                                         "Thing Two"),
2313  *                          G_DBUS_CALL_FLAGS_NONE,
2314  *                          -1,
2315  *                          NULL,
2316  *                          &amp;error);
2317  * ]|
2318  *
2319  * The calling thread is blocked until a reply is received. See
2320  * g_dbus_proxy_call() for the asynchronous version of this
2321  * method.
2322  *
2323  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
2324  * return values. Free with g_variant_unref().
2325  *
2326  * Since: 2.26
2327  */
2328 GVariant *
2329 g_dbus_proxy_call_sync (GDBusProxy      *proxy,
2330                         const gchar     *method_name,
2331                         GVariant        *parameters,
2332                         GDBusCallFlags   flags,
2333                         gint             timeout_msec,
2334                         GCancellable    *cancellable,
2335                         GError         **error)
2336 {
2337   GVariant *ret;
2338   gboolean was_split;
2339   gchar *split_interface_name;
2340   const gchar *split_method_name;
2341   const GDBusMethodInfo *expected_method_info;
2342   const gchar *target_method_name;
2343   const gchar *target_interface_name;
2344   GVariantType *reply_type;
2345
2346   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2347   g_return_val_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name), NULL);
2348   g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
2349   g_return_val_if_fail (timeout_msec == -1 || timeout_msec >= 0, NULL);
2350   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2351
2352   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
2353   target_method_name = was_split ? split_method_name : method_name;
2354   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
2355
2356   if (proxy->priv->expected_interface)
2357     {
2358       expected_method_info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, target_method_name);
2359       if (expected_method_info == NULL)
2360         {
2361           g_warning ("Trying to invoke method `%s' which isn't in expected interface `%s'",
2362                      target_method_name,
2363                      target_interface_name);
2364         }
2365     }
2366   else
2367     {
2368       expected_method_info = NULL;
2369     }
2370
2371   if (expected_method_info)
2372     reply_type = _g_dbus_compute_complete_signature (expected_method_info->out_args);
2373   else
2374     reply_type = NULL;
2375
2376   ret = g_dbus_connection_call_sync (proxy->priv->connection,
2377                                      proxy->priv->name_owner,
2378                                      proxy->priv->object_path,
2379                                      target_interface_name,
2380                                      target_method_name,
2381                                      parameters,
2382                                      reply_type,
2383                                      flags,
2384                                      timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2385                                      cancellable,
2386                                      error);
2387
2388   if (reply_type != NULL)
2389     g_variant_type_free (reply_type);
2390
2391   g_free (split_interface_name);
2392
2393   return ret;
2394 }
2395
2396 /* ---------------------------------------------------------------------------------------------------- */
2397
2398 #define __G_DBUS_PROXY_C__
2399 #include "gioaliasdef.c"