1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 * Author: David Zeuthen <davidz@redhat.com>
25 #include "gdbusobjectmanager.h"
26 #include "gdbusobjectmanagerserver.h"
27 #include "gdbusobject.h"
28 #include "gdbusobjectskeleton.h"
29 #include "gdbusinterfaceskeleton.h"
30 #include "gdbusconnection.h"
31 #include "gdbusintrospection.h"
32 #include "gdbusmethodinvocation.h"
33 #include "gdbuserror.h"
40 * SECTION:gdbusobjectmanagerserver
41 * @short_description: Service-side object manager
44 * #GDBusObjectManagerServer is used to export #GDBusObject instances using
46 * [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
47 * interface. For example, remote D-Bus clients can get all objects
48 * and properties in a single call. Additionally, any change in the
49 * object hierarchy is broadcast using signals. This means that D-Bus
50 * clients can keep caches up to date by only listening to D-Bus
53 * The recommended path to export an object manager at is the path form of the
54 * well-known name of a D-Bus service, or below. For example, if a D-Bus service
55 * is available at the well-known name `net.example.ExampleService1`, the object
56 * manager should typically be exported at `/net/example/ExampleService1`, or
57 * below (to allow for multiple object managers in a service).
59 * It is supported, but not recommended, to export an object manager at the root
62 * See #GDBusObjectManagerClient for the client-side code that is
63 * intended to be used with #GDBusObjectManagerServer or any D-Bus
64 * object implementing the org.freedesktop.DBus.ObjectManager
70 GDBusObjectSkeleton *object;
71 GDBusObjectManagerServer *manager;
72 GHashTable *map_iface_name_to_iface;
76 static void registration_data_free (RegistrationData *data);
78 static void export_all (GDBusObjectManagerServer *manager);
79 static void unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager);
81 static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
82 RegistrationData *data,
83 const gchar *const *interfaces,
84 const gchar *object_path);
86 static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
87 RegistrationData *data,
88 const gchar *const *interfaces);
90 static gboolean g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
91 const gchar *object_path);
93 struct _GDBusObjectManagerServerPrivate
96 GDBusConnection *connection;
98 gchar *object_path_ending_in_slash;
99 GHashTable *map_object_path_to_data;
100 guint manager_reg_id;
110 static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
112 G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer, g_dbus_object_manager_server, G_TYPE_OBJECT,
113 G_ADD_PRIVATE (GDBusObjectManagerServer)
114 G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init))
116 static void g_dbus_object_manager_server_constructed (GObject *object);
119 g_dbus_object_manager_server_finalize (GObject *object)
121 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
123 if (manager->priv->connection != NULL)
125 unexport_all (manager, TRUE);
126 g_object_unref (manager->priv->connection);
128 g_hash_table_unref (manager->priv->map_object_path_to_data);
129 g_free (manager->priv->object_path);
130 g_free (manager->priv->object_path_ending_in_slash);
132 g_mutex_clear (&manager->priv->lock);
134 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize != NULL)
135 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize (object);
139 g_dbus_object_manager_server_get_property (GObject *object,
144 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
148 case PROP_CONNECTION:
149 g_mutex_lock (&manager->priv->lock);
150 g_value_set_object (value, manager->priv->connection);
151 g_mutex_unlock (&manager->priv->lock);
154 case PROP_OBJECT_PATH:
155 g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
159 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
165 g_dbus_object_manager_server_set_property (GObject *object,
170 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
174 case PROP_CONNECTION:
175 g_dbus_object_manager_server_set_connection (manager, g_value_get_object (value));
178 case PROP_OBJECT_PATH:
179 g_assert (manager->priv->object_path == NULL);
180 g_assert (g_variant_is_object_path (g_value_get_string (value)));
181 manager->priv->object_path = g_value_dup_string (value);
182 if (g_str_equal (manager->priv->object_path, "/"))
183 manager->priv->object_path_ending_in_slash = g_strdup (manager->priv->object_path);
185 manager->priv->object_path_ending_in_slash = g_strdup_printf ("%s/", manager->priv->object_path);
189 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
195 g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass *klass)
197 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
199 gobject_class->finalize = g_dbus_object_manager_server_finalize;
200 gobject_class->constructed = g_dbus_object_manager_server_constructed;
201 gobject_class->set_property = g_dbus_object_manager_server_set_property;
202 gobject_class->get_property = g_dbus_object_manager_server_get_property;
205 * GDBusObjectManagerServer:connection:
207 * The #GDBusConnection to export objects on.
211 g_object_class_install_property (gobject_class,
213 g_param_spec_object ("connection",
215 "The connection to export objects on",
216 G_TYPE_DBUS_CONNECTION,
219 G_PARAM_STATIC_STRINGS));
222 * GDBusObjectManagerServer:object-path:
224 * The object path to register the manager object at.
228 g_object_class_install_property (gobject_class,
230 g_param_spec_string ("object-path",
232 "The object path to register the manager object at",
236 G_PARAM_CONSTRUCT_ONLY |
237 G_PARAM_STATIC_STRINGS));
241 g_dbus_object_manager_server_init (GDBusObjectManagerServer *manager)
243 manager->priv = g_dbus_object_manager_server_get_instance_private (manager);
244 g_mutex_init (&manager->priv->lock);
245 manager->priv->map_object_path_to_data = g_hash_table_new_full (g_str_hash,
248 (GDestroyNotify) registration_data_free);
252 * g_dbus_object_manager_server_new:
253 * @object_path: The object path to export the manager object at.
255 * Creates a new #GDBusObjectManagerServer object.
257 * The returned server isn't yet exported on any connection. To do so,
258 * use g_dbus_object_manager_server_set_connection(). Normally you
259 * want to export all of your objects before doing so to avoid
260 * [InterfacesAdded](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
261 * signals being emitted.
263 * Returns: A #GDBusObjectManagerServer object. Free with g_object_unref().
267 GDBusObjectManagerServer *
268 g_dbus_object_manager_server_new (const gchar *object_path)
270 g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
271 return G_DBUS_OBJECT_MANAGER_SERVER (g_object_new (G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
272 "object-path", object_path,
277 * g_dbus_object_manager_server_set_connection:
278 * @manager: A #GDBusObjectManagerServer.
279 * @connection: (nullable): A #GDBusConnection or %NULL.
281 * Exports all objects managed by @manager on @connection. If
282 * @connection is %NULL, stops exporting objects.
285 g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager,
286 GDBusConnection *connection)
288 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
289 g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
291 g_mutex_lock (&manager->priv->lock);
293 if (manager->priv->connection == connection)
295 g_mutex_unlock (&manager->priv->lock);
299 if (manager->priv->connection != NULL)
301 unexport_all (manager, FALSE);
302 g_object_unref (manager->priv->connection);
303 manager->priv->connection = NULL;
306 manager->priv->connection = connection != NULL ? g_object_ref (connection) : NULL;
307 if (manager->priv->connection != NULL)
308 export_all (manager);
310 g_mutex_unlock (&manager->priv->lock);
312 g_object_notify (G_OBJECT (manager), "connection");
318 * g_dbus_object_manager_server_get_connection:
319 * @manager: A #GDBusObjectManagerServer
321 * Gets the #GDBusConnection used by @manager.
323 * Returns: (transfer full) (nullable): A #GDBusConnection object or %NULL if
324 * @manager isn't exported on a connection. The returned object should
325 * be freed with g_object_unref().
330 g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer *manager)
332 GDBusConnection *ret;
333 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), NULL);
334 g_mutex_lock (&manager->priv->lock);
335 ret = manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL;
336 g_mutex_unlock (&manager->priv->lock);
340 /* ---------------------------------------------------------------------------------------------------- */
343 registration_data_export_interface (RegistrationData *data,
344 GDBusInterfaceSkeleton *interface_skeleton,
345 const gchar *object_path)
347 GDBusInterfaceInfo *info;
350 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
352 if (data->manager->priv->connection != NULL)
354 if (!g_dbus_interface_skeleton_export (interface_skeleton,
355 data->manager->priv->connection,
359 g_warning ("%s: Error registering object at %s with interface %s: %s",
364 g_error_free (error);
368 g_assert (g_hash_table_lookup (data->map_iface_name_to_iface, info->name) == NULL);
369 g_hash_table_insert (data->map_iface_name_to_iface,
371 g_object_ref (interface_skeleton));
373 /* if we are already exported, then... */
376 const gchar *interfaces[2];
377 /* emit InterfacesAdded on the ObjectManager object */
378 interfaces[0] = info->name;
379 interfaces[1] = NULL;
380 g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces, object_path);
385 registration_data_unexport_interface (RegistrationData *data,
386 GDBusInterfaceSkeleton *interface_skeleton)
388 GDBusInterfaceInfo *info;
389 GDBusInterfaceSkeleton *iface;
391 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
392 iface = g_hash_table_lookup (data->map_iface_name_to_iface, info->name);
393 g_assert (iface != NULL);
395 if (data->manager->priv->connection != NULL)
396 g_dbus_interface_skeleton_unexport (iface);
398 g_warn_if_fail (g_hash_table_remove (data->map_iface_name_to_iface, info->name));
400 /* if we are already exported, then... */
403 const gchar *interfaces[2];
404 /* emit InterfacesRemoved on the ObjectManager object */
405 interfaces[0] = info->name;
406 interfaces[1] = NULL;
407 g_dbus_object_manager_server_emit_interfaces_removed (data->manager, data, interfaces);
411 /* ---------------------------------------------------------------------------------------------------- */
414 on_interface_added (GDBusObject *object,
415 GDBusInterface *interface,
418 RegistrationData *data = user_data;
419 const gchar *object_path;
420 g_mutex_lock (&data->manager->priv->lock);
421 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
422 registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface), object_path);
423 g_mutex_unlock (&data->manager->priv->lock);
427 on_interface_removed (GDBusObject *object,
428 GDBusInterface *interface,
431 RegistrationData *data = user_data;
432 g_mutex_lock (&data->manager->priv->lock);
433 registration_data_unexport_interface (data, G_DBUS_INTERFACE_SKELETON (interface));
434 g_mutex_unlock (&data->manager->priv->lock);
437 /* ---------------------------------------------------------------------------------------------------- */
441 registration_data_free (RegistrationData *data)
444 GDBusInterfaceSkeleton *iface;
446 data->exported = FALSE;
448 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
449 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &iface))
451 if (data->manager->priv->connection != NULL)
452 g_dbus_interface_skeleton_unexport (iface);
455 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_added), data);
456 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_removed), data);
457 g_object_unref (data->object);
458 g_hash_table_destroy (data->map_iface_name_to_iface);
462 /* Validate whether an object path is valid as a child of the manager. According
463 * to the specification:
464 * https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
466 * > All returned object paths are children of the object path implementing this
467 * > interface, i.e. their object paths start with the ObjectManager's object
470 * For example, if the manager is at `/org/gnome/Example`, children will be
471 * `/org/gnome/Example/(.+)`.
473 * It is permissible (but not encouraged) for the manager to be at `/`. If so,
474 * children will be `/(.+)`.
477 is_valid_child_object_path (GDBusObjectManagerServer *manager,
478 const gchar *child_object_path)
480 /* Historically GDBus accepted @child_object_paths at `/` if the @manager
481 * itself is also at `/". This is not spec-compliant, but making GDBus enforce
482 * the spec more strictly would be an incompatible change.
484 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2500 */
485 g_warn_if_fail (!g_str_equal (child_object_path, manager->priv->object_path_ending_in_slash));
487 return g_str_has_prefix (child_object_path, manager->priv->object_path_ending_in_slash);
490 /* ---------------------------------------------------------------------------------------------------- */
493 g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer *manager,
494 GDBusObjectSkeleton *object,
495 const gchar *object_path)
497 RegistrationData *data;
498 GList *existing_interfaces;
500 GPtrArray *interface_names;
502 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
503 g_return_if_fail (G_IS_DBUS_OBJECT (object));
504 g_return_if_fail (is_valid_child_object_path (manager, object_path));
506 interface_names = g_ptr_array_new ();
508 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
510 g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
512 data = g_new0 (RegistrationData, 1);
513 data->object = g_object_ref (object);
514 data->manager = manager;
515 data->map_iface_name_to_iface = g_hash_table_new_full (g_str_hash,
518 (GDestroyNotify) g_object_unref);
520 g_signal_connect (object,
522 G_CALLBACK (on_interface_added),
524 g_signal_connect (object,
526 G_CALLBACK (on_interface_removed),
529 /* Register all known interfaces - note that data->exported is FALSE so
530 * we don't emit any InterfacesAdded signals.
532 existing_interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
533 for (l = existing_interfaces; l != NULL; l = l->next)
535 GDBusInterfaceSkeleton *interface_skeleton = G_DBUS_INTERFACE_SKELETON (l->data);
536 registration_data_export_interface (data, interface_skeleton, object_path);
537 g_ptr_array_add (interface_names, g_dbus_interface_skeleton_get_info (interface_skeleton)->name);
539 g_list_free_full (existing_interfaces, g_object_unref);
540 g_ptr_array_add (interface_names, NULL);
542 data->exported = TRUE;
544 /* now emit InterfacesAdded() for all the interfaces */
545 g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata, object_path);
546 g_ptr_array_unref (interface_names);
548 g_hash_table_insert (manager->priv->map_object_path_to_data,
549 g_strdup (object_path),
554 * g_dbus_object_manager_server_export:
555 * @manager: A #GDBusObjectManagerServer.
556 * @object: A #GDBusObjectSkeleton.
558 * Exports @object on @manager.
560 * If there is already a #GDBusObject exported at the object path,
561 * then the old object is removed.
563 * The object path for @object must be in the hierarchy rooted by the
564 * object path for @manager.
566 * Note that @manager will take a reference on @object for as long as
572 g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager,
573 GDBusObjectSkeleton *object)
575 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
576 g_mutex_lock (&manager->priv->lock);
577 g_dbus_object_manager_server_export_unlocked (manager, object,
578 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
579 g_mutex_unlock (&manager->priv->lock);
583 * g_dbus_object_manager_server_export_uniquely:
584 * @manager: A #GDBusObjectManagerServer.
585 * @object: An object.
587 * Like g_dbus_object_manager_server_export() but appends a string of
588 * the form _N (with N being a natural number) to @object's object path
589 * if an object with the given path already exists. As such, the
590 * #GDBusObjectProxy:g-object-path property of @object may be modified.
595 g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager,
596 GDBusObjectSkeleton *object)
598 const gchar *orig_object_path;
603 orig_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
605 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
606 g_return_if_fail (G_IS_DBUS_OBJECT (object));
607 g_return_if_fail (is_valid_child_object_path (manager, orig_object_path));
609 g_mutex_lock (&manager->priv->lock);
611 object_path = g_strdup (orig_object_path);
616 RegistrationData *data;
617 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
622 g_free (object_path);
623 object_path = g_strdup_printf ("%s_%d", orig_object_path, count++);
627 g_dbus_object_manager_server_export_unlocked (manager, object, object_path);
629 g_mutex_unlock (&manager->priv->lock);
632 g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path);
634 g_free (object_path);
639 * g_dbus_object_manager_server_is_exported:
640 * @manager: A #GDBusObjectManagerServer.
641 * @object: An object.
643 * Returns whether @object is currently exported on @manager.
645 * Returns: %TRUE if @object is exported
650 g_dbus_object_manager_server_is_exported (GDBusObjectManagerServer *manager,
651 GDBusObjectSkeleton *object)
653 RegistrationData *data = NULL;
654 const gchar *object_path;
655 gboolean object_is_exported;
657 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
658 g_return_val_if_fail (G_IS_DBUS_OBJECT (object), FALSE);
660 g_mutex_lock (&manager->priv->lock);
662 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
663 if (object_path != NULL)
664 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
665 object_is_exported = (data != NULL);
667 g_mutex_unlock (&manager->priv->lock);
669 return object_is_exported;
672 /* ---------------------------------------------------------------------------------------------------- */
675 g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
676 const gchar *object_path)
678 RegistrationData *data;
681 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
682 g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
683 g_return_val_if_fail (is_valid_child_object_path (manager, object_path), FALSE);
687 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
690 GPtrArray *interface_names;
692 const gchar *iface_name;
694 interface_names = g_ptr_array_new ();
695 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
696 while (g_hash_table_iter_next (&iter, (gpointer) &iface_name, NULL))
697 g_ptr_array_add (interface_names, (gpointer) iface_name);
698 g_ptr_array_add (interface_names, NULL);
699 /* now emit InterfacesRemoved() for all the interfaces */
700 g_dbus_object_manager_server_emit_interfaces_removed (manager, data, (const gchar *const *) interface_names->pdata);
701 g_ptr_array_unref (interface_names);
703 g_hash_table_remove (manager->priv->map_object_path_to_data, object_path);
711 * g_dbus_object_manager_server_unexport:
712 * @manager: A #GDBusObjectManagerServer.
713 * @object_path: An object path.
715 * If @manager has an object at @path, removes the object. Otherwise
718 * Note that @object_path must be in the hierarchy rooted by the
719 * object path for @manager.
721 * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
726 g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager,
727 const gchar *object_path)
730 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
731 g_mutex_lock (&manager->priv->lock);
732 ret = g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
733 g_mutex_unlock (&manager->priv->lock);
738 /* ---------------------------------------------------------------------------------------------------- */
740 static const GDBusArgInfo manager_interfaces_added_signal_info_arg0 =
745 (GDBusAnnotationInfo**) NULL,
748 static const GDBusArgInfo manager_interfaces_added_signal_info_arg1 =
751 "interfaces_and_properties",
753 (GDBusAnnotationInfo**) NULL,
756 static const GDBusArgInfo * const manager_interfaces_added_signal_info_arg_pointers[] =
758 &manager_interfaces_added_signal_info_arg0,
759 &manager_interfaces_added_signal_info_arg1,
763 static const GDBusSignalInfo manager_interfaces_added_signal_info =
767 (GDBusArgInfo**) &manager_interfaces_added_signal_info_arg_pointers,
768 (GDBusAnnotationInfo**) NULL
773 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0 =
778 (GDBusAnnotationInfo**) NULL,
781 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1 =
786 (GDBusAnnotationInfo**) NULL,
789 static const GDBusArgInfo * const manager_interfaces_removed_signal_info_arg_pointers[] =
791 &manager_interfaces_removed_signal_info_arg0,
792 &manager_interfaces_removed_signal_info_arg1,
796 static const GDBusSignalInfo manager_interfaces_removed_signal_info =
800 (GDBusArgInfo**) &manager_interfaces_removed_signal_info_arg_pointers,
801 (GDBusAnnotationInfo**) NULL
806 static const GDBusSignalInfo * const manager_signal_info_pointers[] =
808 &manager_interfaces_added_signal_info,
809 &manager_interfaces_removed_signal_info,
815 static const GDBusArgInfo manager_get_all_method_info_out_arg0 =
818 "object_paths_interfaces_and_properties",
820 (GDBusAnnotationInfo**) NULL,
823 static const GDBusArgInfo * const manager_get_all_method_info_out_arg_pointers[] =
825 &manager_get_all_method_info_out_arg0,
829 static const GDBusMethodInfo manager_get_all_method_info =
833 (GDBusArgInfo**) NULL,
834 (GDBusArgInfo**) &manager_get_all_method_info_out_arg_pointers,
835 (GDBusAnnotationInfo**) NULL
838 static const GDBusMethodInfo * const manager_method_info_pointers[] =
840 &manager_get_all_method_info,
846 static const GDBusInterfaceInfo manager_interface_info =
849 "org.freedesktop.DBus.ObjectManager",
850 (GDBusMethodInfo **) manager_method_info_pointers,
851 (GDBusSignalInfo **) manager_signal_info_pointers,
852 (GDBusPropertyInfo **) NULL,
853 (GDBusAnnotationInfo **) NULL
857 manager_method_call (GDBusConnection *connection,
859 const gchar *object_path,
860 const gchar *interface_name,
861 const gchar *method_name,
862 GVariant *parameters,
863 GDBusMethodInvocation *invocation,
866 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (user_data);
867 GVariantBuilder array_builder;
868 GHashTableIter object_iter;
869 RegistrationData *data;
871 g_mutex_lock (&manager->priv->lock);
873 if (g_strcmp0 (method_name, "GetManagedObjects") == 0)
875 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
876 g_hash_table_iter_init (&object_iter, manager->priv->map_object_path_to_data);
877 while (g_hash_table_iter_next (&object_iter, NULL, (gpointer) &data))
879 GVariantBuilder interfaces_builder;
880 GHashTableIter interface_iter;
881 GDBusInterfaceSkeleton *iface;
882 const gchar *iter_object_path;
884 g_variant_builder_init (&interfaces_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
885 g_hash_table_iter_init (&interface_iter, data->map_iface_name_to_iface);
886 while (g_hash_table_iter_next (&interface_iter, NULL, (gpointer) &iface))
888 GVariant *properties = g_dbus_interface_skeleton_get_properties (iface);
889 g_variant_builder_add (&interfaces_builder, "{s@a{sv}}",
890 g_dbus_interface_skeleton_get_info (iface)->name,
892 g_variant_unref (properties);
894 iter_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
895 g_variant_builder_add (&array_builder,
898 &interfaces_builder);
901 g_dbus_method_invocation_return_value (invocation,
902 g_variant_new ("(a{oa{sa{sv}}})",
907 g_dbus_method_invocation_return_error (invocation,
909 G_DBUS_ERROR_UNKNOWN_METHOD,
910 "Unknown method %s - only GetManagedObjects() is supported",
913 g_mutex_unlock (&manager->priv->lock);
916 static const GDBusInterfaceVTable manager_interface_vtable =
918 manager_method_call, /* handle_method_call */
919 NULL, /* get_property */
920 NULL, /* set_property */
924 /* ---------------------------------------------------------------------------------------------------- */
927 g_dbus_object_manager_server_constructed (GObject *object)
929 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
931 if (manager->priv->connection != NULL)
932 export_all (manager);
934 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed != NULL)
935 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed (object);
939 g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
940 RegistrationData *data,
941 const gchar *const *interfaces,
942 const gchar *object_path)
944 GVariantBuilder array_builder;
948 if (data->manager->priv->connection == NULL)
951 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
952 for (n = 0; interfaces[n] != NULL; n++)
954 GDBusInterfaceSkeleton *iface;
955 GVariant *properties;
957 iface = g_hash_table_lookup (data->map_iface_name_to_iface, interfaces[n]);
958 g_assert (iface != NULL);
959 properties = g_dbus_interface_skeleton_get_properties (iface);
960 g_variant_builder_add (&array_builder, "{s@a{sv}}", interfaces[n], properties);
961 g_variant_unref (properties);
965 g_dbus_connection_emit_signal (data->manager->priv->connection,
966 NULL, /* destination_bus_name */
967 manager->priv->object_path,
968 manager_interface_info.name,
970 g_variant_new ("(oa{sa{sv}})",
976 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
977 g_warning ("Couldn't emit InterfacesAdded signal: %s", error->message);
978 g_error_free (error);
985 g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
986 RegistrationData *data,
987 const gchar *const *interfaces)
989 GVariantBuilder array_builder;
992 const gchar *object_path;
994 if (data->manager->priv->connection == NULL)
997 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
998 for (n = 0; interfaces[n] != NULL; n++)
999 g_variant_builder_add (&array_builder, "s", interfaces[n]);
1002 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
1003 g_dbus_connection_emit_signal (data->manager->priv->connection,
1004 NULL, /* destination_bus_name */
1005 manager->priv->object_path,
1006 manager_interface_info.name,
1007 "InterfacesRemoved",
1008 g_variant_new ("(oas)",
1014 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
1015 g_warning ("Couldn't emit InterfacesRemoved signal: %s", error->message);
1016 g_error_free (error);
1022 /* ---------------------------------------------------------------------------------------------------- */
1025 g_dbus_object_manager_server_get_objects (GDBusObjectManager *_manager)
1027 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1029 GHashTableIter iter;
1030 RegistrationData *data;
1032 g_mutex_lock (&manager->priv->lock);
1035 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1036 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1038 ret = g_list_prepend (ret, g_object_ref (data->object));
1041 g_mutex_unlock (&manager->priv->lock);
1046 static const gchar *
1047 g_dbus_object_manager_server_get_object_path (GDBusObjectManager *_manager)
1049 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1050 return manager->priv->object_path;
1053 static GDBusObject *
1054 g_dbus_object_manager_server_get_object (GDBusObjectManager *_manager,
1055 const gchar *object_path)
1057 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1059 RegistrationData *data;
1063 g_mutex_lock (&manager->priv->lock);
1064 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
1066 ret = g_object_ref (G_DBUS_OBJECT (data->object));
1067 g_mutex_unlock (&manager->priv->lock);
1072 static GDBusInterface *
1073 g_dbus_object_manager_server_get_interface (GDBusObjectManager *_manager,
1074 const gchar *object_path,
1075 const gchar *interface_name)
1077 GDBusInterface *ret;
1078 GDBusObject *object;
1082 object = g_dbus_object_manager_get_object (_manager, object_path);
1086 ret = g_dbus_object_get_interface (object, interface_name);
1087 g_object_unref (object);
1094 dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
1096 iface->get_object_path = g_dbus_object_manager_server_get_object_path;
1097 iface->get_objects = g_dbus_object_manager_server_get_objects;
1098 iface->get_object = g_dbus_object_manager_server_get_object;
1099 iface->get_interface = g_dbus_object_manager_server_get_interface;
1102 /* ---------------------------------------------------------------------------------------------------- */
1105 export_all (GDBusObjectManagerServer *manager)
1107 GHashTableIter iter;
1108 const gchar *object_path;
1109 RegistrationData *data;
1110 GHashTableIter iface_iter;
1111 GDBusInterfaceSkeleton *iface;
1114 g_return_if_fail (manager->priv->connection != NULL);
1117 g_warn_if_fail (manager->priv->manager_reg_id == 0);
1118 manager->priv->manager_reg_id = g_dbus_connection_register_object (manager->priv->connection,
1119 manager->priv->object_path,
1120 (GDBusInterfaceInfo *) &manager_interface_info,
1121 &manager_interface_vtable,
1123 NULL, /* user_data_free_func */
1125 if (manager->priv->manager_reg_id == 0)
1127 g_warning ("%s: Error registering manager at %s: %s",
1129 manager->priv->object_path,
1131 g_error_free (error);
1134 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1135 while (g_hash_table_iter_next (&iter, (gpointer) &object_path, (gpointer) &data))
1137 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1138 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1140 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) == NULL);
1142 if (!g_dbus_interface_skeleton_export (iface,
1143 manager->priv->connection,
1147 g_warning ("%s: Error registering object at %s with interface %s: %s",
1150 g_dbus_interface_skeleton_get_info (iface)->name,
1152 g_error_free (error);
1159 unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager)
1161 GHashTableIter iter;
1162 RegistrationData *data;
1163 GHashTableIter iface_iter;
1164 GDBusInterfaceSkeleton *iface;
1166 g_return_if_fail (manager->priv->connection != NULL);
1168 g_warn_if_fail (manager->priv->manager_reg_id > 0);
1169 if (manager->priv->manager_reg_id > 0)
1171 g_warn_if_fail (g_dbus_connection_unregister_object (manager->priv->connection,
1172 manager->priv->manager_reg_id));
1173 manager->priv->manager_reg_id = 0;
1178 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1179 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1181 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1182 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1184 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) != NULL);
1185 g_dbus_interface_skeleton_unexport (iface);
1192 /* ---------------------------------------------------------------------------------------------------- */