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