Add gobject introspection
[profile/ivi/GUPnP.git] / libgupnp / gupnp-connman-manager.c
1 /*
2  * Copyright (C) 2012 Intel Corporation. All rights reserved.
3  * Copyright (C) 2009 Nokia Corporation.
4  *
5  * Author: Ludovic Ferrandis <ludovic.ferrandis@intel.com>
6  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
7  *                               <zeeshan.ali@nokia.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 /**
26  * SECTION:gupnp-connman-manager
27  * @short_description: Connman-based implementation of
28  * #GUPnPContextManager.
29  *
30  */
31
32 #include "gupnp-connman-manager.h"
33 #include "gupnp-context.h"
34 #include "gupnp-marshal.h"
35
36 typedef enum
37 {
38         CM_SERVICE_STATE_ACTIVE   = 1,
39         CM_SERVICE_STATE_INACTIVE = 2
40
41 } CMServiceState;
42
43 typedef struct {
44         GUPnPConnmanManager *manager;
45         GUPnPContext        *context;
46         GDBusProxy          *proxy;
47         CMServiceState      current;
48         guint               sig_prop_id;
49         guint               port;
50         gchar               *iface;
51         gchar               *name;
52
53 } CMService;
54
55 struct _GUPnPConnmanManagerPrivate {
56         GDBusProxy *manager_proxy;
57         GSource    *idle_context_creation_src;
58         GHashTable *cm_services;
59         guint      sig_change_id;
60         GDBusConnection *system_bus;
61 };
62
63 #define CM_DBUS_CONNMAN_NAME      "net.connman"
64 #define CM_DBUS_MANAGER_PATH      "/"
65 #define CM_DBUS_MANAGER_INTERFACE "net.connman.Manager"
66 #define CM_DBUS_SERVICE_INTERFACE "net.connman.Service"
67
68 #define DBUS_SERVICE_DBUS   "org.freedesktop.DBus"
69 #define DBUS_PATH_DBUS      "/org/freedesktop/DBus"
70 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
71
72 #define LOOPBACK_IFACE "lo"
73
74 G_DEFINE_TYPE (GUPnPConnmanManager,
75                gupnp_connman_manager,
76                GUPNP_TYPE_CONTEXT_MANAGER);
77
78 static gboolean
79 loopback_context_create (gpointer data)
80 {
81         GUPnPConnmanManager *manager;
82         GUPnPContext        *context;
83         GError              *error = NULL;
84         guint               port;
85
86         manager = GUPNP_CONNMAN_MANAGER (data);
87         manager->priv->idle_context_creation_src = NULL;
88
89         g_object_get (manager, "port", &port, NULL);
90
91         context = g_initable_new (GUPNP_TYPE_CONTEXT,
92                                   NULL,
93                                   &error,
94                                   "interface", LOOPBACK_IFACE,
95                                   "port", port,
96                                   NULL);
97
98         if (error != NULL) {
99                 g_warning ("Error creating GUPnP context: %s", error->message);
100                 g_error_free (error);
101
102                 return FALSE;
103         }
104
105         g_signal_emit_by_name (manager, "context-available", context);
106         g_object_unref (context);
107
108         return FALSE;
109 }
110
111 static gboolean
112 service_context_create (CMService *cm_service)
113 {
114         GError  *error = NULL;
115
116         cm_service->context = g_initable_new (GUPNP_TYPE_CONTEXT,
117                                               NULL,
118                                               &error,
119                                               "interface", cm_service->iface,
120                                               "network", cm_service->name,
121                                               "port", cm_service->port,
122                                               NULL);
123
124         if (error != NULL) {
125                 g_warning ("Error creating GUPnP context: %s", error->message);
126                 g_error_free (error);
127
128                 return FALSE;
129         }
130
131         g_signal_emit_by_name (cm_service->manager,
132                                "context-available",
133                                cm_service->context);
134
135         return TRUE;
136 }
137
138 static void
139 service_context_delete (CMService *cm_service)
140 {
141         // For other states we just destroy the context
142         g_signal_emit_by_name (cm_service->manager,
143                                "context-unavailable",
144                                cm_service->context);
145
146         g_object_unref (cm_service->context);
147         cm_service->context = NULL;
148 }
149
150 static void
151 service_context_update (CMService *cm_service, CMServiceState new_state)
152 {
153         if (cm_service->current != new_state) {
154                 if (new_state == CM_SERVICE_STATE_ACTIVE) {
155                         if (service_context_create (cm_service) == FALSE)
156                                 new_state = CM_SERVICE_STATE_INACTIVE;
157
158                 } else if ((new_state == CM_SERVICE_STATE_INACTIVE) &&
159                            (cm_service->context != NULL)) {
160                                 service_context_delete (cm_service);
161                 }
162
163                 cm_service->current = new_state;
164         }
165 }
166
167 static void
168 on_service_property_signal (GDBusConnection *connection,
169                             const gchar     *sender_name,
170                             const gchar     *object_path,
171                             const gchar     *interface_name,
172                             const gchar     *signal_name,
173                             GVariant        *parameters,
174                             gpointer        user_data)
175 {
176         CMService      *cm_service;
177         GVariant       *value;
178         gchar          *name;
179         const gchar    *state_str;
180         CMServiceState new_state;
181
182         cm_service = (CMService *) user_data;
183         g_variant_get (parameters, "(&sv)", &name, &value);
184
185         if (g_strcmp0 (name, "Name") == 0) {
186                 g_free (cm_service->name);
187                 g_variant_get (value, "s", &cm_service->name);
188
189                 if (cm_service->context != NULL)
190                         g_object_set (G_OBJECT (cm_service->context),
191                                                "network",
192                                                cm_service->name,
193                                                NULL);
194
195         } else if (g_strcmp0 (name, "Ethernet") == 0) {
196                 g_free (cm_service->iface);
197                 g_variant_lookup (value, "Interface", "s", &cm_service->iface);
198
199                 if (cm_service->context != NULL)
200                         g_object_set (G_OBJECT (cm_service->context),
201                                                "interface",
202                                                cm_service->iface,
203                                                NULL);
204
205         } else if (g_strcmp0 (name, "State") == 0) {
206                 state_str = g_variant_get_string (value, 0);
207
208                 if ((g_strcmp0 (state_str, "online") == 0) ||
209                     (g_strcmp0 (state_str, "ready") == 0))
210                         new_state = CM_SERVICE_STATE_ACTIVE;
211                 else
212                         new_state = CM_SERVICE_STATE_INACTIVE;
213
214                 service_context_update (cm_service, new_state);
215         }
216
217         g_variant_unref (value);
218 }
219
220 static CMService *
221 cm_service_new (GUPnPConnmanManager *manager,
222                 GDBusProxy          *service_proxy)
223 {
224         CMService *cm_service;
225
226         cm_service = g_slice_new0 (CMService);
227
228         cm_service->manager = manager;
229         cm_service->proxy   = service_proxy;
230         cm_service->current = CM_SERVICE_STATE_INACTIVE;
231
232         return cm_service;
233 }
234
235 static void
236 cm_service_free (CMService *cm_service)
237 {
238         GDBusConnection *cnx;
239
240         cnx = g_dbus_proxy_get_connection (cm_service->proxy);
241
242         if (cm_service->sig_prop_id) {
243                 g_dbus_connection_signal_unsubscribe (cnx,
244                                                       cm_service->sig_prop_id);
245                 cm_service->sig_prop_id = 0;
246         }
247
248         g_object_unref (cm_service->proxy);
249
250         if (cm_service->context != NULL) {
251                 g_signal_emit_by_name (cm_service->manager,
252                                        "context-unavailable",
253                                        cm_service->context);
254
255                 g_object_unref (cm_service->context);
256         }
257
258         g_free (cm_service->iface);
259         g_free (cm_service->name);
260         g_slice_free (CMService, cm_service);
261 }
262
263 static void
264 cm_service_use (GUPnPConnmanManager *manager,
265                 CMService           *cm_service)
266 {
267         GDBusConnection *connection;
268
269         connection = g_dbus_proxy_get_connection (cm_service->proxy);
270
271         cm_service->sig_prop_id = g_dbus_connection_signal_subscribe (
272                                 connection,
273                                 CM_DBUS_CONNMAN_NAME,
274                                 CM_DBUS_SERVICE_INTERFACE,
275                                 "PropertyChanged",
276                                 g_dbus_proxy_get_object_path (cm_service->proxy),
277                                 NULL,
278                                 G_DBUS_SIGNAL_FLAGS_NONE,
279                                 on_service_property_signal,
280                                 cm_service,
281                                 NULL);
282
283         if (cm_service->current == CM_SERVICE_STATE_ACTIVE)
284                 if (service_context_create (cm_service) == FALSE)
285                         cm_service->current = CM_SERVICE_STATE_INACTIVE;
286 }
287 static void
288 cm_service_update (CMService *cm_service, GVariant *dict, guint port)
289 {
290         CMServiceState new_state;
291         GVariant       *eth;
292         gchar          *iface;
293         gchar          *name;
294         gchar          *state;
295         gboolean       is_name;
296         gboolean       is_iface;
297
298         is_iface = FALSE;
299         iface    = NULL;
300         name     = NULL;
301
302         is_name = g_variant_lookup (dict, "Name", "s", &name);
303
304         eth = g_variant_lookup_value (dict, "Ethernet", G_VARIANT_TYPE_VARDICT);
305
306         if (eth != NULL) {
307                 is_iface = g_variant_lookup (eth, "Interface", "s", &iface);
308                 g_variant_unref (eth);
309         }
310
311         new_state = CM_SERVICE_STATE_INACTIVE;
312
313         if (g_variant_lookup (dict, "State", "&s", &state) != FALSE)
314                 if ((g_strcmp0 (state, "online") == 0) ||
315                     (g_strcmp0 (state, "ready") == 0))
316                         new_state = CM_SERVICE_STATE_ACTIVE;
317
318         if (is_name && (g_strcmp0 (cm_service->name, name) == 0)) {
319                 g_free (cm_service->name);
320                 cm_service->name = name;
321
322                 if (cm_service->context != NULL)
323                         g_object_set (G_OBJECT (cm_service->context),
324                                       "network",
325                                       cm_service->name,
326                                       NULL);
327         }
328
329         if (is_iface && (g_strcmp0 (cm_service->iface, iface) == 0)) {
330                 g_free (cm_service->iface);
331                 cm_service->iface = iface;
332
333                 if (cm_service->context != NULL)
334                         g_object_set (G_OBJECT (cm_service->context),
335                                       "interface",
336                                       cm_service->iface,
337                                       NULL);
338         }
339
340         cm_service->port = port;
341         service_context_update (cm_service, new_state);
342 }
343
344 static void
345 service_proxy_new_cb (GObject      *source_object,
346                       GAsyncResult *res,
347                       gpointer     user_data)
348 {
349         GUPnPConnmanManager *manager;
350         GDBusProxy          *service_proxy;
351         GError              *error = NULL;
352         CMService           *cm_service;
353         const gchar         *path;
354
355         service_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
356
357         if (error != NULL) {
358                 g_warning ("Failed to create D-Bus proxy: %s", error->message);
359                 g_error_free (error);
360
361                 return;
362         }
363
364         manager = GUPNP_CONNMAN_MANAGER (user_data);
365         path = g_dbus_proxy_get_object_path (service_proxy);
366         cm_service = g_hash_table_lookup (manager->priv->cm_services, path);
367
368         if (cm_service == NULL) {
369                 g_object_unref (service_proxy);
370
371                 return;
372         }
373
374         cm_service->proxy = service_proxy;
375         cm_service_use (manager, cm_service);
376 }
377
378 static void
379 cm_service_add (GUPnPConnmanManager *manager,
380                 GVariant            *dict,
381                 gchar               *path,
382                 guint               port)
383 {
384         CMServiceState new_state;
385         CMService      *cm_service;
386         GVariant       *eth;
387         gchar          *iface;
388         gchar          *name;
389         gchar          *state;
390
391         iface   = NULL;
392         name    = NULL;
393
394         g_variant_lookup (dict, "Name", "s", &name);
395
396         eth = g_variant_lookup_value (dict, "Ethernet", G_VARIANT_TYPE_VARDICT);
397
398         if (eth != NULL) {
399                 g_variant_lookup (eth, "Interface", "s", &iface);
400                 g_variant_unref (eth);
401         }
402
403         new_state = CM_SERVICE_STATE_INACTIVE;
404
405         if (g_variant_lookup (dict, "State", "&s", &state) != FALSE)
406                 if ((g_strcmp0 (state, "online") == 0) ||
407                     (g_strcmp0 (state, "ready") == 0))
408                         new_state = CM_SERVICE_STATE_ACTIVE;
409
410         cm_service = cm_service_new (manager, NULL);
411
412         cm_service->name    = name;
413         cm_service->iface   = iface;
414         cm_service->port    = port;
415         cm_service->current = new_state;
416
417         g_hash_table_insert (manager->priv->cm_services,
418                              g_strdup (path),
419                              cm_service);
420
421         g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
422                                   G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
423                                   G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
424                                   NULL,
425                                   CM_DBUS_CONNMAN_NAME,
426                                   path,
427                                   CM_DBUS_SERVICE_INTERFACE,
428                                   NULL,
429                                   service_proxy_new_cb,
430                                   manager);
431 }
432
433 static void
434 services_array_add (GUPnPConnmanManager *manager, GVariant *data)
435 {
436         GVariant     *dict;
437         CMService    *cm_service;
438         gchar        *path;
439         GVariantIter iter;
440         GVariantIter dict_iter;
441         guint        port;
442
443         g_object_get (manager, "port", &port, NULL);
444         g_variant_iter_init (&iter, data);
445
446         while (g_variant_iter_loop (&iter, "(&o@a{sv})", &path, &dict)) {
447
448                 if (path == NULL)
449                         continue;
450
451                 if (dict == NULL)
452                         continue;
453
454                 if (g_variant_iter_init (&dict_iter, dict) == 0)
455                         continue;
456
457                 cm_service = g_hash_table_lookup (manager->priv->cm_services,
458                                                   path);
459
460                 if (cm_service == NULL)
461                         cm_service_add (manager, dict, path, port);
462                 else
463                         cm_service_update (cm_service, dict, port);
464         }
465 }
466
467 static void
468 services_array_remove (GUPnPConnmanManager *manager, GVariant *data)
469 {
470         GUPnPConnmanManagerPrivate *priv;
471         CMService                  *cm_service;
472         char                       *path;
473         GVariantIter               iter;
474
475         priv = manager->priv;
476         g_variant_iter_init (&iter, data);
477
478         while (g_variant_iter_next (&iter, "&o", &path)) {
479                 if (path == NULL)
480                         continue;
481
482                 cm_service = g_hash_table_lookup (priv->cm_services, path);
483
484                 if (cm_service == NULL)
485                         continue;
486
487                 g_hash_table_remove (priv->cm_services, path);
488         }
489 }
490
491 static void
492 on_manager_svc_changed_signal (GDBusConnection *connection,
493                                const gchar     *sender_name,
494                                const gchar     *object_path,
495                                const gchar     *interface_name,
496                                const gchar     *signal_name,
497                                GVariant        *parameters,
498                                gpointer        user_data)
499 {
500         GUPnPConnmanManager *manager;
501         GVariant            *add_array;
502         GVariant            *remove_array;
503
504         manager = GUPNP_CONNMAN_MANAGER (user_data);
505
506         add_array = g_variant_get_child_value (parameters, 0);
507         remove_array = g_variant_get_child_value (parameters, 1);
508
509         if ((add_array != NULL) && (g_variant_n_children (add_array) > 0))
510                 services_array_add (manager, add_array);
511
512         if ((remove_array != NULL) && (g_variant_n_children (remove_array) > 0))
513                 services_array_remove (manager, remove_array);
514
515         g_variant_unref (add_array);
516         g_variant_unref (remove_array);
517 }
518
519 static void
520 get_services_cb (GObject      *source_object,
521                  GAsyncResult *res,
522                  gpointer     user_data)
523 {
524         GUPnPConnmanManager *manager;
525         GVariant            *ret;
526         GVariant            *services_array;
527         GError              *error = NULL;
528
529         ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
530                                         res,
531                                         &error);
532
533         if (error != NULL) {
534                 g_warning ("Error fetching service list: %s", error->message);
535                 g_error_free (error);
536
537                 return;
538         }
539
540         if (ret == NULL) {
541                 g_warning ("Failed fetching list of services but no error");
542
543                 return;
544         }
545
546         if (g_variant_is_container (ret) != TRUE)
547         {
548                 g_warning ("Wrong format result");
549                 g_variant_unref (ret);
550
551                 return;
552         }
553
554         manager = GUPNP_CONNMAN_MANAGER (user_data);
555         services_array = g_variant_get_child_value (ret, 0);
556         services_array_add (manager, services_array);
557
558         g_variant_unref (services_array);
559         g_variant_unref (ret);
560 }
561
562 static void
563 schedule_loopback_context_creation (GUPnPConnmanManager *manager)
564 {
565         /* Create contexts in mainloop so that it happens after user has hooked
566          * to the "context-available" signal.
567          */
568         manager->priv->idle_context_creation_src = g_idle_source_new ();
569
570         g_source_attach (manager->priv->idle_context_creation_src,
571                          g_main_context_get_thread_default ());
572
573         g_source_set_callback (manager->priv->idle_context_creation_src,
574                                loopback_context_create,
575                                manager,
576                                NULL);
577
578         g_source_unref (manager->priv->idle_context_creation_src);
579 }
580
581 static void
582 init_connman_manager (GUPnPConnmanManager *manager)
583 {
584         GUPnPConnmanManagerPrivate *priv;
585         GError                     *error = NULL;
586         GDBusConnection            *connection;
587
588         priv = manager->priv;
589
590         priv->manager_proxy = g_dbus_proxy_new_for_bus_sync (
591                                 G_BUS_TYPE_SYSTEM,
592                                 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
593                                 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
594                                 NULL,
595                                 CM_DBUS_CONNMAN_NAME,
596                                 CM_DBUS_MANAGER_PATH,
597                                 CM_DBUS_MANAGER_INTERFACE,
598                                 NULL,
599                                 &error);
600
601         if (error != NULL) {
602                 g_warning ("Failed to connect to Connman: %s", error->message);
603                 g_error_free (error);
604
605                 return;
606         }
607
608         connection = g_dbus_proxy_get_connection (priv->manager_proxy);
609
610         if (connection == NULL) {
611                 g_warning ("Failed to get DBus Connection");
612                 g_object_unref (priv->manager_proxy);
613                 priv->manager_proxy = NULL;
614
615                 return;
616         }
617
618         g_dbus_proxy_call (priv->manager_proxy,
619                            "GetServices",
620                            NULL,
621                            G_DBUS_CALL_FLAGS_NONE,
622                            -1,
623                            NULL,
624                            get_services_cb,
625                            manager);
626
627         priv->sig_change_id = g_dbus_connection_signal_subscribe (
628                                                 connection,
629                                                 CM_DBUS_CONNMAN_NAME,
630                                                 CM_DBUS_MANAGER_INTERFACE,
631                                                 "ServicesChanged",
632                                                 CM_DBUS_MANAGER_PATH,
633                                                 NULL,
634                                                 G_DBUS_SIGNAL_FLAGS_NONE,
635                                                 on_manager_svc_changed_signal,
636                                                 manager,
637                                                 NULL);
638 }
639
640 static void
641 gupnp_connman_manager_dispose (GObject *object)
642 {
643         GUPnPConnmanManager        *manager;
644         GUPnPConnmanManagerPrivate *priv;
645         GObjectClass               *object_class;
646         GDBusConnection            *cnx;
647
648         manager = GUPNP_CONNMAN_MANAGER (object);
649         priv = manager->priv;
650         cnx = g_dbus_proxy_get_connection (priv->manager_proxy);
651
652         if (priv->sig_change_id) {
653                 g_dbus_connection_signal_unsubscribe (cnx, priv->sig_change_id);
654                 priv->sig_change_id = 0;
655         }
656
657         if (priv->idle_context_creation_src) {
658                 g_source_destroy (priv->idle_context_creation_src);
659                 priv->idle_context_creation_src = NULL;
660         }
661
662         if (priv->manager_proxy != NULL) {
663                 g_object_unref (priv->manager_proxy);
664                 priv->manager_proxy = NULL;
665         }
666
667         if (priv->cm_services) {
668                 g_hash_table_destroy (priv->cm_services);
669                 priv->cm_services = NULL;
670         }
671
672         g_clear_object (&(priv->system_bus));
673
674         /* Call super */
675         object_class = G_OBJECT_CLASS (gupnp_connman_manager_parent_class);
676         object_class->dispose (object);
677 }
678
679 static void
680 gupnp_connman_manager_constructed (GObject *object)
681 {
682         GUPnPConnmanManager *manager;
683         GObjectClass        *object_class;
684
685         manager = GUPNP_CONNMAN_MANAGER (object);
686
687         manager->priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
688                                                     NULL,
689                                                     NULL);
690
691         init_connman_manager (manager);
692
693         schedule_loopback_context_creation (manager);
694
695         /* Call super */
696         object_class = G_OBJECT_CLASS (gupnp_connman_manager_parent_class);
697
698         if (object_class->constructed != NULL) {
699                 object_class->constructed (object);
700         }
701 }
702
703 static void
704 gupnp_connman_manager_init (GUPnPConnmanManager *manager)
705 {
706         manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (
707                                                 manager,
708                                                 GUPNP_TYPE_CONNMAN_MANAGER,
709                                                 GUPnPConnmanManagerPrivate);
710
711         manager->priv->cm_services = g_hash_table_new_full (
712                                         g_str_hash,
713                                         g_str_equal,
714                                         (GDestroyNotify) g_free,
715                                         (GDestroyNotify) cm_service_free);
716 }
717
718 static void
719 gupnp_connman_manager_class_init (GUPnPConnmanManagerClass *klass)
720 {
721         GObjectClass *object_class;
722
723         object_class = G_OBJECT_CLASS (klass);
724
725         object_class->constructed  = gupnp_connman_manager_constructed;
726         object_class->dispose      = gupnp_connman_manager_dispose;
727
728         g_type_class_add_private (klass, sizeof (GUPnPConnmanManagerPrivate));
729 }
730
731 gboolean
732 gupnp_connman_manager_is_available (void)
733 {
734         GDBusProxy *dbus_proxy;
735         GVariant   *ret_values;
736         GError     *error = NULL;
737         gboolean   ret = FALSE;
738
739         dbus_proxy = g_dbus_proxy_new_for_bus_sync (
740                         G_BUS_TYPE_SYSTEM,
741                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
742                         NULL,
743                         DBUS_SERVICE_DBUS,
744                         DBUS_PATH_DBUS,
745                         DBUS_INTERFACE_DBUS,
746                         NULL,
747                         &error);
748
749
750         if (error != NULL) {
751                 g_warning ("Failed to connect to Connman: %s", error->message);
752                 g_error_free (error);
753
754                 return ret;
755         }
756
757         ret_values = g_dbus_proxy_call_sync (
758                                 dbus_proxy,
759                                 "NameHasOwner",
760                                 g_variant_new ("(s)", CM_DBUS_CONNMAN_NAME),
761                                 G_DBUS_CALL_FLAGS_NONE,
762                                 -1,
763                                 NULL,
764                                 &error);
765
766         if (error != NULL) {
767                 g_warning ("%s.NameHasOwner() failed: %s",
768                            DBUS_INTERFACE_DBUS,
769                            error->message);
770
771                 g_error_free (error);
772
773         } else {
774                 g_variant_get_child (ret_values, 0, "b", &ret);
775                 g_variant_unref (ret_values);
776         }
777
778         g_object_unref (dbus_proxy);
779
780         return ret;
781 }