1629c137fbfabd46313999aa474f7be102593856
[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__VARIANT_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_VARIANT,
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   error = NULL;
1396   data->proxy->priv->connection = g_bus_get_finish (res, &error);
1397   if (data->proxy->priv->connection == NULL)
1398     {
1399       GSimpleAsyncResult *simple;
1400       simple = g_simple_async_result_new (G_OBJECT (data->proxy),
1401                                           data->callback,
1402                                           data->user_data,
1403                                           NULL);
1404       g_simple_async_result_set_from_error (simple, error);
1405       g_error_free (error);
1406       g_simple_async_result_complete_in_idle (simple);
1407       g_object_unref (simple);
1408     }
1409   else
1410     {
1411       async_initable_init_first (G_ASYNC_INITABLE (data->proxy));
1412       async_initable_init_second_async (G_ASYNC_INITABLE (data->proxy),
1413                                         data->io_priority,
1414                                         data->cancellable,
1415                                         data->callback,
1416                                         data->user_data);
1417     }
1418
1419   if (data->cancellable != NULL)
1420     g_object_unref (data->cancellable);
1421   if (data->proxy != NULL)
1422     g_object_unref (data->proxy);
1423   g_free (data);
1424 }
1425
1426 static void
1427 async_initable_init_async (GAsyncInitable      *initable,
1428                            gint                 io_priority,
1429                            GCancellable        *cancellable,
1430                            GAsyncReadyCallback  callback,
1431                            gpointer             user_data)
1432 {
1433   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1434
1435   if (proxy->priv->bus_type != G_BUS_TYPE_NONE)
1436     {
1437       GetConnectionData *data;
1438
1439       g_assert (proxy->priv->connection == NULL);
1440
1441       data = g_new0 (GetConnectionData, 1);
1442       data->proxy = g_object_ref (proxy);
1443       data->io_priority = io_priority;
1444       data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
1445       data->callback = callback;
1446       data->user_data = user_data;
1447       g_bus_get (proxy->priv->bus_type,
1448                  cancellable,
1449                  get_connection_cb,
1450                  data);
1451     }
1452   else
1453     {
1454       async_initable_init_first (initable);
1455       async_initable_init_second_async (initable, io_priority, cancellable, callback, user_data);
1456     }
1457 }
1458
1459 static gboolean
1460 async_initable_init_finish (GAsyncInitable  *initable,
1461                             GAsyncResult    *res,
1462                             GError         **error)
1463 {
1464   return async_initable_init_second_finish (initable, res, error);
1465 }
1466
1467 static void
1468 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
1469 {
1470   async_initable_iface->init_async = async_initable_init_async;
1471   async_initable_iface->init_finish = async_initable_init_finish;
1472 }
1473
1474 /* ---------------------------------------------------------------------------------------------------- */
1475
1476 typedef struct
1477 {
1478   GMainContext *context;
1479   GMainLoop *loop;
1480   GAsyncResult *res;
1481 } InitableAsyncInitableData;
1482
1483 static void
1484 async_initable_init_async_cb (GObject      *source_object,
1485                               GAsyncResult *res,
1486                               gpointer      user_data)
1487 {
1488   InitableAsyncInitableData *data = user_data;
1489   data->res = g_object_ref (res);
1490   g_main_loop_quit (data->loop);
1491 }
1492
1493 /* Simply reuse the GAsyncInitable implementation but run the first
1494  * part (that is non-blocking and requires the callers GMainContext)
1495  * with the callers GMainContext.. and the second with a private
1496  * GMainContext (bug 621310 is slightly related).
1497  *
1498  * Note that obtaining a GDBusConnection is not shared between the two
1499  * paths.
1500  */
1501 static gboolean
1502 initable_init (GInitable     *initable,
1503                GCancellable  *cancellable,
1504                GError       **error)
1505 {
1506   GDBusProxy *proxy = G_DBUS_PROXY (initable);
1507   InitableAsyncInitableData *data;
1508   gboolean ret;
1509
1510   ret = FALSE;
1511
1512   if (proxy->priv->bus_type != G_BUS_TYPE_NONE)
1513     {
1514       g_assert (proxy->priv->connection == NULL);
1515       proxy->priv->connection = g_bus_get_sync (proxy->priv->bus_type,
1516                                                 cancellable,
1517                                                 error);
1518       if (proxy->priv->connection == NULL)
1519         goto out;
1520     }
1521
1522   async_initable_init_first (G_ASYNC_INITABLE (initable));
1523
1524   data = g_new0 (InitableAsyncInitableData, 1);
1525   data->context = g_main_context_new ();
1526   data->loop = g_main_loop_new (data->context, FALSE);
1527
1528   g_main_context_push_thread_default (data->context);
1529
1530   async_initable_init_second_async (G_ASYNC_INITABLE (initable),
1531                                     G_PRIORITY_DEFAULT,
1532                                     cancellable,
1533                                     async_initable_init_async_cb,
1534                                     data);
1535
1536   g_main_loop_run (data->loop);
1537
1538   ret = async_initable_init_second_finish (G_ASYNC_INITABLE (initable),
1539                                            data->res,
1540                                            error);
1541
1542   g_main_context_pop_thread_default (data->context);
1543
1544   g_main_context_unref (data->context);
1545   g_main_loop_unref (data->loop);
1546   g_object_unref (data->res);
1547   g_free (data);
1548
1549  out:
1550
1551   return ret;
1552 }
1553
1554 static void
1555 initable_iface_init (GInitableIface *initable_iface)
1556 {
1557   initable_iface->init = initable_init;
1558 }
1559
1560 /* ---------------------------------------------------------------------------------------------------- */
1561
1562 /**
1563  * g_dbus_proxy_new:
1564  * @connection: A #GDBusConnection.
1565  * @flags: Flags used when constructing the proxy.
1566  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1567  * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
1568  * @object_path: An object path.
1569  * @interface_name: A D-Bus interface name.
1570  * @cancellable: A #GCancellable or %NULL.
1571  * @callback: Callback function to invoke when the proxy is ready.
1572  * @user_data: User data to pass to @callback.
1573  *
1574  * Creates a proxy for accessing @interface_name on the remote object
1575  * at @object_path owned by @name at @connection and asynchronously
1576  * loads D-Bus properties unless the
1577  * #G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used. Connect to
1578  * the #GDBusProxy::g-properties-changed signal to get notified about
1579  * property changes.
1580  *
1581  * If the #G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
1582  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
1583  * to handle signals from the remote object.
1584  *
1585  * If @name is a well-known name and the
1586  * #G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag isn't set and no name
1587  * owner currently exists, the message bus will be requested to launch
1588  * a name owner for the name.
1589  *
1590  * This is a failable asynchronous constructor - when the proxy is
1591  * ready, @callback will be invoked and you can use
1592  * g_dbus_proxy_new_finish() to get the result.
1593  *
1594  * See g_dbus_proxy_new_sync() and for a synchronous version of this constructor.
1595  *
1596  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1597  *
1598  * Since: 2.26
1599  */
1600 void
1601 g_dbus_proxy_new (GDBusConnection     *connection,
1602                   GDBusProxyFlags      flags,
1603                   GDBusInterfaceInfo  *info,
1604                   const gchar         *name,
1605                   const gchar         *object_path,
1606                   const gchar         *interface_name,
1607                   GCancellable        *cancellable,
1608                   GAsyncReadyCallback  callback,
1609                   gpointer             user_data)
1610 {
1611   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1612   g_return_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) || g_dbus_is_name (name));
1613   g_return_if_fail (g_variant_is_object_path (object_path));
1614   g_return_if_fail (g_dbus_is_interface_name (interface_name));
1615
1616   g_async_initable_new_async (G_TYPE_DBUS_PROXY,
1617                               G_PRIORITY_DEFAULT,
1618                               cancellable,
1619                               callback,
1620                               user_data,
1621                               "g-flags", flags,
1622                               "g-interface-info", info,
1623                               "g-name", name,
1624                               "g-connection", connection,
1625                               "g-object-path", object_path,
1626                               "g-interface-name", interface_name,
1627                               NULL);
1628 }
1629
1630 /**
1631  * g_dbus_proxy_new_finish:
1632  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new().
1633  * @error: Return location for error or %NULL.
1634  *
1635  * Finishes creating a #GDBusProxy.
1636  *
1637  * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
1638  *
1639  * Since: 2.26
1640  */
1641 GDBusProxy *
1642 g_dbus_proxy_new_finish (GAsyncResult  *res,
1643                          GError       **error)
1644 {
1645   GObject *object;
1646   GObject *source_object;
1647
1648   source_object = g_async_result_get_source_object (res);
1649   g_assert (source_object != NULL);
1650
1651   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
1652                                         res,
1653                                         error);
1654   g_object_unref (source_object);
1655
1656   if (object != NULL)
1657     return G_DBUS_PROXY (object);
1658   else
1659     return NULL;
1660 }
1661
1662 /**
1663  * g_dbus_proxy_new_sync:
1664  * @connection: A #GDBusConnection.
1665  * @flags: Flags used when constructing the proxy.
1666  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1667  * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
1668  * @object_path: An object path.
1669  * @interface_name: A D-Bus interface name.
1670  * @cancellable: A #GCancellable or %NULL.
1671  * @error: Return location for error or %NULL.
1672  *
1673  * Creates a proxy for accessing @interface_name on the remote object
1674  * at @object_path owned by @name at @connection and synchronously
1675  * loads D-Bus properties unless the
1676  * #G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used.
1677  *
1678  * If the #G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
1679  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
1680  * to handle signals from the remote object.
1681  *
1682  * If @name is a well-known name and the
1683  * #G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag isn't set and no name
1684  * owner currently exists, the message bus will be requested to launch
1685  * a name owner for the name.
1686  *
1687  * This is a synchronous failable constructor. See g_dbus_proxy_new()
1688  * and g_dbus_proxy_new_finish() for the asynchronous version.
1689  *
1690  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1691  *
1692  * Returns: A #GDBusProxy or %NULL if error is set. Free with g_object_unref().
1693  *
1694  * Since: 2.26
1695  */
1696 GDBusProxy *
1697 g_dbus_proxy_new_sync (GDBusConnection     *connection,
1698                        GDBusProxyFlags      flags,
1699                        GDBusInterfaceInfo  *info,
1700                        const gchar         *name,
1701                        const gchar         *object_path,
1702                        const gchar         *interface_name,
1703                        GCancellable        *cancellable,
1704                        GError             **error)
1705 {
1706   GInitable *initable;
1707
1708   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1709   g_return_val_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
1710                         g_dbus_is_name (name), NULL);
1711   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
1712   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
1713
1714   initable = g_initable_new (G_TYPE_DBUS_PROXY,
1715                              cancellable,
1716                              error,
1717                              "g-flags", flags,
1718                              "g-interface-info", info,
1719                              "g-name", name,
1720                              "g-connection", connection,
1721                              "g-object-path", object_path,
1722                              "g-interface-name", interface_name,
1723                              NULL);
1724   if (initable != NULL)
1725     return G_DBUS_PROXY (initable);
1726   else
1727     return NULL;
1728 }
1729
1730 /* ---------------------------------------------------------------------------------------------------- */
1731
1732 /**
1733  * g_dbus_proxy_new_for_bus:
1734  * @bus_type: A #GBusType.
1735  * @flags: Flags used when constructing the proxy.
1736  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1737  * @name: A bus name (well-known or unique).
1738  * @object_path: An object path.
1739  * @interface_name: A D-Bus interface name.
1740  * @cancellable: A #GCancellable or %NULL.
1741  * @callback: Callback function to invoke when the proxy is ready.
1742  * @user_data: User data to pass to @callback.
1743  *
1744  * Like g_dbus_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
1745  *
1746  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1747  *
1748  * Since: 2.26
1749  */
1750 void
1751 g_dbus_proxy_new_for_bus (GBusType             bus_type,
1752                           GDBusProxyFlags      flags,
1753                           GDBusInterfaceInfo  *info,
1754                           const gchar         *name,
1755                           const gchar         *object_path,
1756                           const gchar         *interface_name,
1757                           GCancellable        *cancellable,
1758                           GAsyncReadyCallback  callback,
1759                           gpointer             user_data)
1760 {
1761   g_return_if_fail (g_dbus_is_name (name));
1762   g_return_if_fail (g_variant_is_object_path (object_path));
1763   g_return_if_fail (g_dbus_is_interface_name (interface_name));
1764
1765   g_async_initable_new_async (G_TYPE_DBUS_PROXY,
1766                               G_PRIORITY_DEFAULT,
1767                               cancellable,
1768                               callback,
1769                               user_data,
1770                               "g-flags", flags,
1771                               "g-interface-info", info,
1772                               "g-name", name,
1773                               "g-bus-type", bus_type,
1774                               "g-object-path", object_path,
1775                               "g-interface-name", interface_name,
1776                               NULL);
1777 }
1778
1779 /**
1780  * g_dbus_proxy_new_for_bus_finish:
1781  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new_for_bus().
1782  * @error: Return location for error or %NULL.
1783  *
1784  * Finishes creating a #GDBusProxy.
1785  *
1786  * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
1787  *
1788  * Since: 2.26
1789  */
1790 GDBusProxy *
1791 g_dbus_proxy_new_for_bus_finish (GAsyncResult  *res,
1792                                  GError       **error)
1793 {
1794   return g_dbus_proxy_new_finish (res, error);
1795 }
1796
1797 /**
1798  * g_dbus_proxy_new_for_bus_sync:
1799  * @bus_type: A #GBusType.
1800  * @flags: Flags used when constructing the proxy.
1801  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1802  * @name: A bus name (well-known or unique).
1803  * @object_path: An object path.
1804  * @interface_name: A D-Bus interface name.
1805  * @cancellable: A #GCancellable or %NULL.
1806  * @error: Return location for error or %NULL.
1807  *
1808  * Like g_dbus_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
1809  *
1810  * See <xref linkend="gdbus-wellknown-proxy"/> for an example of how #GDBusProxy can be used.
1811  *
1812  * Returns: A #GDBusProxy or %NULL if error is set. Free with g_object_unref().
1813  *
1814  * Since: 2.26
1815  */
1816 GDBusProxy *
1817 g_dbus_proxy_new_for_bus_sync (GBusType             bus_type,
1818                                GDBusProxyFlags      flags,
1819                                GDBusInterfaceInfo  *info,
1820                                const gchar         *name,
1821                                const gchar         *object_path,
1822                                const gchar         *interface_name,
1823                                GCancellable        *cancellable,
1824                                GError             **error)
1825 {
1826   GInitable *initable;
1827
1828   g_return_val_if_fail (g_dbus_is_name (name), NULL);
1829   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
1830   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
1831
1832   initable = g_initable_new (G_TYPE_DBUS_PROXY,
1833                              cancellable,
1834                              error,
1835                              "g-flags", flags,
1836                              "g-interface-info", info,
1837                              "g-name", name,
1838                              "g-bus-type", bus_type,
1839                              "g-object-path", object_path,
1840                              "g-interface-name", interface_name,
1841                              NULL);
1842   if (initable != NULL)
1843     return G_DBUS_PROXY (initable);
1844   else
1845     return NULL;
1846 }
1847
1848 /* ---------------------------------------------------------------------------------------------------- */
1849
1850 /**
1851  * g_dbus_proxy_get_connection:
1852  * @proxy: A #GDBusProxy.
1853  *
1854  * Gets the connection @proxy is for.
1855  *
1856  * Returns: A #GDBusConnection owned by @proxy. Do not free.
1857  *
1858  * Since: 2.26
1859  */
1860 GDBusConnection *
1861 g_dbus_proxy_get_connection (GDBusProxy *proxy)
1862 {
1863   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1864   return proxy->priv->connection;
1865 }
1866
1867 /**
1868  * g_dbus_proxy_get_flags:
1869  * @proxy: A #GDBusProxy.
1870  *
1871  * Gets the flags that @proxy was constructed with.
1872  *
1873  * Returns: Flags from the #GDBusProxyFlags enumeration.
1874  *
1875  * Since: 2.26
1876  */
1877 GDBusProxyFlags
1878 g_dbus_proxy_get_flags (GDBusProxy *proxy)
1879 {
1880   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
1881   return proxy->priv->flags;
1882 }
1883
1884 /**
1885  * g_dbus_proxy_get_name:
1886  * @proxy: A #GDBusProxy.
1887  *
1888  * Gets the name that @proxy was constructed for.
1889  *
1890  * Returns: A string owned by @proxy. Do not free.
1891  *
1892  * Since: 2.26
1893  */
1894 const gchar *
1895 g_dbus_proxy_get_name (GDBusProxy *proxy)
1896 {
1897   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1898   return proxy->priv->name;
1899 }
1900
1901 /**
1902  * g_dbus_proxy_get_name_owner:
1903  * @proxy: A #GDBusProxy.
1904  *
1905  * The unique name that owns the name that @proxy is for or %NULL if
1906  * no-one currently owns that name. You may connect to the
1907  * #GObject::notify signal to track changes to the
1908  * #GDBusProxy:g-name-owner property.
1909  *
1910  * Returns: The name owner or %NULL if no name owner exists. Free with g_free().
1911  *
1912  * Since: 2.26
1913  */
1914 gchar *
1915 g_dbus_proxy_get_name_owner (GDBusProxy *proxy)
1916 {
1917   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1918   return g_strdup (proxy->priv->name_owner);
1919 }
1920
1921 /**
1922  * g_dbus_proxy_get_object_path:
1923  * @proxy: A #GDBusProxy.
1924  *
1925  * Gets the object path @proxy is for.
1926  *
1927  * Returns: A string owned by @proxy. Do not free.
1928  *
1929  * Since: 2.26
1930  */
1931 const gchar *
1932 g_dbus_proxy_get_object_path (GDBusProxy *proxy)
1933 {
1934   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1935   return proxy->priv->object_path;
1936 }
1937
1938 /**
1939  * g_dbus_proxy_get_interface_name:
1940  * @proxy: A #GDBusProxy.
1941  *
1942  * Gets the D-Bus interface name @proxy is for.
1943  *
1944  * Returns: A string owned by @proxy. Do not free.
1945  *
1946  * Since: 2.26
1947  */
1948 const gchar *
1949 g_dbus_proxy_get_interface_name (GDBusProxy *proxy)
1950 {
1951   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1952   return proxy->priv->interface_name;
1953 }
1954
1955 /**
1956  * g_dbus_proxy_get_default_timeout:
1957  * @proxy: A #GDBusProxy.
1958  *
1959  * Gets the timeout to use if -1 (specifying default timeout) is
1960  * passed as @timeout_msec in the g_dbus_proxy_call() and
1961  * g_dbus_proxy_call_sync() functions.
1962  *
1963  * See the #GDBusProxy:g-default-timeout property for more details.
1964  *
1965  * Returns: Timeout to use for @proxy.
1966  *
1967  * Since: 2.26
1968  */
1969 gint
1970 g_dbus_proxy_get_default_timeout (GDBusProxy *proxy)
1971 {
1972   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), -1);
1973   return proxy->priv->timeout_msec;
1974 }
1975
1976 /**
1977  * g_dbus_proxy_set_default_timeout:
1978  * @proxy: A #GDBusProxy.
1979  * @timeout_msec: Timeout in milliseconds.
1980  *
1981  * Sets the timeout to use if -1 (specifying default timeout) is
1982  * passed as @timeout_msec in the g_dbus_proxy_call() and
1983  * g_dbus_proxy_call_sync() functions.
1984  *
1985  * See the #GDBusProxy:g-default-timeout property for more details.
1986  *
1987  * Since: 2.26
1988  */
1989 void
1990 g_dbus_proxy_set_default_timeout (GDBusProxy *proxy,
1991                                   gint        timeout_msec)
1992 {
1993   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
1994   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
1995
1996   /* TODO: locking? */
1997   if (proxy->priv->timeout_msec != timeout_msec)
1998     {
1999       proxy->priv->timeout_msec = timeout_msec;
2000       g_object_notify (G_OBJECT (proxy), "g-default-timeout");
2001     }
2002 }
2003
2004 /**
2005  * g_dbus_proxy_get_interface_info:
2006  * @proxy: A #GDBusProxy
2007  *
2008  * Returns the #GDBusInterfaceInfo, if any, specifying the minimal
2009  * interface that @proxy conforms to.
2010  *
2011  * See the #GDBusProxy:g-interface-info property for more details.
2012  *
2013  * Returns: A #GDBusInterfaceInfo or %NULL. Do not unref the returned
2014  * object, it is owned by @proxy.
2015  *
2016  * Since: 2.26
2017  */
2018 GDBusInterfaceInfo *
2019 g_dbus_proxy_get_interface_info (GDBusProxy *proxy)
2020 {
2021   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2022   return proxy->priv->expected_interface;
2023 }
2024
2025 /**
2026  * g_dbus_proxy_set_interface_info:
2027  * @proxy: A #GDBusProxy
2028  * @info: Minimum interface this proxy conforms to or %NULL to unset.
2029  *
2030  * Ensure that interactions with @proxy conform to the given
2031  * interface.  For example, when completing a method call, if the type
2032  * signature of the message isn't what's expected, the given #GError
2033  * is set.  Signals that have a type signature mismatch are simply
2034  * dropped.
2035  *
2036  * See the #GDBusProxy:g-interface-info property for more details.
2037  *
2038  * Since: 2.26
2039  */
2040 void
2041 g_dbus_proxy_set_interface_info (GDBusProxy         *proxy,
2042                                  GDBusInterfaceInfo *info)
2043 {
2044   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
2045   if (proxy->priv->expected_interface != NULL)
2046     g_dbus_interface_info_unref (proxy->priv->expected_interface);
2047   proxy->priv->expected_interface = info != NULL ? g_dbus_interface_info_ref (info) : NULL;
2048 }
2049
2050 /* ---------------------------------------------------------------------------------------------------- */
2051
2052 static gboolean
2053 maybe_split_method_name (const gchar  *method_name,
2054                          gchar       **out_interface_name,
2055                          const gchar **out_method_name)
2056 {
2057   gboolean was_split;
2058
2059   was_split = FALSE;
2060   g_assert (out_interface_name != NULL);
2061   g_assert (out_method_name != NULL);
2062   *out_interface_name = NULL;
2063   *out_method_name = NULL;
2064
2065   if (strchr (method_name, '.') != NULL)
2066     {
2067       gchar *p;
2068       gchar *last_dot;
2069
2070       p = g_strdup (method_name);
2071       last_dot = strrchr (p, '.');
2072       *last_dot = '\0';
2073
2074       *out_interface_name = p;
2075       *out_method_name = last_dot + 1;
2076
2077       was_split = TRUE;
2078     }
2079
2080   return was_split;
2081 }
2082
2083
2084 static void
2085 reply_cb (GDBusConnection *connection,
2086           GAsyncResult    *res,
2087           gpointer         user_data)
2088 {
2089   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
2090   GVariant *value;
2091   GError *error;
2092
2093   error = NULL;
2094   value = g_dbus_connection_call_finish (connection,
2095                                          res,
2096                                          &error);
2097   if (error != NULL)
2098     {
2099       g_simple_async_result_set_from_error (simple,
2100                                             error);
2101       g_error_free (error);
2102     }
2103   else
2104     {
2105       g_simple_async_result_set_op_res_gpointer (simple,
2106                                                  value,
2107                                                  (GDestroyNotify) g_variant_unref);
2108     }
2109
2110   /* no need to complete in idle since the method GDBusConnection already does */
2111   g_simple_async_result_complete (simple);
2112 }
2113
2114 static const GDBusMethodInfo *
2115 lookup_method_info_or_warn (GDBusProxy  *proxy,
2116                             const gchar *method_name)
2117 {
2118   const GDBusMethodInfo *info;
2119
2120   if (proxy->priv->expected_interface == NULL)
2121     return NULL;
2122
2123   info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, method_name);
2124   if (info == NULL)
2125     {
2126       g_warning ("Trying to invoke method %s which isn't in expected interface %s",
2127                  method_name, proxy->priv->expected_interface->name);
2128     }
2129
2130   return info;
2131 }
2132
2133 /**
2134  * g_dbus_proxy_call:
2135  * @proxy: A #GDBusProxy.
2136  * @method_name: Name of method to invoke.
2137  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
2138  * @flags: Flags from the #GDBusCallFlags enumeration.
2139  * @timeout_msec: The timeout in milliseconds or -1 to use the proxy default timeout.
2140  * @cancellable: A #GCancellable or %NULL.
2141  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
2142  * care about the result of the method invocation.
2143  * @user_data: The data to pass to @callback.
2144  *
2145  * Asynchronously invokes the @method_name method on @proxy.
2146  *
2147  * If @method_name contains any dots, then @name is split into interface and
2148  * method name parts. This allows using @proxy for invoking methods on
2149  * other interfaces.
2150  *
2151  * If the #GDBusConnection associated with @proxy is closed then
2152  * the operation will fail with %G_IO_ERROR_CLOSED. If
2153  * @cancellable is canceled, the operation will fail with
2154  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
2155  * compatible with the D-Bus protocol, the operation fails with
2156  * %G_IO_ERROR_INVALID_ARGUMENT.
2157  *
2158  * If the @parameters #GVariant is floating, it is consumed. This allows
2159  * convenient 'inline' use of g_variant_new(), e.g.:
2160  * |[
2161  *  g_dbus_proxy_call (proxy,
2162  *                     "TwoStrings",
2163  *                     g_variant_new ("(ss)",
2164  *                                    "Thing One",
2165  *                                    "Thing Two"),
2166  *                     G_DBUS_CALL_FLAGS_NONE,
2167  *                     -1,
2168  *                     NULL,
2169  *                     (GAsyncReadyCallback) two_strings_done,
2170  *                     &amp;data);
2171  * ]|
2172  *
2173  * This is an asynchronous method. When the operation is finished,
2174  * @callback will be invoked in the
2175  * <link linkend="g-main-context-push-thread-default">thread-default
2176  * main loop</link> of the thread you are calling this method from.
2177  * You can then call g_dbus_proxy_call_finish() to get the result of
2178  * the operation. See g_dbus_proxy_call_sync() for the synchronous
2179  * version of this method.
2180  *
2181  * Since: 2.26
2182  */
2183 void
2184 g_dbus_proxy_call (GDBusProxy          *proxy,
2185                    const gchar         *method_name,
2186                    GVariant            *parameters,
2187                    GDBusCallFlags       flags,
2188                    gint                 timeout_msec,
2189                    GCancellable        *cancellable,
2190                    GAsyncReadyCallback  callback,
2191                    gpointer             user_data)
2192 {
2193   GSimpleAsyncResult *simple;
2194   gboolean was_split;
2195   gchar *split_interface_name;
2196   const gchar *split_method_name;
2197   const GDBusMethodInfo *expected_method_info;
2198   const gchar *target_method_name;
2199   const gchar *target_interface_name;
2200   GVariantType *reply_type;
2201
2202   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
2203   g_return_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name));
2204   g_return_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
2205   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
2206
2207   simple = g_simple_async_result_new (G_OBJECT (proxy),
2208                                       callback,
2209                                       user_data,
2210                                       g_dbus_proxy_call);
2211
2212   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
2213   target_method_name = was_split ? split_method_name : method_name;
2214   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
2215
2216   g_object_set_data_full (G_OBJECT (simple), "-gdbus-proxy-method-name", g_strdup (target_method_name), g_free);
2217
2218   /* Just warn here */
2219   expected_method_info = lookup_method_info_or_warn (proxy, target_method_name);
2220
2221   if (expected_method_info)
2222     reply_type = _g_dbus_compute_complete_signature (expected_method_info->out_args);
2223   else
2224     reply_type = NULL;
2225
2226   g_dbus_connection_call (proxy->priv->connection,
2227                           proxy->priv->name_owner,
2228                           proxy->priv->object_path,
2229                           target_interface_name,
2230                           target_method_name,
2231                           parameters,
2232                           reply_type,
2233                           flags,
2234                           timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2235                           cancellable,
2236                           (GAsyncReadyCallback) reply_cb,
2237                           simple);
2238
2239   if (reply_type != NULL)
2240     g_variant_type_free (reply_type);
2241
2242   g_free (split_interface_name);
2243 }
2244
2245 /**
2246  * g_dbus_proxy_call_finish:
2247  * @proxy: A #GDBusProxy.
2248  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call().
2249  * @error: Return location for error or %NULL.
2250  *
2251  * Finishes an operation started with g_dbus_proxy_call().
2252  *
2253  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
2254  * return values. Free with g_variant_unref().
2255  *
2256  * Since: 2.26
2257  */
2258 GVariant *
2259 g_dbus_proxy_call_finish (GDBusProxy    *proxy,
2260                           GAsyncResult  *res,
2261                           GError       **error)
2262 {
2263   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
2264   GVariant *value;
2265   const char *method_name;
2266
2267   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2268   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2269   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2270
2271   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_proxy_call);
2272
2273   value = NULL;
2274
2275   if (g_simple_async_result_propagate_error (simple, error))
2276     goto out;
2277
2278   value = g_simple_async_result_get_op_res_gpointer (simple);
2279   method_name = g_object_get_data (G_OBJECT (simple), "-gdbus-proxy-method-name");
2280
2281  out:
2282   return value;
2283 }
2284
2285 /**
2286  * g_dbus_proxy_call_sync:
2287  * @proxy: A #GDBusProxy.
2288  * @method_name: Name of method to invoke.
2289  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
2290  * @flags: Flags from the #GDBusCallFlags enumeration.
2291  * @timeout_msec: The timeout in milliseconds or -1 to use the proxy default timeout.
2292  * @cancellable: A #GCancellable or %NULL.
2293  * @error: Return location for error or %NULL.
2294  *
2295  * Synchronously invokes the @method_name method on @proxy.
2296  *
2297  * If @method_name contains any dots, then @name is split into interface and
2298  * method name parts. This allows using @proxy for invoking methods on
2299  * other interfaces.
2300  *
2301  * If the #GDBusConnection associated with @proxy is disconnected then
2302  * the operation will fail with %G_IO_ERROR_CLOSED. If
2303  * @cancellable is canceled, the operation will fail with
2304  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
2305  * compatible with the D-Bus protocol, the operation fails with
2306  * %G_IO_ERROR_INVALID_ARGUMENT.
2307  *
2308  * If the @parameters #GVariant is floating, it is consumed. This allows
2309  * convenient 'inline' use of g_variant_new(), e.g.:
2310  * |[
2311  *  g_dbus_proxy_call_sync (proxy,
2312  *                          "TwoStrings",
2313  *                          g_variant_new ("(ss)",
2314  *                                         "Thing One",
2315  *                                         "Thing Two"),
2316  *                          G_DBUS_CALL_FLAGS_NONE,
2317  *                          -1,
2318  *                          NULL,
2319  *                          &amp;error);
2320  * ]|
2321  *
2322  * The calling thread is blocked until a reply is received. See
2323  * g_dbus_proxy_call() for the asynchronous version of this
2324  * method.
2325  *
2326  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
2327  * return values. Free with g_variant_unref().
2328  *
2329  * Since: 2.26
2330  */
2331 GVariant *
2332 g_dbus_proxy_call_sync (GDBusProxy      *proxy,
2333                         const gchar     *method_name,
2334                         GVariant        *parameters,
2335                         GDBusCallFlags   flags,
2336                         gint             timeout_msec,
2337                         GCancellable    *cancellable,
2338                         GError         **error)
2339 {
2340   GVariant *ret;
2341   gboolean was_split;
2342   gchar *split_interface_name;
2343   const gchar *split_method_name;
2344   const GDBusMethodInfo *expected_method_info;
2345   const gchar *target_method_name;
2346   const gchar *target_interface_name;
2347   GVariantType *reply_type;
2348
2349   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
2350   g_return_val_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name), NULL);
2351   g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
2352   g_return_val_if_fail (timeout_msec == -1 || timeout_msec >= 0, NULL);
2353   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2354
2355   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
2356   target_method_name = was_split ? split_method_name : method_name;
2357   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
2358
2359   if (proxy->priv->expected_interface)
2360     {
2361       expected_method_info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, target_method_name);
2362       if (expected_method_info == NULL)
2363         {
2364           g_warning ("Trying to invoke method `%s' which isn't in expected interface `%s'",
2365                      target_method_name,
2366                      target_interface_name);
2367         }
2368     }
2369   else
2370     {
2371       expected_method_info = NULL;
2372     }
2373
2374   if (expected_method_info)
2375     reply_type = _g_dbus_compute_complete_signature (expected_method_info->out_args);
2376   else
2377     reply_type = NULL;
2378
2379   ret = g_dbus_connection_call_sync (proxy->priv->connection,
2380                                      proxy->priv->name_owner,
2381                                      proxy->priv->object_path,
2382                                      target_interface_name,
2383                                      target_method_name,
2384                                      parameters,
2385                                      reply_type,
2386                                      flags,
2387                                      timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
2388                                      cancellable,
2389                                      error);
2390
2391   if (reply_type != NULL)
2392     g_variant_type_free (reply_type);
2393
2394   g_free (split_interface_name);
2395
2396   return ret;
2397 }
2398
2399 /* ---------------------------------------------------------------------------------------------------- */
2400
2401 #define __G_DBUS_PROXY_C__
2402 #include "gioaliasdef.c"