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