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