mention inline use of floating variants
[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 <gobject/gvaluecollector.h>
29
30 #include "gdbusutils.h"
31 #include "gdbusproxy.h"
32 #include "gioenumtypes.h"
33 #include "gdbusconnection.h"
34 #include "gdbuserror.h"
35 #include "gdbusprivate.h"
36 #include "gio-marshal.h"
37 #include "ginitable.h"
38 #include "gasyncinitable.h"
39 #include "gioerror.h"
40 #include "gasyncresult.h"
41 #include "gsimpleasyncresult.h"
42
43 #include "glibintl.h"
44 #include "gioalias.h"
45
46 /**
47  * SECTION:gdbusproxy
48  * @short_description: Base class for proxies
49  * @include: gio/gio.h
50  *
51  * #GDBusProxy is a base class used for proxies to access a D-Bus
52  * interface on a remote object. A #GDBusProxy can only be constructed
53  * for unique name bus and does not track whether the name
54  * vanishes. Use g_bus_watch_proxy() to construct #GDBusProxy proxies
55  * for owners of a well-known names.
56  */
57
58 struct _GDBusProxyPrivate
59 {
60   GDBusConnection *connection;
61   GDBusProxyFlags flags;
62   gchar *unique_bus_name;
63   gchar *object_path;
64   gchar *interface_name;
65   gint timeout_msec;
66
67   /* gchar* -> GVariant* */
68   GHashTable *properties;
69
70   GDBusInterfaceInfo *expected_interface;
71
72   guint properties_changed_subscriber_id;
73   guint signals_subscriber_id;
74 };
75
76 enum
77 {
78   PROP_0,
79   PROP_G_CONNECTION,
80   PROP_G_UNIQUE_BUS_NAME,
81   PROP_G_FLAGS,
82   PROP_G_OBJECT_PATH,
83   PROP_G_INTERFACE_NAME,
84   PROP_G_DEFAULT_TIMEOUT,
85   PROP_G_INTERFACE_INFO
86 };
87
88 enum
89 {
90   PROPERTIES_CHANGED_SIGNAL,
91   SIGNAL_SIGNAL,
92   LAST_SIGNAL,
93 };
94
95 static void g_dbus_proxy_constructed (GObject *object);
96
97 guint signals[LAST_SIGNAL] = {0};
98
99 static void initable_iface_init       (GInitableIface *initable_iface);
100 static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
101
102 G_DEFINE_TYPE_WITH_CODE (GDBusProxy, g_dbus_proxy, G_TYPE_OBJECT,
103                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
104                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
105                          );
106
107 static void
108 g_dbus_proxy_finalize (GObject *object)
109 {
110   GDBusProxy *proxy = G_DBUS_PROXY (object);
111
112   if (proxy->priv->properties_changed_subscriber_id > 0)
113     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
114                                           proxy->priv->properties_changed_subscriber_id);
115
116   if (proxy->priv->signals_subscriber_id > 0)
117     g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
118                                           proxy->priv->signals_subscriber_id);
119
120   g_object_unref (proxy->priv->connection);
121   g_free (proxy->priv->unique_bus_name);
122   g_free (proxy->priv->object_path);
123   g_free (proxy->priv->interface_name);
124   if (proxy->priv->properties != NULL)
125     g_hash_table_unref (proxy->priv->properties);
126
127   if (proxy->priv->expected_interface != NULL)
128     g_dbus_interface_info_unref (proxy->priv->expected_interface);
129
130   G_OBJECT_CLASS (g_dbus_proxy_parent_class)->finalize (object);
131 }
132
133 static void
134 g_dbus_proxy_get_property (GObject    *object,
135                            guint       prop_id,
136                            GValue     *value,
137                            GParamSpec *pspec)
138 {
139   GDBusProxy *proxy = G_DBUS_PROXY (object);
140
141   switch (prop_id)
142     {
143     case PROP_G_CONNECTION:
144       g_value_set_object (value, proxy->priv->connection);
145       break;
146
147     case PROP_G_FLAGS:
148       g_value_set_flags (value, proxy->priv->flags);
149       break;
150
151     case PROP_G_UNIQUE_BUS_NAME:
152       g_value_set_string (value, proxy->priv->unique_bus_name);
153       break;
154
155     case PROP_G_OBJECT_PATH:
156       g_value_set_string (value, proxy->priv->object_path);
157       break;
158
159     case PROP_G_INTERFACE_NAME:
160       g_value_set_string (value, proxy->priv->interface_name);
161       break;
162
163     case PROP_G_DEFAULT_TIMEOUT:
164       g_value_set_int (value, proxy->priv->timeout_msec);
165       break;
166
167     case PROP_G_INTERFACE_INFO:
168       g_value_set_boxed (value, g_dbus_proxy_get_interface_info (proxy));
169       break;
170
171     default:
172       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
173       break;
174     }
175 }
176
177 static void
178 g_dbus_proxy_set_property (GObject      *object,
179                            guint         prop_id,
180                            const 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       proxy->priv->connection = g_value_dup_object (value);
189       break;
190
191     case PROP_G_FLAGS:
192       proxy->priv->flags = g_value_get_flags (value);
193       break;
194
195     case PROP_G_UNIQUE_BUS_NAME:
196       proxy->priv->unique_bus_name = g_value_dup_string (value);
197       break;
198
199     case PROP_G_OBJECT_PATH:
200       proxy->priv->object_path = g_value_dup_string (value);
201       break;
202
203     case PROP_G_INTERFACE_NAME:
204       proxy->priv->interface_name = g_value_dup_string (value);
205       break;
206
207     case PROP_G_DEFAULT_TIMEOUT:
208       g_dbus_proxy_set_default_timeout (proxy, g_value_get_int (value));
209       break;
210
211     case PROP_G_INTERFACE_INFO:
212       g_dbus_proxy_set_interface_info (proxy, g_value_get_boxed (value));
213       break;
214
215     default:
216       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
217       break;
218     }
219 }
220
221 static void
222 g_dbus_proxy_class_init (GDBusProxyClass *klass)
223 {
224   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
225
226   gobject_class->finalize     = g_dbus_proxy_finalize;
227   gobject_class->set_property = g_dbus_proxy_set_property;
228   gobject_class->get_property = g_dbus_proxy_get_property;
229   gobject_class->constructed  = g_dbus_proxy_constructed;
230
231   /* Note that all property names are prefixed to avoid collisions with D-Bus property names
232    * in derived classes */
233
234   /**
235    * GDBusProxy:g-interface-info:
236    *
237    * Ensure that interactions with this proxy conform to the given
238    * interface.  For example, when completing a method call, if the
239    * type signature of the message isn't what's expected, the given
240    * #GError is set.  Signals that have a type signature mismatch are
241    * simply dropped.
242    *
243    * Since: 2.26
244    */
245   g_object_class_install_property (gobject_class,
246                                    PROP_G_INTERFACE_INFO,
247                                    g_param_spec_boxed ("g-interface-info",
248                                                        P_("Interface Information"),
249                                                        P_("Interface Information"),
250                                                        G_TYPE_DBUS_INTERFACE_INFO,
251                                                        G_PARAM_READABLE |
252                                                        G_PARAM_WRITABLE |
253                                                        G_PARAM_STATIC_NAME |
254                                                        G_PARAM_STATIC_BLURB |
255                                                        G_PARAM_STATIC_NICK));
256
257   /**
258    * GDBusProxy:g-connection:
259    *
260    * The #GDBusConnection the proxy is for.
261    *
262    * Since: 2.26
263    */
264   g_object_class_install_property (gobject_class,
265                                    PROP_G_CONNECTION,
266                                    g_param_spec_object ("g-connection",
267                                                         P_("g-connection"),
268                                                         P_("The connection the proxy is for"),
269                                                         G_TYPE_DBUS_CONNECTION,
270                                                         G_PARAM_READABLE |
271                                                         G_PARAM_WRITABLE |
272                                                         G_PARAM_CONSTRUCT_ONLY |
273                                                         G_PARAM_STATIC_NAME |
274                                                         G_PARAM_STATIC_BLURB |
275                                                         G_PARAM_STATIC_NICK));
276
277   /**
278    * GDBusProxy:g-flags:
279    *
280    * Flags from the #GDBusProxyFlags enumeration.
281    *
282    * Since: 2.26
283    */
284   g_object_class_install_property (gobject_class,
285                                    PROP_G_FLAGS,
286                                    g_param_spec_flags ("g-flags",
287                                                        P_("g-flags"),
288                                                        P_("Flags for the proxy"),
289                                                        G_TYPE_DBUS_PROXY_FLAGS,
290                                                        G_DBUS_PROXY_FLAGS_NONE,
291                                                        G_PARAM_READABLE |
292                                                        G_PARAM_WRITABLE |
293                                                        G_PARAM_CONSTRUCT_ONLY |
294                                                        G_PARAM_STATIC_NAME |
295                                                        G_PARAM_STATIC_BLURB |
296                                                        G_PARAM_STATIC_NICK));
297
298   /**
299    * GDBusProxy:g-unique-bus-name:
300    *
301    * The unique bus name the proxy is for.
302    *
303    * Since: 2.26
304    */
305   g_object_class_install_property (gobject_class,
306                                    PROP_G_UNIQUE_BUS_NAME,
307                                    g_param_spec_string ("g-unique-bus-name",
308                                                         P_("g-unique-bus-name"),
309                                                         P_("The unique bus name the proxy is for"),
310                                                         NULL,
311                                                         G_PARAM_READABLE |
312                                                         G_PARAM_WRITABLE |
313                                                         G_PARAM_CONSTRUCT_ONLY |
314                                                         G_PARAM_STATIC_NAME |
315                                                         G_PARAM_STATIC_BLURB |
316                                                         G_PARAM_STATIC_NICK));
317
318   /**
319    * GDBusProxy:g-object-path:
320    *
321    * The object path the proxy is for.
322    *
323    * Since: 2.26
324    */
325   g_object_class_install_property (gobject_class,
326                                    PROP_G_OBJECT_PATH,
327                                    g_param_spec_string ("g-object-path",
328                                                         P_("g-object-path"),
329                                                         P_("The object path the proxy is for"),
330                                                         NULL,
331                                                         G_PARAM_READABLE |
332                                                         G_PARAM_WRITABLE |
333                                                         G_PARAM_CONSTRUCT_ONLY |
334                                                         G_PARAM_STATIC_NAME |
335                                                         G_PARAM_STATIC_BLURB |
336                                                         G_PARAM_STATIC_NICK));
337
338   /**
339    * GDBusProxy:g-interface-name:
340    *
341    * The D-Bus interface name the proxy is for.
342    *
343    * Since: 2.26
344    */
345   g_object_class_install_property (gobject_class,
346                                    PROP_G_INTERFACE_NAME,
347                                    g_param_spec_string ("g-interface-name",
348                                                         P_("g-interface-name"),
349                                                         P_("The D-Bus interface name the proxy is for"),
350                                                         NULL,
351                                                         G_PARAM_READABLE |
352                                                         G_PARAM_WRITABLE |
353                                                         G_PARAM_CONSTRUCT_ONLY |
354                                                         G_PARAM_STATIC_NAME |
355                                                         G_PARAM_STATIC_BLURB |
356                                                         G_PARAM_STATIC_NICK));
357
358   /**
359    * GDBusProxy:g-default-timeout:
360    *
361    * The timeout to use if -1 (specifying default timeout) is passed
362    * as @timeout_msec in the g_dbus_proxy_call() and
363    * g_dbus_proxy_call_sync() functions.
364    *
365    * This allows applications to set a proxy-wide timeout for all
366    * remote method invocations on the proxy. If this property is -1,
367    * the default timeout (typically 25 seconds) is used. If set to
368    * %G_MAXINT, then no timeout is used.
369    *
370    * Since: 2.26
371    */
372   g_object_class_install_property (gobject_class,
373                                    PROP_G_DEFAULT_TIMEOUT,
374                                    g_param_spec_int ("g-default-timeout",
375                                                      P_("Default Timeout"),
376                                                      P_("Timeout for remote method invocation"),
377                                                      -1,
378                                                      G_MAXINT,
379                                                      -1,
380                                                      G_PARAM_READABLE |
381                                                      G_PARAM_WRITABLE |
382                                                      G_PARAM_CONSTRUCT |
383                                                      G_PARAM_STATIC_NAME |
384                                                      G_PARAM_STATIC_BLURB |
385                                                      G_PARAM_STATIC_NICK));
386
387   /**
388    * GDBusProxy::g-properties-changed:
389    * @proxy: The #GDBusProxy emitting the signal.
390    * @changed_properties: A #GVariant containing the properties that changed.
391    *
392    * Emitted when one or more D-Bus properties on @proxy changes. The cached properties
393    * are already replaced when this signal fires.
394    *
395    * Since: 2.26
396    */
397   signals[PROPERTIES_CHANGED_SIGNAL] = g_signal_new ("g-properties-changed",
398                                                      G_TYPE_DBUS_PROXY,
399                                                      G_SIGNAL_RUN_LAST,
400                                                      G_STRUCT_OFFSET (GDBusProxyClass, g_properties_changed),
401                                                      NULL,
402                                                      NULL,
403                                                      g_cclosure_marshal_VOID__BOXED,
404                                                      G_TYPE_NONE,
405                                                      1,
406                                                      G_TYPE_VARIANT);
407
408   /**
409    * GDBusProxy::g-signal:
410    * @proxy: The #GDBusProxy emitting the signal.
411    * @sender_name: The sender of the signal or %NULL if the connection is not a bus connection.
412    * @signal_name: The name of the signal.
413    * @parameters: A #GVariant tuple with parameters for the signal.
414    *
415    * Emitted when a signal from the remote object and interface that @proxy is for, has been received.
416    *
417    * Since: 2.26
418    */
419   signals[SIGNAL_SIGNAL] = g_signal_new ("g-signal",
420                                          G_TYPE_DBUS_PROXY,
421                                          G_SIGNAL_RUN_LAST,
422                                          G_STRUCT_OFFSET (GDBusProxyClass, g_signal),
423                                          NULL,
424                                          NULL,
425                                          _gio_marshal_VOID__STRING_STRING_BOXED,
426                                          G_TYPE_NONE,
427                                          3,
428                                          G_TYPE_STRING,
429                                          G_TYPE_STRING,
430                                          G_TYPE_VARIANT);
431
432
433   g_type_class_add_private (klass, sizeof (GDBusProxyPrivate));
434 }
435
436 static void
437 g_dbus_proxy_init (GDBusProxy *proxy)
438 {
439   proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, G_TYPE_DBUS_PROXY, GDBusProxyPrivate);
440 }
441
442 /* ---------------------------------------------------------------------------------------------------- */
443
444 /**
445  * g_dbus_proxy_get_cached_property_names:
446  * @proxy: A #GDBusProxy.
447  * @error: Return location for error or %NULL.
448  *
449  * Gets the names of all cached properties on @proxy.
450  *
451  * Returns: A %NULL-terminated array of strings or %NULL if @error is set. Free with
452  * g_strfreev().
453  *
454  * Since: 2.26
455  */
456 gchar **
457 g_dbus_proxy_get_cached_property_names (GDBusProxy  *proxy,
458                                         GError     **error)
459 {
460   gchar **names;
461   GPtrArray *p;
462   GHashTableIter iter;
463   const gchar *key;
464
465   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
466   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
467
468   names = NULL;
469
470   if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
471     {
472       g_set_error (error,
473                    G_IO_ERROR,
474                    G_IO_ERROR_FAILED,
475                    _("Properties are not available (proxy created with G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)"));
476       goto out;
477     }
478
479   p = g_ptr_array_new ();
480
481   g_hash_table_iter_init (&iter, proxy->priv->properties);
482   while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL))
483     g_ptr_array_add (p, g_strdup (key));
484   g_ptr_array_sort (p, (GCompareFunc) g_strcmp0);
485   g_ptr_array_add (p, NULL);
486
487   names = (gchar **) g_ptr_array_free (p, FALSE);
488
489  out:
490   return names;
491 }
492
493 /**
494  * g_dbus_proxy_get_cached_property:
495  * @proxy: A #GDBusProxy.
496  * @property_name: Property name.
497  * @error: Return location for error or %NULL.
498  *
499  * Looks up the value for a property from the cache. This call does no blocking IO.
500  *
501  * Normally you will not need to modify the returned variant since it is updated automatically
502  * in response to <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
503  * D-Bus signals (which also causes #GDBusProxy::g-properties-changed to be emitted).
504  *
505  * However, for properties for which said D-Bus signal is not emitted, you
506  * can catch other signals and modify the returned variant accordingly (remember to emit
507  * #GDBusProxy::g-properties-changed yourself).
508  *
509  * Returns: A reference to the #GVariant instance that holds the value for @property_name or
510  * %NULL if @error is set. Free the reference with g_variant_unref().
511  *
512  * Since: 2.26
513  */
514 GVariant *
515 g_dbus_proxy_get_cached_property (GDBusProxy   *proxy,
516                                   const gchar  *property_name,
517                                   GError      **error)
518 {
519   GVariant *value;
520
521   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
522   g_return_val_if_fail (property_name != NULL, NULL);
523
524   value = NULL;
525
526   if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
527     {
528       g_set_error (error,
529                    G_IO_ERROR,
530                    G_IO_ERROR_FAILED,
531                    _("Properties are not available (proxy created with G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)"));
532       goto out;
533     }
534
535   value = g_hash_table_lookup (proxy->priv->properties, property_name);
536   if (value == NULL)
537     {
538       g_set_error (error,
539                    G_IO_ERROR,
540                    G_IO_ERROR_FAILED,
541                    _("No property with name %s"),
542                    property_name);
543       goto out;
544     }
545
546   g_variant_ref (value);
547
548  out:
549
550   return value;
551 }
552
553 /* ---------------------------------------------------------------------------------------------------- */
554
555 static void
556 on_signal_received (GDBusConnection *connection,
557                     const gchar     *sender_name,
558                     const gchar     *object_path,
559                     const gchar     *interface_name,
560                     const gchar     *signal_name,
561                     GVariant        *parameters,
562                     gpointer         user_data)
563 {
564   GDBusProxy *proxy = G_DBUS_PROXY (user_data);
565
566   g_signal_emit (proxy,
567                  signals[SIGNAL_SIGNAL],
568                  0,
569                  sender_name,
570                  signal_name,
571                  parameters);
572 }
573
574 /* ---------------------------------------------------------------------------------------------------- */
575
576 static void
577 on_properties_changed (GDBusConnection *connection,
578                        const gchar     *sender_name,
579                        const gchar     *object_path,
580                        const gchar     *interface_name,
581                        const gchar     *signal_name,
582                        GVariant        *parameters,
583                        gpointer         user_data)
584 {
585   GDBusProxy *proxy = G_DBUS_PROXY (user_data);
586   GError *error;
587   const gchar *interface_name_for_signal;
588   GVariantIter *iter;
589   GVariant *item;
590   GVariant *changed_properties;
591   GVariantBuilder *builder;
592
593   error = NULL;
594   iter = NULL;
595
596 #if 0 // TODO!
597   /* Ignore this signal if properties are not yet available
598    *
599    * (can happen in the window between subscribing to PropertiesChanged() and until
600    *  org.freedesktop.DBus.Properties.GetAll() returns)
601    */
602   if (!proxy->priv->properties_available)
603     goto out;
604 #endif
605
606   if (strcmp (g_variant_get_type_string (parameters), "(sa{sv})") != 0)
607     {
608       g_warning ("Value for PropertiesChanged signal with type `%s' does not match `(sa{sv})'",
609                  g_variant_get_type_string (parameters));
610       goto out;
611     }
612
613   g_variant_get (parameters,
614                  "(sa{sv})",
615                  &interface_name_for_signal,
616                  &iter);
617
618   if (g_strcmp0 (interface_name_for_signal, proxy->priv->interface_name) != 0)
619     goto out;
620
621   builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
622   while ((item = g_variant_iter_next_value (iter)))
623     {
624       const gchar *key;
625       GVariant *value;
626
627       g_variant_get (item,
628                      "{sv}",
629                      &key,
630                      &value);
631
632       g_hash_table_insert (proxy->priv->properties,
633                            g_strdup (key),
634                            value); /* steals value */
635
636       g_variant_builder_add (builder,
637                              "{sv}",
638                              g_strdup (key),
639                              g_variant_ref (value));
640     }
641   changed_properties = g_variant_builder_end (builder);
642
643   /* emit signal */
644   g_signal_emit (proxy, signals[PROPERTIES_CHANGED_SIGNAL], 0, changed_properties);
645
646   g_variant_unref (changed_properties);
647
648  out:
649   if (iter != NULL)
650     g_variant_iter_free (iter);
651 }
652
653 /* ---------------------------------------------------------------------------------------------------- */
654
655 static void
656 g_dbus_proxy_constructed (GObject *object)
657 {
658   if (G_OBJECT_CLASS (g_dbus_proxy_parent_class)->constructed != NULL)
659     G_OBJECT_CLASS (g_dbus_proxy_parent_class)->constructed (object);
660 }
661
662 /* ---------------------------------------------------------------------------------------------------- */
663
664 static void
665 subscribe_to_signals (GDBusProxy *proxy)
666 {
667   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
668     {
669       /* subscribe to PropertiesChanged() */
670       proxy->priv->properties_changed_subscriber_id =
671         g_dbus_connection_signal_subscribe (proxy->priv->connection,
672                                             proxy->priv->unique_bus_name,
673                                             "org.freedesktop.DBus.Properties",
674                                             "PropertiesChanged",
675                                             proxy->priv->object_path,
676                                             proxy->priv->interface_name,
677                                             on_properties_changed,
678                                             proxy,
679                                             NULL);
680     }
681
682   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS))
683     {
684       /* subscribe to all signals for the object */
685       proxy->priv->signals_subscriber_id =
686         g_dbus_connection_signal_subscribe (proxy->priv->connection,
687                                             proxy->priv->unique_bus_name,
688                                             proxy->priv->interface_name,
689                                             NULL,                        /* member */
690                                             proxy->priv->object_path,
691                                             NULL,                        /* arg0 */
692                                             on_signal_received,
693                                             proxy,
694                                             NULL);
695     }
696 }
697
698 /* ---------------------------------------------------------------------------------------------------- */
699
700 static void
701 process_get_all_reply (GDBusProxy *proxy,
702                        GVariant   *result)
703 {
704   GVariantIter iter;
705   GVariant *item;
706
707   if (strcmp (g_variant_get_type_string (result), "(a{sv})") != 0)
708     {
709       g_warning ("Value for GetAll reply with type `%s' does not match `(a{sv})'",
710                  g_variant_get_type_string (result));
711       goto out;
712     }
713
714   proxy->priv->properties = g_hash_table_new_full (g_str_hash,
715                                                    g_str_equal,
716                                                    g_free,
717                                                    (GDestroyNotify) g_variant_unref);
718
719   g_variant_iter_init (&iter, g_variant_get_child_value (result, 0));
720   while ((item = g_variant_iter_next_value (&iter)) != NULL)
721     {
722       const gchar *key;
723       GVariant *value;
724
725       g_variant_get (item,
726                      "{sv}",
727                      &key,
728                      &value);
729       //g_print ("got %s -> %s\n", key, g_variant_markup_print (value, FALSE, 0, 0));
730
731       g_hash_table_insert (proxy->priv->properties,
732                            g_strdup (key),
733                            value); /* steals value */
734     }
735  out:
736   ;
737 }
738
739 static gboolean
740 initable_init (GInitable     *initable,
741                GCancellable  *cancellable,
742                GError       **error)
743 {
744   GDBusProxy *proxy = G_DBUS_PROXY (initable);
745   GVariant *result;
746   gboolean ret;
747
748   ret = FALSE;
749
750   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
751     {
752       /* load all properties synchronously */
753       result = g_dbus_connection_call_sync (proxy->priv->connection,
754                                             proxy->priv->unique_bus_name,
755                                             proxy->priv->object_path,
756                                             "org.freedesktop.DBus.Properties",
757                                             "GetAll",
758                                             g_variant_new ("(s)", proxy->priv->interface_name),
759                                             G_DBUS_CALL_FLAGS_NONE,
760                                             -1,           /* timeout */
761                                             cancellable,
762                                             error);
763       if (result == NULL)
764         goto out;
765
766       process_get_all_reply (proxy, result);
767
768       g_variant_unref (result);
769     }
770
771   subscribe_to_signals (proxy);
772
773   ret = TRUE;
774
775  out:
776   return ret;
777 }
778
779 static void
780 initable_iface_init (GInitableIface *initable_iface)
781 {
782   initable_iface->init = initable_init;
783 }
784
785 /* ---------------------------------------------------------------------------------------------------- */
786
787 static void
788 get_all_cb (GDBusConnection *connection,
789             GAsyncResult    *res,
790             gpointer         user_data)
791 {
792   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
793   GVariant *result;
794   GError *error;
795
796   error = NULL;
797   result = g_dbus_connection_call_finish (connection,
798                                           res,
799                                           &error);
800   if (result == NULL)
801     {
802       g_simple_async_result_set_from_error (simple, error);
803       g_error_free (error);
804     }
805   else
806     {
807       g_simple_async_result_set_op_res_gpointer (simple,
808                                                  result,
809                                                  (GDestroyNotify) g_variant_unref);
810     }
811
812   g_simple_async_result_complete_in_idle (simple);
813   g_object_unref (simple);
814 }
815
816 static void
817 async_initable_init_async (GAsyncInitable      *initable,
818                            gint                 io_priority,
819                            GCancellable        *cancellable,
820                            GAsyncReadyCallback  callback,
821                            gpointer             user_data)
822 {
823   GDBusProxy *proxy = G_DBUS_PROXY (initable);
824   GSimpleAsyncResult *simple;
825
826   simple = g_simple_async_result_new (G_OBJECT (proxy),
827                                       callback,
828                                       user_data,
829                                       NULL);
830
831   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
832     {
833       /* load all properties asynchronously */
834       g_dbus_connection_call (proxy->priv->connection,
835                               proxy->priv->unique_bus_name,
836                               proxy->priv->object_path,
837                               "org.freedesktop.DBus.Properties",
838                               "GetAll",
839                               g_variant_new ("(s)", proxy->priv->interface_name),
840                               G_DBUS_CALL_FLAGS_NONE,
841                               -1,           /* timeout */
842                               cancellable,
843                               (GAsyncReadyCallback) get_all_cb,
844                               simple);
845     }
846   else
847     {
848       g_simple_async_result_complete_in_idle (simple);
849       g_object_unref (simple);
850     }
851 }
852
853 static gboolean
854 async_initable_init_finish (GAsyncInitable  *initable,
855                             GAsyncResult    *res,
856                             GError         **error)
857 {
858   GDBusProxy *proxy = G_DBUS_PROXY (initable);
859   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
860   GVariant *result;
861   gboolean ret;
862
863   ret = FALSE;
864
865   result = g_simple_async_result_get_op_res_gpointer (simple);
866   if (result == NULL)
867     {
868       if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
869         {
870           g_simple_async_result_propagate_error (simple, error);
871           goto out;
872         }
873     }
874   else
875     {
876       process_get_all_reply (proxy, result);
877     }
878
879   subscribe_to_signals (proxy);
880
881   ret = TRUE;
882
883  out:
884   return ret;
885 }
886
887 static void
888 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
889 {
890   async_initable_iface->init_async = async_initable_init_async;
891   async_initable_iface->init_finish = async_initable_init_finish;
892 }
893
894 /* ---------------------------------------------------------------------------------------------------- */
895
896 /**
897  * g_dbus_proxy_new:
898  * @connection: A #GDBusConnection.
899  * @object_type: Either #G_TYPE_DBUS_PROXY or the #GType for the #GDBusProxy<!-- -->-derived type of proxy to create.
900  * @flags: Flags used when constructing the proxy.
901  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
902  * @unique_bus_name: A unique bus name or %NULL if @connection is not a message bus connection.
903  * @object_path: An object path.
904  * @interface_name: A D-Bus interface name.
905  * @cancellable: A #GCancellable or %NULL.
906  * @callback: Callback function to invoke when the proxy is ready.
907  * @user_data: User data to pass to @callback.
908  *
909  * Creates a proxy for accessing @interface_name on the remote object at @object_path
910  * owned by @unique_bus_name at @connection and asynchronously loads D-Bus properties unless the
911  * #G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used. Connect to the
912  * #GDBusProxy::g-properties-changed signal to get notified about property changes.
913  *
914  * If the #G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
915  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
916  * to handle signals from the remote object.
917  *
918  * This is a failable asynchronous constructor - when the proxy is
919  * ready, @callback will be invoked and you can use
920  * g_dbus_proxy_new_finish() to get the result.
921  *
922  * See g_dbus_proxy_new_sync() and for a synchronous version of this constructor.
923  *
924  * Since: 2.26
925  */
926 void
927 g_dbus_proxy_new (GDBusConnection     *connection,
928                   GType                object_type,
929                   GDBusProxyFlags      flags,
930                   GDBusInterfaceInfo  *info,
931                   const gchar         *unique_bus_name,
932                   const gchar         *object_path,
933                   const gchar         *interface_name,
934                   GCancellable        *cancellable,
935                   GAsyncReadyCallback  callback,
936                   gpointer             user_data)
937 {
938   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
939   g_return_if_fail (g_type_is_a (object_type, G_TYPE_DBUS_PROXY));
940   g_return_if_fail ((unique_bus_name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
941                     g_dbus_is_unique_name (unique_bus_name));
942   g_return_if_fail (g_variant_is_object_path (object_path));
943   g_return_if_fail (g_dbus_is_interface_name (interface_name));
944
945   g_async_initable_new_async (object_type,
946                               G_PRIORITY_DEFAULT,
947                               cancellable,
948                               callback,
949                               user_data,
950                               "g-flags", flags,
951                               "g-interface-info", info,
952                               "g-unique-bus-name", unique_bus_name,
953                               "g-connection", connection,
954                               "g-object-path", object_path,
955                               "g-interface-name", interface_name,
956                               NULL);
957 }
958
959 /**
960  * g_dbus_proxy_new_finish:
961  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new().
962  * @error: Return location for error or %NULL.
963  *
964  * Finishes creating a #GDBusProxy.
965  *
966  * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
967  *
968  * Since: 2.26
969  */
970 GDBusProxy *
971 g_dbus_proxy_new_finish (GAsyncResult  *res,
972                          GError       **error)
973 {
974   GObject *object;
975   GObject *source_object;
976
977   source_object = g_async_result_get_source_object (res);
978   g_assert (source_object != NULL);
979
980   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
981                                         res,
982                                         error);
983   g_object_unref (source_object);
984
985   if (object != NULL)
986     return G_DBUS_PROXY (object);
987   else
988     return NULL;
989 }
990
991
992 /* ---------------------------------------------------------------------------------------------------- */
993
994 /**
995  * g_dbus_proxy_new_sync:
996  * @connection: A #GDBusConnection.
997  * @object_type: Either #G_TYPE_DBUS_PROXY or the #GType for the #GDBusProxy<!-- -->-derived type of proxy to create.
998  * @flags: Flags used when constructing the proxy.
999  * @info: A #GDBusInterfaceInfo specifying the minimal interface that @proxy conforms to or %NULL.
1000  * @unique_bus_name: A unique bus name or %NULL if @connection is not a message bus connection.
1001  * @object_path: An object path.
1002  * @interface_name: A D-Bus interface name.
1003  * @cancellable: A #GCancellable or %NULL.
1004  * @error: Return location for error or %NULL.
1005  *
1006  * Creates a proxy for accessing @interface_name on the remote object at @object_path
1007  * owned by @unique_bus_name at @connection and synchronously loads D-Bus properties unless the
1008  * #G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used.
1009  *
1010  * If the #G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set, also sets up
1011  * match rules for signals. Connect to the #GDBusProxy::g-signal signal
1012  * to handle signals from the remote object.
1013  *
1014  * This is a synchronous failable constructor. See g_dbus_proxy_new()
1015  * and g_dbus_proxy_new_finish() for the asynchronous version.
1016  *
1017  * Returns: A #GDBusProxy or %NULL if error is set. Free with g_object_unref().
1018  *
1019  * Since: 2.26
1020  */
1021 GDBusProxy *
1022 g_dbus_proxy_new_sync (GDBusConnection     *connection,
1023                        GType                object_type,
1024                        GDBusProxyFlags      flags,
1025                        GDBusInterfaceInfo  *info,
1026                        const gchar         *unique_bus_name,
1027                        const gchar         *object_path,
1028                        const gchar         *interface_name,
1029                        GCancellable        *cancellable,
1030                        GError             **error)
1031 {
1032   GInitable *initable;
1033
1034   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1035   g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_DBUS_PROXY), NULL);
1036   g_return_val_if_fail ((unique_bus_name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
1037                         g_dbus_is_unique_name (unique_bus_name), NULL);
1038   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
1039   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
1040
1041   initable = g_initable_new (object_type,
1042                              cancellable,
1043                              error,
1044                              "g-flags", flags,
1045                              "g-interface-info", info,
1046                              "g-unique-bus-name", unique_bus_name,
1047                              "g-connection", connection,
1048                              "g-object-path", object_path,
1049                              "g-interface-name", interface_name,
1050                              NULL);
1051   if (initable != NULL)
1052     return G_DBUS_PROXY (initable);
1053   else
1054     return NULL;
1055 }
1056
1057 /* ---------------------------------------------------------------------------------------------------- */
1058
1059 /**
1060  * g_dbus_proxy_get_connection:
1061  * @proxy: A #GDBusProxy.
1062  *
1063  * Gets the connection @proxy is for.
1064  *
1065  * Returns: A #GDBusConnection owned by @proxy. Do not free.
1066  *
1067  * Since: 2.26
1068  */
1069 GDBusConnection *
1070 g_dbus_proxy_get_connection (GDBusProxy *proxy)
1071 {
1072   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1073   return proxy->priv->connection;
1074 }
1075
1076 /**
1077  * g_dbus_proxy_get_flags:
1078  * @proxy: A #GDBusProxy.
1079  *
1080  * Gets the flags that @proxy was constructed with.
1081  *
1082  * Returns: Flags from the #GDBusProxyFlags enumeration.
1083  *
1084  * Since: 2.26
1085  */
1086 GDBusProxyFlags
1087 g_dbus_proxy_get_flags (GDBusProxy *proxy)
1088 {
1089   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
1090   return proxy->priv->flags;
1091 }
1092
1093 /**
1094  * g_dbus_proxy_get_unique_bus_name:
1095  * @proxy: A #GDBusProxy.
1096  *
1097  * Gets the unique bus name @proxy is for.
1098  *
1099  * Returns: A string owned by @proxy. Do not free.
1100  *
1101  * Since: 2.26
1102  */
1103 const gchar *
1104 g_dbus_proxy_get_unique_bus_name (GDBusProxy *proxy)
1105 {
1106   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1107   return proxy->priv->unique_bus_name;
1108 }
1109
1110 /**
1111  * g_dbus_proxy_get_object_path:
1112  * @proxy: A #GDBusProxy.
1113  *
1114  * Gets the object path @proxy is for.
1115  *
1116  * Returns: A string owned by @proxy. Do not free.
1117  *
1118  * Since: 2.26
1119  */
1120 const gchar *
1121 g_dbus_proxy_get_object_path (GDBusProxy *proxy)
1122 {
1123   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1124   return proxy->priv->object_path;
1125 }
1126
1127 /**
1128  * g_dbus_proxy_get_interface_name:
1129  * @proxy: A #GDBusProxy.
1130  *
1131  * Gets the D-Bus interface name @proxy is for.
1132  *
1133  * Returns: A string owned by @proxy. Do not free.
1134  *
1135  * Since: 2.26
1136  */
1137 const gchar *
1138 g_dbus_proxy_get_interface_name (GDBusProxy *proxy)
1139 {
1140   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1141   return proxy->priv->interface_name;
1142 }
1143
1144 /**
1145  * g_dbus_proxy_get_default_timeout:
1146  * @proxy: A #GDBusProxy.
1147  *
1148  * Gets the timeout to use if -1 (specifying default timeout) is
1149  * passed as @timeout_msec in the g_dbus_proxy_call() and
1150  * g_dbus_proxy_call_sync() functions.
1151  *
1152  * See the #GDBusProxy:g-default-timeout property for more details.
1153  *
1154  * Returns: Timeout to use for @proxy.
1155  *
1156  * Since: 2.26
1157  */
1158 gint
1159 g_dbus_proxy_get_default_timeout (GDBusProxy *proxy)
1160 {
1161   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), -1);
1162   return proxy->priv->timeout_msec;
1163 }
1164
1165 /**
1166  * g_dbus_proxy_set_default_timeout:
1167  * @proxy: A #GDBusProxy.
1168  * @timeout_msec: Timeout in milliseconds.
1169  *
1170  * Sets the timeout to use if -1 (specifying default timeout) is
1171  * passed as @timeout_msec in the g_dbus_proxy_call() and
1172  * g_dbus_proxy_call_sync() functions.
1173  *
1174  * See the #GDBusProxy:g-default-timeout property for more details.
1175  *
1176  * Since: 2.26
1177  */
1178 void
1179 g_dbus_proxy_set_default_timeout (GDBusProxy *proxy,
1180                                   gint        timeout_msec)
1181 {
1182   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
1183   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
1184
1185   /* TODO: locking? */
1186   if (proxy->priv->timeout_msec != timeout_msec)
1187     {
1188       proxy->priv->timeout_msec = timeout_msec;
1189       g_object_notify (G_OBJECT (proxy), "g-default-timeout");
1190     }
1191 }
1192
1193 /**
1194  * g_dbus_proxy_get_interface_info:
1195  * @proxy: A #GDBusProxy
1196  *
1197  * Returns the #GDBusInterfaceInfo, if any, specifying the minimal
1198  * interface that @proxy conforms to.
1199  *
1200  * See the #GDBusProxy:g-interface-info property for more details.
1201  *
1202  * Returns: A #GDBusInterfaceInfo or %NULL. Do not unref the returned
1203  * object, it is owned by @proxy.
1204  *
1205  * Since: 2.26
1206  */
1207 GDBusInterfaceInfo *
1208 g_dbus_proxy_get_interface_info (GDBusProxy *proxy)
1209 {
1210   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1211   return proxy->priv->expected_interface;
1212 }
1213
1214 /**
1215  * g_dbus_proxy_set_interface_info:
1216  * @proxy: A #GDBusProxy
1217  * @info: Minimum interface this proxy conforms to or %NULL to unset.
1218  *
1219  * Ensure that interactions with @proxy conform to the given
1220  * interface.  For example, when completing a method call, if the type
1221  * signature of the message isn't what's expected, the given #GError
1222  * is set.  Signals that have a type signature mismatch are simply
1223  * dropped.
1224  *
1225  * See the #GDBusProxy:g-interface-info property for more details.
1226  *
1227  * Since: 2.26
1228  */
1229 void
1230 g_dbus_proxy_set_interface_info (GDBusProxy         *proxy,
1231                                  GDBusInterfaceInfo *info)
1232 {
1233   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
1234   if (proxy->priv->expected_interface != NULL)
1235     g_dbus_interface_info_unref (proxy->priv->expected_interface);
1236   proxy->priv->expected_interface = info != NULL ? g_dbus_interface_info_ref (info) : NULL;
1237 }
1238
1239 /* ---------------------------------------------------------------------------------------------------- */
1240
1241 static gboolean
1242 maybe_split_method_name (const gchar  *method_name,
1243                          gchar       **out_interface_name,
1244                          const gchar **out_method_name)
1245 {
1246   gboolean was_split;
1247
1248   was_split = FALSE;
1249   g_assert (out_interface_name != NULL);
1250   g_assert (out_method_name != NULL);
1251   *out_interface_name = NULL;
1252   *out_method_name = NULL;
1253
1254   if (strchr (method_name, '.') != NULL)
1255     {
1256       gchar *p;
1257       gchar *last_dot;
1258
1259       p = g_strdup (method_name);
1260       last_dot = strrchr (p, '.');
1261       *last_dot = '\0';
1262
1263       *out_interface_name = p;
1264       *out_method_name = last_dot + 1;
1265
1266       was_split = TRUE;
1267     }
1268
1269   return was_split;
1270 }
1271
1272
1273 static void
1274 reply_cb (GDBusConnection *connection,
1275           GAsyncResult    *res,
1276           gpointer         user_data)
1277 {
1278   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
1279   GVariant *value;
1280   GError *error;
1281
1282   error = NULL;
1283   value = g_dbus_connection_call_finish (connection,
1284                                          res,
1285                                          &error);
1286   if (error != NULL)
1287     {
1288       g_simple_async_result_set_from_error (simple,
1289                                             error);
1290       g_error_free (error);
1291     }
1292   else
1293     {
1294       g_simple_async_result_set_op_res_gpointer (simple,
1295                                                  value,
1296                                                  (GDestroyNotify) g_variant_unref);
1297     }
1298
1299   /* no need to complete in idle since the method GDBusConnection already does */
1300   g_simple_async_result_complete (simple);
1301 }
1302
1303 static const GDBusMethodInfo *
1304 lookup_method_info_or_warn (GDBusProxy  *proxy,
1305                             const gchar *method_name)
1306 {
1307   const GDBusMethodInfo *info;
1308
1309   if (!proxy->priv->expected_interface)
1310     return NULL;
1311
1312   info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, method_name);
1313   if (!info)
1314     g_warning ("Trying to invoke method %s which isn't in expected interface %s",
1315                method_name, proxy->priv->expected_interface->name);
1316
1317   return info;
1318 }
1319
1320 static gboolean
1321 validate_method_return (const char             *method_name,
1322                         GVariant               *value,
1323                         const GDBusMethodInfo  *expected_method_info,
1324                         GError                **error)
1325 {
1326   const gchar *type_string;
1327   gchar *signature;
1328   gboolean ret;
1329
1330   ret = TRUE;
1331   signature = NULL;
1332
1333   if (value == NULL || expected_method_info == NULL)
1334     goto out;
1335
1336   /* Shouldn't happen... */
1337   if (g_variant_classify (value) != G_VARIANT_CLASS_TUPLE)
1338     goto out;
1339
1340   type_string = g_variant_get_type_string (value);
1341   signature = _g_dbus_compute_complete_signature (expected_method_info->out_args, TRUE);
1342   if (g_strcmp0 (type_string, signature) != 0)
1343     {
1344       g_set_error (error,
1345                    G_IO_ERROR,
1346                    G_IO_ERROR_INVALID_ARGUMENT,
1347                    _("Method `%s' returned signature `%s', but expected `%s'"),
1348                    method_name,
1349                    type_string,
1350                    signature);
1351       ret = FALSE;
1352     }
1353
1354  out:
1355   g_free (signature);
1356   return ret;
1357 }
1358
1359 /**
1360  * g_dbus_proxy_call:
1361  * @proxy: A #GDBusProxy.
1362  * @method_name: Name of method to invoke.
1363  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
1364  * @flags: Flags from the #GDBusCallFlags enumeration.
1365  * @timeout_msec: The timeout in milliseconds or -1 to use the proxy default timeout.
1366  * @cancellable: A #GCancellable or %NULL.
1367  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
1368  * care about the result of the method invocation.
1369  * @user_data: The data to pass to @callback.
1370  *
1371  * Asynchronously invokes the @method_name method on @proxy.
1372  *
1373  * If @method_name contains any dots, then @name is split into interface and
1374  * method name parts. This allows using @proxy for invoking methods on
1375  * other interfaces.
1376  *
1377  * If the #GDBusConnection associated with @proxy is closed then
1378  * the operation will fail with %G_IO_ERROR_CLOSED. If
1379  * @cancellable is canceled, the operation will fail with
1380  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
1381  * compatible with the D-Bus protocol, the operation fails with
1382  * %G_IO_ERROR_INVALID_ARGUMENT.
1383  *
1384  * If the @parameters #GVariant is floating, it is consumed. This allows
1385  * convenient 'inline' use of g_variant_new(), e.g.:
1386  * |[
1387  *  g_dbus_proxy_call (proxy,
1388  *                     "TwoStrings",
1389  *                     g_variant_new ("(ss)",
1390  *                                    "Thing One",
1391  *                                    "Thing Two"),
1392  *                     G_DBUS_CALL_FLAGS_NONE,
1393  *                     -1,
1394  *                     NULL,
1395  *                     (GAsyncReadyCallback) two_strings_done,
1396  *                     &amp;data);
1397  * ]|
1398  *
1399  * This is an asynchronous method. When the operation is finished,
1400  * @callback will be invoked in the
1401  * <link linkend="g-main-context-push-thread-default">thread-default
1402  * main loop</link> of the thread you are calling this method from.
1403  * You can then call g_dbus_proxy_call_finish() to get the result of
1404  * the operation. See g_dbus_proxy_call_sync() for the synchronous
1405  * version of this method.
1406  *
1407  * Since: 2.26
1408  */
1409 void
1410 g_dbus_proxy_call (GDBusProxy          *proxy,
1411                    const gchar         *method_name,
1412                    GVariant            *parameters,
1413                    GDBusCallFlags       flags,
1414                    gint                 timeout_msec,
1415                    GCancellable        *cancellable,
1416                    GAsyncReadyCallback  callback,
1417                    gpointer             user_data)
1418 {
1419   GSimpleAsyncResult *simple;
1420   gboolean was_split;
1421   gchar *split_interface_name;
1422   const gchar *split_method_name;
1423   const GDBusMethodInfo *expected_method_info;
1424   const gchar *target_method_name;
1425   const gchar *target_interface_name;
1426
1427   g_return_if_fail (G_IS_DBUS_PROXY (proxy));
1428   g_return_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name));
1429   g_return_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
1430   g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
1431
1432   simple = g_simple_async_result_new (G_OBJECT (proxy),
1433                                       callback,
1434                                       user_data,
1435                                       g_dbus_proxy_call);
1436
1437   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
1438   target_method_name = was_split ? split_method_name : method_name;
1439   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
1440
1441   g_object_set_data_full (G_OBJECT (simple), "-gdbus-proxy-method-name", g_strdup (target_method_name), g_free);
1442
1443   /* Just warn here */
1444   expected_method_info = lookup_method_info_or_warn (proxy, target_method_name);
1445
1446   g_dbus_connection_call (proxy->priv->connection,
1447                           proxy->priv->unique_bus_name,
1448                           proxy->priv->object_path,
1449                           target_interface_name,
1450                           target_method_name,
1451                           parameters,
1452                           flags,
1453                           timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
1454                           cancellable,
1455                           (GAsyncReadyCallback) reply_cb,
1456                           simple);
1457
1458   g_free (split_interface_name);
1459 }
1460
1461 /**
1462  * g_dbus_proxy_call_finish:
1463  * @proxy: A #GDBusProxy.
1464  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call().
1465  * @error: Return location for error or %NULL.
1466  *
1467  * Finishes an operation started with g_dbus_proxy_call().
1468  *
1469  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
1470  * return values. Free with g_variant_unref().
1471  *
1472  * Since: 2.26
1473  */
1474 GVariant *
1475 g_dbus_proxy_call_finish (GDBusProxy    *proxy,
1476                           GAsyncResult  *res,
1477                           GError       **error)
1478 {
1479   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
1480   GVariant *value;
1481   const char *method_name;
1482   const GDBusMethodInfo *expected_method_info;
1483
1484   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1485   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
1486   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1487
1488   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_proxy_call);
1489
1490   value = NULL;
1491
1492   if (g_simple_async_result_propagate_error (simple, error))
1493     goto out;
1494
1495   value = g_simple_async_result_get_op_res_gpointer (simple);
1496   method_name = g_object_get_data (G_OBJECT (simple), "-gdbus-proxy-method-name");
1497
1498   /* We may not have a method name for internally-generated proxy calls like GetAll */
1499   if (value && method_name && proxy->priv->expected_interface)
1500     {
1501       expected_method_info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, method_name);
1502       if (!validate_method_return (method_name, value, expected_method_info, error))
1503         {
1504           g_variant_unref (value);
1505           value = NULL;
1506         }
1507     }
1508
1509  out:
1510   return value;
1511 }
1512
1513 /**
1514  * g_dbus_proxy_call_sync:
1515  * @proxy: A #GDBusProxy.
1516  * @method_name: Name of method to invoke.
1517  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
1518  * @flags: Flags from the #GDBusCallFlags enumeration.
1519  * @timeout_msec: The timeout in milliseconds or -1 to use the proxy default timeout.
1520  * @cancellable: A #GCancellable or %NULL.
1521  * @error: Return location for error or %NULL.
1522  *
1523  * Synchronously invokes the @method_name method on @proxy.
1524  *
1525  * If @method_name contains any dots, then @name is split into interface and
1526  * method name parts. This allows using @proxy for invoking methods on
1527  * other interfaces.
1528  *
1529  * If the #GDBusConnection associated with @proxy is disconnected then
1530  * the operation will fail with %G_IO_ERROR_CLOSED. If
1531  * @cancellable is canceled, the operation will fail with
1532  * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
1533  * compatible with the D-Bus protocol, the operation fails with
1534  * %G_IO_ERROR_INVALID_ARGUMENT.
1535  *
1536  * If the @parameters #GVariant is floating, it is consumed. This allows
1537  * convenient 'inline' use of g_variant_new(), e.g.:
1538  * |[
1539  *  g_dbus_proxy_call_sync (proxy,
1540  *                          "TwoStrings",
1541  *                          g_variant_new ("(ss)",
1542  *                                         "Thing One",
1543  *                                         "Thing Two"),
1544  *                          G_DBUS_CALL_FLAGS_NONE,
1545  *                          -1,
1546  *                          NULL,
1547  *                          &amp;error);
1548  * ]|
1549  *
1550  * The calling thread is blocked until a reply is received. See
1551  * g_dbus_proxy_call() for the asynchronous version of this
1552  * method.
1553  *
1554  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
1555  * return values. Free with g_variant_unref().
1556  *
1557  * Since: 2.26
1558  */
1559 GVariant *
1560 g_dbus_proxy_call_sync (GDBusProxy      *proxy,
1561                         const gchar     *method_name,
1562                         GVariant        *parameters,
1563                         GDBusCallFlags   flags,
1564                         gint             timeout_msec,
1565                         GCancellable    *cancellable,
1566                         GError         **error)
1567 {
1568   GVariant *ret;
1569   gboolean was_split;
1570   gchar *split_interface_name;
1571   const gchar *split_method_name;
1572   const GDBusMethodInfo *expected_method_info;
1573   const gchar *target_method_name;
1574   const gchar *target_interface_name;
1575
1576   g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
1577   g_return_val_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name), NULL);
1578   g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
1579   g_return_val_if_fail (timeout_msec == -1 || timeout_msec >= 0, NULL);
1580   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1581
1582   was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
1583   target_method_name = was_split ? split_method_name : method_name;
1584   target_interface_name = was_split ? split_interface_name : proxy->priv->interface_name;
1585
1586   if (proxy->priv->expected_interface)
1587     {
1588       expected_method_info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, target_method_name);
1589       if (!expected_method_info)
1590         g_warning ("Trying to invoke method %s which isn't in expected interface %s",
1591                    target_method_name, target_interface_name);
1592     }
1593   else
1594     {
1595       expected_method_info = NULL;
1596     }
1597
1598   ret = g_dbus_connection_call_sync (proxy->priv->connection,
1599                                      proxy->priv->unique_bus_name,
1600                                      proxy->priv->object_path,
1601                                      target_interface_name,
1602                                      target_method_name,
1603                                      parameters,
1604                                      flags,
1605                                      timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
1606                                      cancellable,
1607                                      error);
1608   if (!validate_method_return (target_method_name, ret, expected_method_info, error))
1609     {
1610       g_variant_unref (ret);
1611       ret = NULL;
1612     }
1613
1614   g_free (split_interface_name);
1615
1616   return ret;
1617 }
1618
1619 /* ---------------------------------------------------------------------------------------------------- */
1620
1621 #define __G_DBUS_PROXY_C__
1622 #include "gioaliasdef.c"