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