Branch data Line data Source code
1 : : /* GDBus - GLib D-Bus Library
2 : : *
3 : : * Copyright (C) 2008-2010 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
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.
11 : : *
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.
16 : : *
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/>.
19 : : *
20 : : * Author: David Zeuthen <davidz@redhat.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
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"
34 : :
35 : : #include "gioerror.h"
36 : :
37 : : #include "gdbusprivate.h"
38 : :
39 : : #include "glibintl.h"
40 : :
41 : : /**
42 : : * GDBusObjectManagerServer:
43 : : *
44 : : * `GDBusObjectManagerServer` is used to export [iface@Gio.DBusObject] instances
45 : : * using the standardized
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
51 : : * signals.
52 : : *
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).
58 : : *
59 : : * It is supported, but not recommended, to export an object manager at the root
60 : : * path, `/`.
61 : : *
62 : : * See [class@Gio.DBusObjectManagerClient] 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` interface.
65 : : *
66 : : * Since: 2.30
67 : : */
68 : :
69 : : typedef struct
70 : : {
71 : : GDBusObjectSkeleton *object;
72 : : GDBusObjectManagerServer *manager;
73 : : GHashTable *map_iface_name_to_iface;
74 : : gboolean exported;
75 : : } RegistrationData;
76 : :
77 : : static void registration_data_free (RegistrationData *data);
78 : :
79 : : static void export_all (GDBusObjectManagerServer *manager);
80 : : static void unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager);
81 : :
82 : : static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
83 : : RegistrationData *data,
84 : : const gchar *const *interfaces,
85 : : const gchar *object_path);
86 : :
87 : : static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
88 : : RegistrationData *data,
89 : : const gchar *const *interfaces);
90 : :
91 : : static gboolean g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
92 : : const gchar *object_path);
93 : :
94 : : struct _GDBusObjectManagerServerPrivate
95 : : {
96 : : GMutex lock;
97 : : GDBusConnection *connection;
98 : : gchar *object_path;
99 : : gchar *object_path_ending_in_slash;
100 : : GHashTable *map_object_path_to_data;
101 : : guint manager_reg_id;
102 : : };
103 : :
104 : : enum
105 : : {
106 : : PROP_0,
107 : : PROP_CONNECTION,
108 : : PROP_OBJECT_PATH
109 : : };
110 : :
111 : : static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
112 : :
113 : 294 : G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer, g_dbus_object_manager_server, G_TYPE_OBJECT,
114 : : G_ADD_PRIVATE (GDBusObjectManagerServer)
115 : : G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init))
116 : :
117 : : static void g_dbus_object_manager_server_constructed (GObject *object);
118 : :
119 : : static void
120 : 5 : g_dbus_object_manager_server_finalize (GObject *object)
121 : : {
122 : 5 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
123 : :
124 : 5 : if (manager->priv->connection != NULL)
125 : : {
126 : 5 : unexport_all (manager, TRUE);
127 : 5 : g_object_unref (manager->priv->connection);
128 : : }
129 : 5 : g_hash_table_unref (manager->priv->map_object_path_to_data);
130 : 5 : g_free (manager->priv->object_path);
131 : 5 : g_free (manager->priv->object_path_ending_in_slash);
132 : :
133 : 5 : g_mutex_clear (&manager->priv->lock);
134 : :
135 : 5 : if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize != NULL)
136 : 5 : G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize (object);
137 : 5 : }
138 : :
139 : : static void
140 : 6 : g_dbus_object_manager_server_get_property (GObject *object,
141 : : guint prop_id,
142 : : GValue *value,
143 : : GParamSpec *pspec)
144 : : {
145 : 6 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
146 : :
147 : 6 : switch (prop_id)
148 : : {
149 : 3 : case PROP_CONNECTION:
150 : 3 : g_mutex_lock (&manager->priv->lock);
151 : 3 : g_value_set_object (value, manager->priv->connection);
152 : 3 : g_mutex_unlock (&manager->priv->lock);
153 : 3 : break;
154 : :
155 : 3 : case PROP_OBJECT_PATH:
156 : 3 : g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
157 : 3 : break;
158 : :
159 : 0 : default:
160 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
161 : 0 : break;
162 : : }
163 : 6 : }
164 : :
165 : : static void
166 : 5 : g_dbus_object_manager_server_set_property (GObject *object,
167 : : guint prop_id,
168 : : const GValue *value,
169 : : GParamSpec *pspec)
170 : : {
171 : 5 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
172 : :
173 : 5 : switch (prop_id)
174 : : {
175 : 0 : case PROP_CONNECTION:
176 : 0 : g_dbus_object_manager_server_set_connection (manager, g_value_get_object (value));
177 : 0 : break;
178 : :
179 : 5 : case PROP_OBJECT_PATH:
180 : 5 : g_assert (manager->priv->object_path == NULL);
181 : 5 : g_assert (g_variant_is_object_path (g_value_get_string (value)));
182 : 5 : manager->priv->object_path = g_value_dup_string (value);
183 : 5 : if (g_str_equal (manager->priv->object_path, "/"))
184 : 2 : manager->priv->object_path_ending_in_slash = g_strdup (manager->priv->object_path);
185 : : else
186 : 4 : manager->priv->object_path_ending_in_slash = g_strdup_printf ("%s/", manager->priv->object_path);
187 : 5 : break;
188 : :
189 : 0 : default:
190 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191 : 0 : break;
192 : : }
193 : 5 : }
194 : :
195 : : static void
196 : 5 : g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass *klass)
197 : : {
198 : 5 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
199 : :
200 : 5 : gobject_class->finalize = g_dbus_object_manager_server_finalize;
201 : 5 : gobject_class->constructed = g_dbus_object_manager_server_constructed;
202 : 5 : gobject_class->set_property = g_dbus_object_manager_server_set_property;
203 : 5 : gobject_class->get_property = g_dbus_object_manager_server_get_property;
204 : :
205 : : /**
206 : : * GDBusObjectManagerServer:connection:
207 : : *
208 : : * The #GDBusConnection to export objects on.
209 : : *
210 : : * Since: 2.30
211 : : */
212 : 5 : g_object_class_install_property (gobject_class,
213 : : PROP_CONNECTION,
214 : : g_param_spec_object ("connection", NULL, NULL,
215 : : G_TYPE_DBUS_CONNECTION,
216 : : G_PARAM_READABLE |
217 : : G_PARAM_WRITABLE |
218 : : G_PARAM_STATIC_STRINGS));
219 : :
220 : : /**
221 : : * GDBusObjectManagerServer:object-path:
222 : : *
223 : : * The object path to register the manager object at.
224 : : *
225 : : * Since: 2.30
226 : : */
227 : 5 : g_object_class_install_property (gobject_class,
228 : : PROP_OBJECT_PATH,
229 : : g_param_spec_string ("object-path", NULL, NULL,
230 : : NULL,
231 : : G_PARAM_READABLE |
232 : : G_PARAM_WRITABLE |
233 : : G_PARAM_CONSTRUCT_ONLY |
234 : : G_PARAM_STATIC_STRINGS));
235 : 5 : }
236 : :
237 : : static void
238 : 5 : g_dbus_object_manager_server_init (GDBusObjectManagerServer *manager)
239 : : {
240 : 5 : manager->priv = g_dbus_object_manager_server_get_instance_private (manager);
241 : 5 : g_mutex_init (&manager->priv->lock);
242 : 5 : manager->priv->map_object_path_to_data = g_hash_table_new_full (g_str_hash,
243 : : g_str_equal,
244 : : g_free,
245 : : (GDestroyNotify) registration_data_free);
246 : 5 : }
247 : :
248 : : /**
249 : : * g_dbus_object_manager_server_new:
250 : : * @object_path: The object path to export the manager object at.
251 : : *
252 : : * Creates a new #GDBusObjectManagerServer object.
253 : : *
254 : : * The returned server isn't yet exported on any connection. To do so,
255 : : * use g_dbus_object_manager_server_set_connection(). Normally you
256 : : * want to export all of your objects before doing so to avoid
257 : : * [InterfacesAdded](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
258 : : * signals being emitted.
259 : : *
260 : : * Returns: A #GDBusObjectManagerServer object. Free with g_object_unref().
261 : : *
262 : : * Since: 2.30
263 : : */
264 : : GDBusObjectManagerServer *
265 : 5 : g_dbus_object_manager_server_new (const gchar *object_path)
266 : : {
267 : 5 : g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
268 : 5 : return G_DBUS_OBJECT_MANAGER_SERVER (g_object_new (G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
269 : : "object-path", object_path,
270 : : NULL));
271 : : }
272 : :
273 : : /**
274 : : * g_dbus_object_manager_server_set_connection:
275 : : * @manager: A #GDBusObjectManagerServer.
276 : : * @connection: (nullable): A #GDBusConnection or %NULL.
277 : : *
278 : : * Exports all objects managed by @manager on @connection. If
279 : : * @connection is %NULL, stops exporting objects.
280 : : */
281 : : void
282 : 11 : g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager,
283 : : GDBusConnection *connection)
284 : : {
285 : 11 : g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
286 : 11 : g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
287 : :
288 : 11 : g_mutex_lock (&manager->priv->lock);
289 : :
290 : 11 : if (manager->priv->connection == connection)
291 : : {
292 : 0 : g_mutex_unlock (&manager->priv->lock);
293 : 0 : goto out;
294 : : }
295 : :
296 : 11 : if (manager->priv->connection != NULL)
297 : : {
298 : 3 : unexport_all (manager, FALSE);
299 : 3 : g_object_unref (manager->priv->connection);
300 : 3 : manager->priv->connection = NULL;
301 : : }
302 : :
303 : 11 : manager->priv->connection = connection != NULL ? g_object_ref (connection) : NULL;
304 : 11 : if (manager->priv->connection != NULL)
305 : 8 : export_all (manager);
306 : :
307 : 11 : g_mutex_unlock (&manager->priv->lock);
308 : :
309 : 11 : g_object_notify (G_OBJECT (manager), "connection");
310 : 11 : out:
311 : : ;
312 : : }
313 : :
314 : : /**
315 : : * g_dbus_object_manager_server_get_connection:
316 : : * @manager: A #GDBusObjectManagerServer
317 : : *
318 : : * Gets the #GDBusConnection used by @manager.
319 : : *
320 : : * Returns: (transfer full) (nullable): A #GDBusConnection object or %NULL if
321 : : * @manager isn't exported on a connection. The returned object should
322 : : * be freed with g_object_unref().
323 : : *
324 : : * Since: 2.30
325 : : */
326 : : GDBusConnection *
327 : 3 : g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer *manager)
328 : : {
329 : : GDBusConnection *ret;
330 : 3 : g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), NULL);
331 : 3 : g_mutex_lock (&manager->priv->lock);
332 : 3 : ret = manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL;
333 : 3 : g_mutex_unlock (&manager->priv->lock);
334 : 3 : return ret;
335 : : }
336 : :
337 : : /* ---------------------------------------------------------------------------------------------------- */
338 : :
339 : : static void
340 : 28 : registration_data_export_interface (RegistrationData *data,
341 : : GDBusInterfaceSkeleton *interface_skeleton,
342 : : const gchar *object_path)
343 : : {
344 : : GDBusInterfaceInfo *info;
345 : : GError *error;
346 : :
347 : 28 : info = g_dbus_interface_skeleton_get_info (interface_skeleton);
348 : 28 : error = NULL;
349 : 28 : if (data->manager->priv->connection != NULL)
350 : : {
351 : 24 : if (!g_dbus_interface_skeleton_export (interface_skeleton,
352 : 24 : data->manager->priv->connection,
353 : : object_path,
354 : : &error))
355 : : {
356 : 0 : g_warning ("%s: Error registering object at %s with interface %s: %s",
357 : : G_STRLOC,
358 : : object_path,
359 : : info->name,
360 : : error->message);
361 : 0 : g_error_free (error);
362 : : }
363 : : }
364 : :
365 : 28 : g_assert (g_hash_table_lookup (data->map_iface_name_to_iface, info->name) == NULL);
366 : 28 : g_hash_table_insert (data->map_iface_name_to_iface,
367 : 28 : info->name,
368 : : g_object_ref (interface_skeleton));
369 : :
370 : : /* if we are already exported, then... */
371 : 28 : if (data->exported)
372 : : {
373 : : const gchar *interfaces[2];
374 : : /* emit InterfacesAdded on the ObjectManager object */
375 : 12 : interfaces[0] = info->name;
376 : 12 : interfaces[1] = NULL;
377 : 12 : g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces, object_path);
378 : : }
379 : 28 : }
380 : :
381 : : static void
382 : 12 : registration_data_unexport_interface (RegistrationData *data,
383 : : GDBusInterfaceSkeleton *interface_skeleton)
384 : : {
385 : : GDBusInterfaceInfo *info;
386 : : GDBusInterfaceSkeleton *iface;
387 : :
388 : 12 : info = g_dbus_interface_skeleton_get_info (interface_skeleton);
389 : 12 : iface = g_hash_table_lookup (data->map_iface_name_to_iface, info->name);
390 : 12 : g_assert (iface != NULL);
391 : :
392 : 12 : if (data->manager->priv->connection != NULL)
393 : 12 : g_dbus_interface_skeleton_unexport (iface);
394 : :
395 : 12 : g_warn_if_fail (g_hash_table_remove (data->map_iface_name_to_iface, info->name));
396 : :
397 : : /* if we are already exported, then... */
398 : 12 : if (data->exported)
399 : : {
400 : : const gchar *interfaces[2];
401 : : /* emit InterfacesRemoved on the ObjectManager object */
402 : 12 : interfaces[0] = info->name;
403 : 12 : interfaces[1] = NULL;
404 : 12 : g_dbus_object_manager_server_emit_interfaces_removed (data->manager, data, interfaces);
405 : : }
406 : 12 : }
407 : :
408 : : /* ---------------------------------------------------------------------------------------------------- */
409 : :
410 : : static void
411 : 12 : on_interface_added (GDBusObject *object,
412 : : GDBusInterface *interface,
413 : : gpointer user_data)
414 : : {
415 : 12 : RegistrationData *data = user_data;
416 : : const gchar *object_path;
417 : 12 : g_mutex_lock (&data->manager->priv->lock);
418 : 12 : object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
419 : 12 : registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface), object_path);
420 : 12 : g_mutex_unlock (&data->manager->priv->lock);
421 : 12 : }
422 : :
423 : : static void
424 : 12 : on_interface_removed (GDBusObject *object,
425 : : GDBusInterface *interface,
426 : : gpointer user_data)
427 : : {
428 : 12 : RegistrationData *data = user_data;
429 : 12 : g_mutex_lock (&data->manager->priv->lock);
430 : 12 : registration_data_unexport_interface (data, G_DBUS_INTERFACE_SKELETON (interface));
431 : 12 : g_mutex_unlock (&data->manager->priv->lock);
432 : 12 : }
433 : :
434 : : /* ---------------------------------------------------------------------------------------------------- */
435 : :
436 : :
437 : : static void
438 : 13 : registration_data_free (RegistrationData *data)
439 : : {
440 : : GHashTableIter iter;
441 : : GDBusInterfaceSkeleton *iface;
442 : :
443 : 13 : data->exported = FALSE;
444 : :
445 : 13 : g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
446 : 42 : while (g_hash_table_iter_next (&iter, NULL, (gpointer) &iface))
447 : : {
448 : 16 : if (data->manager->priv->connection != NULL)
449 : 16 : g_dbus_interface_skeleton_unexport (iface);
450 : : }
451 : :
452 : 13 : g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_added), data);
453 : 13 : g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_removed), data);
454 : 13 : g_object_unref (data->object);
455 : 13 : g_hash_table_destroy (data->map_iface_name_to_iface);
456 : 13 : g_free (data);
457 : 13 : }
458 : :
459 : : /* Validate whether an object path is valid as a child of the manager. According
460 : : * to the specification:
461 : : * https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
462 : : * this means that:
463 : : * > All returned object paths are children of the object path implementing this
464 : : * > interface, i.e. their object paths start with the ObjectManager's object
465 : : * > path plus '/'
466 : : *
467 : : * For example, if the manager is at `/org/gnome/Example`, children will be
468 : : * `/org/gnome/Example/(.+)`.
469 : : *
470 : : * It is permissible (but not encouraged) for the manager to be at `/`. If so,
471 : : * children will be `/(.+)`.
472 : : */
473 : : static gboolean
474 : 25 : is_valid_child_object_path (GDBusObjectManagerServer *manager,
475 : : const gchar *child_object_path)
476 : : {
477 : : /* Historically GDBus accepted @child_object_paths at `/` if the @manager
478 : : * itself is also at `/". This is not spec-compliant, but making GDBus enforce
479 : : * the spec more strictly would be an incompatible change.
480 : : *
481 : : * See https://gitlab.gnome.org/GNOME/glib/-/issues/2500 */
482 : 25 : g_warn_if_fail (!g_str_equal (child_object_path, manager->priv->object_path_ending_in_slash));
483 : :
484 : 25 : return g_str_has_prefix (child_object_path, manager->priv->object_path_ending_in_slash);
485 : : }
486 : :
487 : : /* ---------------------------------------------------------------------------------------------------- */
488 : :
489 : : static void
490 : 13 : g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer *manager,
491 : : GDBusObjectSkeleton *object,
492 : : const gchar *object_path)
493 : : {
494 : : RegistrationData *data;
495 : : GList *existing_interfaces;
496 : : GList *l;
497 : : GPtrArray *interface_names;
498 : :
499 : 13 : g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
500 : 13 : g_return_if_fail (G_IS_DBUS_OBJECT (object));
501 : 13 : g_return_if_fail (is_valid_child_object_path (manager, object_path));
502 : :
503 : 13 : interface_names = g_ptr_array_new ();
504 : :
505 : 13 : data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
506 : 13 : if (data != NULL)
507 : 0 : g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
508 : :
509 : 13 : data = g_new0 (RegistrationData, 1);
510 : 13 : data->object = g_object_ref (object);
511 : 13 : data->manager = manager;
512 : 13 : data->map_iface_name_to_iface = g_hash_table_new_full (g_str_hash,
513 : : g_str_equal,
514 : : NULL,
515 : : (GDestroyNotify) g_object_unref);
516 : :
517 : 13 : g_signal_connect (object,
518 : : "interface-added",
519 : : G_CALLBACK (on_interface_added),
520 : : data);
521 : 13 : g_signal_connect (object,
522 : : "interface-removed",
523 : : G_CALLBACK (on_interface_removed),
524 : : data);
525 : :
526 : : /* Register all known interfaces - note that data->exported is FALSE so
527 : : * we don't emit any InterfacesAdded signals.
528 : : */
529 : 13 : existing_interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
530 : 29 : for (l = existing_interfaces; l != NULL; l = l->next)
531 : : {
532 : 16 : GDBusInterfaceSkeleton *interface_skeleton = G_DBUS_INTERFACE_SKELETON (l->data);
533 : 16 : registration_data_export_interface (data, interface_skeleton, object_path);
534 : 16 : g_ptr_array_add (interface_names, g_dbus_interface_skeleton_get_info (interface_skeleton)->name);
535 : : }
536 : 13 : g_list_free_full (existing_interfaces, g_object_unref);
537 : 13 : g_ptr_array_add (interface_names, NULL);
538 : :
539 : 13 : data->exported = TRUE;
540 : :
541 : : /* now emit InterfacesAdded() for all the interfaces */
542 : 13 : g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata, object_path);
543 : 13 : g_ptr_array_unref (interface_names);
544 : :
545 : 13 : g_hash_table_insert (manager->priv->map_object_path_to_data,
546 : 13 : g_strdup (object_path),
547 : : data);
548 : : }
549 : :
550 : : /**
551 : : * g_dbus_object_manager_server_export:
552 : : * @manager: A #GDBusObjectManagerServer.
553 : : * @object: A #GDBusObjectSkeleton.
554 : : *
555 : : * Exports @object on @manager.
556 : : *
557 : : * If there is already a #GDBusObject exported at the object path,
558 : : * then the old object is removed.
559 : : *
560 : : * The object path for @object must be in the hierarchy rooted by the
561 : : * object path for @manager.
562 : : *
563 : : * Note that @manager will take a reference on @object for as long as
564 : : * it is exported.
565 : : *
566 : : * Since: 2.30
567 : : */
568 : : void
569 : 10 : g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager,
570 : : GDBusObjectSkeleton *object)
571 : : {
572 : 10 : g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
573 : 10 : g_mutex_lock (&manager->priv->lock);
574 : 10 : g_dbus_object_manager_server_export_unlocked (manager, object,
575 : 10 : g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
576 : 10 : g_mutex_unlock (&manager->priv->lock);
577 : : }
578 : :
579 : : /**
580 : : * g_dbus_object_manager_server_export_uniquely:
581 : : * @manager: A #GDBusObjectManagerServer.
582 : : * @object: An object.
583 : : *
584 : : * Like g_dbus_object_manager_server_export() but appends a string of
585 : : * the form _N (with N being a natural number) to @object's object path
586 : : * if an object with the given path already exists. As such, the
587 : : * #GDBusObjectProxy:g-object-path property of @object may be modified.
588 : : *
589 : : * Since: 2.30
590 : : */
591 : : void
592 : 3 : g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager,
593 : : GDBusObjectSkeleton *object)
594 : : {
595 : : const gchar *orig_object_path;
596 : : gchar *object_path;
597 : : guint count;
598 : : gboolean modified;
599 : :
600 : 3 : orig_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
601 : :
602 : 3 : g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
603 : 3 : g_return_if_fail (G_IS_DBUS_OBJECT (object));
604 : 3 : g_return_if_fail (is_valid_child_object_path (manager, orig_object_path));
605 : :
606 : 3 : g_mutex_lock (&manager->priv->lock);
607 : :
608 : 3 : object_path = g_strdup (orig_object_path);
609 : 3 : count = 1;
610 : 3 : modified = FALSE;
611 : : while (TRUE)
612 : 3 : {
613 : : RegistrationData *data;
614 : 6 : data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
615 : 6 : if (data == NULL)
616 : : {
617 : 3 : break;
618 : : }
619 : 3 : g_free (object_path);
620 : 3 : object_path = g_strdup_printf ("%s_%d", orig_object_path, count++);
621 : 3 : modified = TRUE;
622 : : }
623 : :
624 : 3 : g_dbus_object_manager_server_export_unlocked (manager, object, object_path);
625 : :
626 : 3 : g_mutex_unlock (&manager->priv->lock);
627 : :
628 : 3 : if (modified)
629 : 3 : g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path);
630 : :
631 : 3 : g_free (object_path);
632 : :
633 : : }
634 : :
635 : : /**
636 : : * g_dbus_object_manager_server_is_exported:
637 : : * @manager: A #GDBusObjectManagerServer.
638 : : * @object: An object.
639 : : *
640 : : * Returns whether @object is currently exported on @manager.
641 : : *
642 : : * Returns: %TRUE if @object is exported
643 : : *
644 : : * Since: 2.34
645 : : **/
646 : : gboolean
647 : 0 : g_dbus_object_manager_server_is_exported (GDBusObjectManagerServer *manager,
648 : : GDBusObjectSkeleton *object)
649 : : {
650 : 0 : RegistrationData *data = NULL;
651 : : const gchar *object_path;
652 : : gboolean object_is_exported;
653 : :
654 : 0 : g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
655 : 0 : g_return_val_if_fail (G_IS_DBUS_OBJECT (object), FALSE);
656 : :
657 : 0 : g_mutex_lock (&manager->priv->lock);
658 : :
659 : 0 : object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
660 : 0 : if (object_path != NULL)
661 : 0 : data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
662 : 0 : object_is_exported = (data != NULL);
663 : :
664 : 0 : g_mutex_unlock (&manager->priv->lock);
665 : :
666 : 0 : return object_is_exported;
667 : : }
668 : :
669 : : /* ---------------------------------------------------------------------------------------------------- */
670 : :
671 : : static gboolean
672 : 9 : g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
673 : : const gchar *object_path)
674 : : {
675 : : RegistrationData *data;
676 : : gboolean ret;
677 : :
678 : 9 : g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
679 : 9 : g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
680 : 9 : g_return_val_if_fail (is_valid_child_object_path (manager, object_path), FALSE);
681 : :
682 : 9 : ret = FALSE;
683 : :
684 : 9 : data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
685 : 9 : if (data != NULL)
686 : : {
687 : : GPtrArray *interface_names;
688 : : GHashTableIter iter;
689 : : const gchar *iface_name;
690 : :
691 : 9 : interface_names = g_ptr_array_new ();
692 : 9 : g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
693 : 21 : while (g_hash_table_iter_next (&iter, (gpointer) &iface_name, NULL))
694 : 12 : g_ptr_array_add (interface_names, (gpointer) iface_name);
695 : 9 : g_ptr_array_add (interface_names, NULL);
696 : : /* now emit InterfacesRemoved() for all the interfaces */
697 : 9 : g_dbus_object_manager_server_emit_interfaces_removed (manager, data, (const gchar *const *) interface_names->pdata);
698 : 9 : g_ptr_array_unref (interface_names);
699 : :
700 : 9 : g_hash_table_remove (manager->priv->map_object_path_to_data, object_path);
701 : 9 : ret = TRUE;
702 : : }
703 : :
704 : 9 : return ret;
705 : : }
706 : :
707 : : /**
708 : : * g_dbus_object_manager_server_unexport:
709 : : * @manager: A #GDBusObjectManagerServer.
710 : : * @object_path: An object path.
711 : : *
712 : : * If @manager has an object at @path, removes the object. Otherwise
713 : : * does nothing.
714 : : *
715 : : * Note that @object_path must be in the hierarchy rooted by the
716 : : * object path for @manager.
717 : : *
718 : : * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
719 : : *
720 : : * Since: 2.30
721 : : */
722 : : gboolean
723 : 9 : g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager,
724 : : const gchar *object_path)
725 : : {
726 : : gboolean ret;
727 : 9 : g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
728 : 9 : g_mutex_lock (&manager->priv->lock);
729 : 9 : ret = g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
730 : 9 : g_mutex_unlock (&manager->priv->lock);
731 : 9 : return ret;
732 : : }
733 : :
734 : :
735 : : /* ---------------------------------------------------------------------------------------------------- */
736 : :
737 : : static const GDBusArgInfo manager_interfaces_added_signal_info_arg0 =
738 : : {
739 : : -1,
740 : : "object_path",
741 : : "o",
742 : : (GDBusAnnotationInfo**) NULL,
743 : : };
744 : :
745 : : static const GDBusArgInfo manager_interfaces_added_signal_info_arg1 =
746 : : {
747 : : -1,
748 : : "interfaces_and_properties",
749 : : "a{sa{sv}}",
750 : : (GDBusAnnotationInfo**) NULL,
751 : : };
752 : :
753 : : static const GDBusArgInfo * const manager_interfaces_added_signal_info_arg_pointers[] =
754 : : {
755 : : &manager_interfaces_added_signal_info_arg0,
756 : : &manager_interfaces_added_signal_info_arg1,
757 : : NULL
758 : : };
759 : :
760 : : static const GDBusSignalInfo manager_interfaces_added_signal_info =
761 : : {
762 : : -1,
763 : : "InterfacesAdded",
764 : : (GDBusArgInfo**) &manager_interfaces_added_signal_info_arg_pointers,
765 : : (GDBusAnnotationInfo**) NULL
766 : : };
767 : :
768 : : /* ---------- */
769 : :
770 : : static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0 =
771 : : {
772 : : -1,
773 : : "object_path",
774 : : "o",
775 : : (GDBusAnnotationInfo**) NULL,
776 : : };
777 : :
778 : : static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1 =
779 : : {
780 : : -1,
781 : : "interfaces",
782 : : "as",
783 : : (GDBusAnnotationInfo**) NULL,
784 : : };
785 : :
786 : : static const GDBusArgInfo * const manager_interfaces_removed_signal_info_arg_pointers[] =
787 : : {
788 : : &manager_interfaces_removed_signal_info_arg0,
789 : : &manager_interfaces_removed_signal_info_arg1,
790 : : NULL
791 : : };
792 : :
793 : : static const GDBusSignalInfo manager_interfaces_removed_signal_info =
794 : : {
795 : : -1,
796 : : "InterfacesRemoved",
797 : : (GDBusArgInfo**) &manager_interfaces_removed_signal_info_arg_pointers,
798 : : (GDBusAnnotationInfo**) NULL
799 : : };
800 : :
801 : : /* ---------- */
802 : :
803 : : static const GDBusSignalInfo * const manager_signal_info_pointers[] =
804 : : {
805 : : &manager_interfaces_added_signal_info,
806 : : &manager_interfaces_removed_signal_info,
807 : : NULL
808 : : };
809 : :
810 : : /* ---------- */
811 : :
812 : : static const GDBusArgInfo manager_get_all_method_info_out_arg0 =
813 : : {
814 : : -1,
815 : : "object_paths_interfaces_and_properties",
816 : : "a{oa{sa{sv}}}",
817 : : (GDBusAnnotationInfo**) NULL,
818 : : };
819 : :
820 : : static const GDBusArgInfo * const manager_get_all_method_info_out_arg_pointers[] =
821 : : {
822 : : &manager_get_all_method_info_out_arg0,
823 : : NULL
824 : : };
825 : :
826 : : static const GDBusMethodInfo manager_get_all_method_info =
827 : : {
828 : : -1,
829 : : "GetManagedObjects",
830 : : (GDBusArgInfo**) NULL,
831 : : (GDBusArgInfo**) &manager_get_all_method_info_out_arg_pointers,
832 : : (GDBusAnnotationInfo**) NULL
833 : : };
834 : :
835 : : static const GDBusMethodInfo * const manager_method_info_pointers[] =
836 : : {
837 : : &manager_get_all_method_info,
838 : : NULL
839 : : };
840 : :
841 : : /* ---------- */
842 : :
843 : : static const GDBusInterfaceInfo manager_interface_info =
844 : : {
845 : : -1,
846 : : DBUS_INTERFACE_OBJECT_MANAGER,
847 : : (GDBusMethodInfo **) manager_method_info_pointers,
848 : : (GDBusSignalInfo **) manager_signal_info_pointers,
849 : : (GDBusPropertyInfo **) NULL,
850 : : (GDBusAnnotationInfo **) NULL
851 : : };
852 : :
853 : : static void
854 : 23 : manager_method_call (GDBusConnection *connection,
855 : : const gchar *sender,
856 : : const gchar *object_path,
857 : : const gchar *interface_name,
858 : : const gchar *method_name,
859 : : GVariant *parameters,
860 : : GDBusMethodInvocation *invocation,
861 : : gpointer user_data)
862 : : {
863 : 23 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (user_data);
864 : : GVariantBuilder array_builder;
865 : : GHashTableIter object_iter;
866 : : RegistrationData *data;
867 : :
868 : 23 : g_mutex_lock (&manager->priv->lock);
869 : :
870 : 23 : if (g_strcmp0 (method_name, "GetManagedObjects") == 0)
871 : : {
872 : 23 : g_variant_builder_init_static (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
873 : 23 : g_hash_table_iter_init (&object_iter, manager->priv->map_object_path_to_data);
874 : 51 : while (g_hash_table_iter_next (&object_iter, NULL, (gpointer) &data))
875 : : {
876 : : GVariantBuilder interfaces_builder;
877 : : GHashTableIter interface_iter;
878 : : GDBusInterfaceSkeleton *iface;
879 : : const gchar *iter_object_path;
880 : :
881 : 28 : g_variant_builder_init_static (&interfaces_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
882 : 28 : g_hash_table_iter_init (&interface_iter, data->map_iface_name_to_iface);
883 : 62 : while (g_hash_table_iter_next (&interface_iter, NULL, (gpointer) &iface))
884 : : {
885 : 34 : GVariant *properties = g_dbus_interface_skeleton_get_properties (iface);
886 : 34 : g_variant_builder_add (&interfaces_builder, "{s@a{sv}}",
887 : 34 : g_dbus_interface_skeleton_get_info (iface)->name,
888 : : properties);
889 : 34 : g_variant_unref (properties);
890 : : }
891 : 28 : iter_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
892 : 28 : g_variant_builder_add (&array_builder,
893 : : "{oa{sa{sv}}}",
894 : : iter_object_path,
895 : : &interfaces_builder);
896 : : }
897 : :
898 : 23 : g_dbus_method_invocation_return_value (invocation,
899 : : g_variant_new ("(a{oa{sa{sv}}})",
900 : : &array_builder));
901 : : }
902 : : else
903 : : {
904 : 0 : g_dbus_method_invocation_return_error (invocation,
905 : : G_DBUS_ERROR,
906 : : G_DBUS_ERROR_UNKNOWN_METHOD,
907 : : "Unknown method %s - only GetManagedObjects() is supported",
908 : : method_name);
909 : : }
910 : 23 : g_mutex_unlock (&manager->priv->lock);
911 : 23 : }
912 : :
913 : : static const GDBusInterfaceVTable manager_interface_vtable =
914 : : {
915 : : manager_method_call, /* handle_method_call */
916 : : NULL, /* get_property */
917 : : NULL, /* set_property */
918 : : { 0 }
919 : : };
920 : :
921 : : /* ---------------------------------------------------------------------------------------------------- */
922 : :
923 : : static void
924 : 5 : g_dbus_object_manager_server_constructed (GObject *object)
925 : : {
926 : 5 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
927 : :
928 : 5 : if (manager->priv->connection != NULL)
929 : 0 : export_all (manager);
930 : :
931 : 5 : if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed != NULL)
932 : 5 : G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed (object);
933 : 5 : }
934 : :
935 : : static void
936 : 25 : g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
937 : : RegistrationData *data,
938 : : const gchar *const *interfaces,
939 : : const gchar *object_path)
940 : : {
941 : : GVariantBuilder array_builder;
942 : : GError *error;
943 : : guint n;
944 : :
945 : 25 : if (data->manager->priv->connection == NULL)
946 : 4 : goto out;
947 : :
948 : 21 : g_variant_builder_init_static (&array_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
949 : 45 : for (n = 0; interfaces[n] != NULL; n++)
950 : : {
951 : : GDBusInterfaceSkeleton *iface;
952 : : GVariant *properties;
953 : :
954 : 24 : iface = g_hash_table_lookup (data->map_iface_name_to_iface, interfaces[n]);
955 : 24 : g_assert (iface != NULL);
956 : 24 : properties = g_dbus_interface_skeleton_get_properties (iface);
957 : 24 : g_variant_builder_add (&array_builder, "{s@a{sv}}", interfaces[n], properties);
958 : 24 : g_variant_unref (properties);
959 : : }
960 : :
961 : 21 : error = NULL;
962 : 21 : g_dbus_connection_emit_signal (data->manager->priv->connection,
963 : : NULL, /* destination_bus_name */
964 : 21 : manager->priv->object_path,
965 : 21 : manager_interface_info.name,
966 : : "InterfacesAdded",
967 : : g_variant_new ("(oa{sa{sv}})",
968 : : object_path,
969 : : &array_builder),
970 : : &error);
971 : 21 : if (error)
972 : : {
973 : 0 : if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
974 : 0 : g_warning ("Couldn't emit InterfacesAdded signal: %s", error->message);
975 : 0 : g_error_free (error);
976 : : }
977 : 21 : out:
978 : : ;
979 : 25 : }
980 : :
981 : : static void
982 : 21 : g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
983 : : RegistrationData *data,
984 : : const gchar *const *interfaces)
985 : : {
986 : : GVariantBuilder array_builder;
987 : : GError *error;
988 : : guint n;
989 : : const gchar *object_path;
990 : :
991 : 21 : if (data->manager->priv->connection == NULL)
992 : 0 : goto out;
993 : :
994 : 21 : g_variant_builder_init_static (&array_builder, G_VARIANT_TYPE ("as"));
995 : 45 : for (n = 0; interfaces[n] != NULL; n++)
996 : 24 : g_variant_builder_add (&array_builder, "s", interfaces[n]);
997 : :
998 : 21 : error = NULL;
999 : 21 : object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
1000 : 21 : g_dbus_connection_emit_signal (data->manager->priv->connection,
1001 : : NULL, /* destination_bus_name */
1002 : 21 : manager->priv->object_path,
1003 : 21 : manager_interface_info.name,
1004 : : "InterfacesRemoved",
1005 : : g_variant_new ("(oas)",
1006 : : object_path,
1007 : : &array_builder),
1008 : : &error);
1009 : 21 : if (error)
1010 : : {
1011 : 0 : if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
1012 : 0 : g_warning ("Couldn't emit InterfacesRemoved signal: %s", error->message);
1013 : 0 : g_error_free (error);
1014 : : }
1015 : 21 : out:
1016 : : ;
1017 : 21 : }
1018 : :
1019 : : /* ---------------------------------------------------------------------------------------------------- */
1020 : :
1021 : : static GList *
1022 : 3 : g_dbus_object_manager_server_get_objects (GDBusObjectManager *_manager)
1023 : : {
1024 : 3 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1025 : : GList *ret;
1026 : : GHashTableIter iter;
1027 : : RegistrationData *data;
1028 : :
1029 : 3 : g_mutex_lock (&manager->priv->lock);
1030 : :
1031 : 3 : ret = NULL;
1032 : 3 : g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1033 : 3 : while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1034 : : {
1035 : 0 : ret = g_list_prepend (ret, g_object_ref (data->object));
1036 : : }
1037 : :
1038 : 3 : g_mutex_unlock (&manager->priv->lock);
1039 : :
1040 : 3 : return ret;
1041 : : }
1042 : :
1043 : : static const gchar *
1044 : 6 : g_dbus_object_manager_server_get_object_path (GDBusObjectManager *_manager)
1045 : : {
1046 : 6 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1047 : 6 : return manager->priv->object_path;
1048 : : }
1049 : :
1050 : : static GDBusObject *
1051 : 6 : g_dbus_object_manager_server_get_object (GDBusObjectManager *_manager,
1052 : : const gchar *object_path)
1053 : : {
1054 : 6 : GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1055 : : GDBusObject *ret;
1056 : : RegistrationData *data;
1057 : :
1058 : 6 : ret = NULL;
1059 : :
1060 : 6 : g_mutex_lock (&manager->priv->lock);
1061 : 6 : data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
1062 : 6 : if (data != NULL)
1063 : 6 : ret = g_object_ref (G_DBUS_OBJECT (data->object));
1064 : 6 : g_mutex_unlock (&manager->priv->lock);
1065 : :
1066 : 6 : return ret;
1067 : : }
1068 : :
1069 : : static GDBusInterface *
1070 : 6 : g_dbus_object_manager_server_get_interface (GDBusObjectManager *_manager,
1071 : : const gchar *object_path,
1072 : : const gchar *interface_name)
1073 : : {
1074 : : GDBusInterface *ret;
1075 : : GDBusObject *object;
1076 : :
1077 : 6 : ret = NULL;
1078 : :
1079 : 6 : object = g_dbus_object_manager_get_object (_manager, object_path);
1080 : 6 : if (object == NULL)
1081 : 0 : goto out;
1082 : :
1083 : 6 : ret = g_dbus_object_get_interface (object, interface_name);
1084 : 6 : g_object_unref (object);
1085 : :
1086 : 6 : out:
1087 : 6 : return ret;
1088 : : }
1089 : :
1090 : : static void
1091 : 5 : dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
1092 : : {
1093 : 5 : iface->get_object_path = g_dbus_object_manager_server_get_object_path;
1094 : 5 : iface->get_objects = g_dbus_object_manager_server_get_objects;
1095 : 5 : iface->get_object = g_dbus_object_manager_server_get_object;
1096 : 5 : iface->get_interface = g_dbus_object_manager_server_get_interface;
1097 : 5 : }
1098 : :
1099 : : /* ---------------------------------------------------------------------------------------------------- */
1100 : :
1101 : : static void
1102 : 8 : export_all (GDBusObjectManagerServer *manager)
1103 : : {
1104 : : GHashTableIter iter;
1105 : : const gchar *object_path;
1106 : : RegistrationData *data;
1107 : : GHashTableIter iface_iter;
1108 : : GDBusInterfaceSkeleton *iface;
1109 : : GError *error;
1110 : :
1111 : 8 : g_return_if_fail (manager->priv->connection != NULL);
1112 : :
1113 : 8 : error = NULL;
1114 : 8 : g_warn_if_fail (manager->priv->manager_reg_id == 0);
1115 : 16 : manager->priv->manager_reg_id = g_dbus_connection_register_object (manager->priv->connection,
1116 : 8 : manager->priv->object_path,
1117 : : (GDBusInterfaceInfo *) &manager_interface_info,
1118 : : &manager_interface_vtable,
1119 : : manager,
1120 : : NULL, /* user_data_free_func */
1121 : : &error);
1122 : 8 : if (manager->priv->manager_reg_id == 0)
1123 : : {
1124 : 0 : g_warning ("%s: Error registering manager at %s: %s",
1125 : : G_STRLOC,
1126 : : manager->priv->object_path,
1127 : : error->message);
1128 : 0 : g_error_free (error);
1129 : : }
1130 : :
1131 : 8 : g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1132 : 18 : while (g_hash_table_iter_next (&iter, (gpointer) &object_path, (gpointer) &data))
1133 : : {
1134 : 10 : g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1135 : 33 : while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1136 : : {
1137 : 13 : g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) == NULL);
1138 : 13 : error = NULL;
1139 : 13 : if (!g_dbus_interface_skeleton_export (iface,
1140 : 13 : manager->priv->connection,
1141 : : object_path,
1142 : : &error))
1143 : : {
1144 : 0 : g_warning ("%s: Error registering object at %s with interface %s: %s",
1145 : : G_STRLOC,
1146 : : object_path,
1147 : : g_dbus_interface_skeleton_get_info (iface)->name,
1148 : : error->message);
1149 : 0 : g_error_free (error);
1150 : : }
1151 : : }
1152 : : }
1153 : : }
1154 : :
1155 : : static void
1156 : 8 : unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager)
1157 : : {
1158 : : GHashTableIter iter;
1159 : : RegistrationData *data;
1160 : : GHashTableIter iface_iter;
1161 : : GDBusInterfaceSkeleton *iface;
1162 : :
1163 : 8 : g_return_if_fail (manager->priv->connection != NULL);
1164 : :
1165 : 8 : g_warn_if_fail (manager->priv->manager_reg_id > 0);
1166 : 8 : if (manager->priv->manager_reg_id > 0)
1167 : : {
1168 : 8 : g_warn_if_fail (g_dbus_connection_unregister_object (manager->priv->connection,
1169 : : manager->priv->manager_reg_id));
1170 : 8 : manager->priv->manager_reg_id = 0;
1171 : : }
1172 : 8 : if (only_manager)
1173 : 5 : goto out;
1174 : :
1175 : 3 : g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1176 : 9 : while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1177 : : {
1178 : 6 : g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1179 : 15 : while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1180 : : {
1181 : 9 : g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) != NULL);
1182 : 9 : g_dbus_interface_skeleton_unexport (iface);
1183 : : }
1184 : : }
1185 : 8 : out:
1186 : : ;
1187 : : }
1188 : :
1189 : : /* ---------------------------------------------------------------------------------------------------- */
|