Blame gio/gdbusobjectmanagerserver.c

Packit ae235b
/* GDBus - GLib D-Bus Library
Packit ae235b
 *
Packit ae235b
 * Copyright (C) 2008-2010 Red Hat, Inc.
Packit ae235b
 *
Packit ae235b
 * This library is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * This library is distributed in the hope that it will be useful,
Packit ae235b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ae235b
 * Lesser General Public License for more details.
Packit ae235b
 *
Packit ae235b
 * You should have received a copy of the GNU Lesser General
Packit ae235b
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit ae235b
 *
Packit ae235b
 * Author: David Zeuthen <davidz@redhat.com>
Packit ae235b
 */
Packit ae235b
Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
#include "gdbusobjectmanager.h"
Packit ae235b
#include "gdbusobjectmanagerserver.h"
Packit ae235b
#include "gdbusobject.h"
Packit ae235b
#include "gdbusobjectskeleton.h"
Packit ae235b
#include "gdbusinterfaceskeleton.h"
Packit ae235b
#include "gdbusconnection.h"
Packit ae235b
#include "gdbusintrospection.h"
Packit ae235b
#include "gdbusmethodinvocation.h"
Packit ae235b
#include "gdbuserror.h"
Packit ae235b
Packit ae235b
#include "gioerror.h"
Packit ae235b
Packit ae235b
#include "glibintl.h"
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * SECTION:gdbusobjectmanagerserver
Packit ae235b
 * @short_description: Service-side object manager
Packit ae235b
 * @include: gio/gio.h
Packit ae235b
 *
Packit ae235b
 * #GDBusObjectManagerServer is used to export #GDBusObject instances using
Packit ae235b
 * the standardized
Packit ae235b
 * [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
Packit ae235b
 * interface. For example, remote D-Bus clients can get all objects
Packit ae235b
 * and properties in a single call. Additionally, any change in the
Packit ae235b
 * object hierarchy is broadcast using signals. This means that D-Bus
Packit ae235b
 * clients can keep caches up to date by only listening to D-Bus
Packit ae235b
 * signals.
Packit ae235b
 *
Packit ae235b
 * The recommended path to export an object manager at is the path form of the
Packit ae235b
 * well-known name of a D-Bus service, or below. For example, if a D-Bus service
Packit ae235b
 * is available at the well-known name `net.example.ExampleService1`, the object
Packit ae235b
 * manager should typically be exported at `/net/example/ExampleService1`, or
Packit ae235b
 * below (to allow for multiple object managers in a service).
Packit ae235b
 *
Packit ae235b
 * It is supported, but not recommended, to export an object manager at the root
Packit ae235b
 * path, `/`.
Packit ae235b
 *
Packit ae235b
 * See #GDBusObjectManagerClient for the client-side code that is
Packit ae235b
 * intended to be used with #GDBusObjectManagerServer or any D-Bus
Packit ae235b
 * object implementing the org.freedesktop.DBus.ObjectManager
Packit ae235b
 * interface.
Packit ae235b
 */
Packit ae235b
Packit ae235b
typedef struct
Packit ae235b
{
Packit ae235b
  GDBusObjectSkeleton *object;
Packit ae235b
  GDBusObjectManagerServer *manager;
Packit ae235b
  GHashTable *map_iface_name_to_iface;
Packit ae235b
  gboolean exported;
Packit ae235b
} RegistrationData;
Packit ae235b
Packit ae235b
static void registration_data_free (RegistrationData *data);
Packit ae235b
Packit ae235b
static void export_all (GDBusObjectManagerServer *manager);
Packit ae235b
static void unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager);
Packit ae235b
Packit ae235b
static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
Packit ae235b
                                                         RegistrationData   *data,
Packit ae235b
                                                         const gchar *const *interfaces,
Packit ae235b
                                                         const gchar *object_path);
Packit ae235b
Packit ae235b
static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
Packit ae235b
                                                           RegistrationData   *data,
Packit ae235b
                                                           const gchar *const *interfaces);
Packit ae235b
Packit ae235b
static gboolean g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer  *manager,
Packit ae235b
                                                                const gchar               *object_path);
Packit ae235b
Packit ae235b
struct _GDBusObjectManagerServerPrivate
Packit ae235b
{
Packit ae235b
  GMutex lock;
Packit ae235b
  GDBusConnection *connection;
Packit ae235b
  gchar *object_path;
Packit ae235b
  gchar *object_path_ending_in_slash;
Packit ae235b
  GHashTable *map_object_path_to_data;
Packit ae235b
  guint manager_reg_id;
Packit ae235b
};
Packit ae235b
Packit ae235b
enum
Packit ae235b
{
Packit ae235b
  PROP_0,
Packit ae235b
  PROP_CONNECTION,
Packit ae235b
  PROP_OBJECT_PATH
Packit ae235b
};
Packit ae235b
Packit ae235b
static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
Packit ae235b
Packit ae235b
G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer, g_dbus_object_manager_server, G_TYPE_OBJECT,
Packit ae235b
                         G_ADD_PRIVATE (GDBusObjectManagerServer)
Packit ae235b
                         G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init))
Packit ae235b
Packit ae235b
static void g_dbus_object_manager_server_constructed (GObject *object);
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_finalize (GObject *object)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
Packit ae235b
Packit ae235b
  if (manager->priv->connection != NULL)
Packit ae235b
    {
Packit ae235b
      unexport_all (manager, TRUE);
Packit ae235b
      g_object_unref (manager->priv->connection);
Packit ae235b
    }
Packit ae235b
  g_hash_table_unref (manager->priv->map_object_path_to_data);
Packit ae235b
  g_free (manager->priv->object_path);
Packit ae235b
  g_free (manager->priv->object_path_ending_in_slash);
Packit ae235b
Packit ae235b
  g_mutex_clear (&manager->priv->lock);
Packit ae235b
Packit ae235b
  if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize != NULL)
Packit ae235b
    G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize (object);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_get_property (GObject    *object,
Packit ae235b
                                           guint       prop_id,
Packit ae235b
                                           GValue     *value,
Packit ae235b
                                           GParamSpec *pspec)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
Packit ae235b
Packit ae235b
  switch (prop_id)
Packit ae235b
    {
Packit ae235b
    case PROP_CONNECTION:
Packit ae235b
      g_mutex_lock (&manager->priv->lock);
Packit ae235b
      g_value_set_object (value, manager->priv->connection);
Packit ae235b
      g_mutex_unlock (&manager->priv->lock);
Packit ae235b
      break;
Packit ae235b
Packit ae235b
    case PROP_OBJECT_PATH:
Packit ae235b
      g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
Packit ae235b
      break;
Packit ae235b
Packit ae235b
    default:
Packit ae235b
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit ae235b
      break;
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_set_property (GObject       *object,
Packit ae235b
                                           guint          prop_id,
Packit ae235b
                                           const GValue  *value,
Packit ae235b
                                           GParamSpec    *pspec)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
Packit ae235b
Packit ae235b
  switch (prop_id)
Packit ae235b
    {
Packit ae235b
    case PROP_CONNECTION:
Packit ae235b
      g_dbus_object_manager_server_set_connection (manager, g_value_get_object (value));
Packit ae235b
      break;
Packit ae235b
Packit ae235b
    case PROP_OBJECT_PATH:
Packit ae235b
      g_assert (manager->priv->object_path == NULL);
Packit ae235b
      g_assert (g_variant_is_object_path (g_value_get_string (value)));
Packit ae235b
      manager->priv->object_path = g_value_dup_string (value);
Packit ae235b
      if (g_str_equal (manager->priv->object_path, "/"))
Packit ae235b
        manager->priv->object_path_ending_in_slash = g_strdup (manager->priv->object_path);
Packit ae235b
      else
Packit ae235b
        manager->priv->object_path_ending_in_slash = g_strdup_printf ("%s/", manager->priv->object_path);
Packit ae235b
      break;
Packit ae235b
Packit ae235b
    default:
Packit ae235b
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit ae235b
      break;
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass *klass)
Packit ae235b
{
Packit ae235b
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit ae235b
Packit ae235b
  gobject_class->finalize     = g_dbus_object_manager_server_finalize;
Packit ae235b
  gobject_class->constructed  = g_dbus_object_manager_server_constructed;
Packit ae235b
  gobject_class->set_property = g_dbus_object_manager_server_set_property;
Packit ae235b
  gobject_class->get_property = g_dbus_object_manager_server_get_property;
Packit ae235b
Packit ae235b
  /**
Packit ae235b
   * GDBusObjectManagerServer:connection:
Packit ae235b
   *
Packit ae235b
   * The #GDBusConnection to export objects on.
Packit ae235b
   *
Packit ae235b
   * Since: 2.30
Packit ae235b
   */
Packit ae235b
  g_object_class_install_property (gobject_class,
Packit ae235b
                                   PROP_CONNECTION,
Packit ae235b
                                   g_param_spec_object ("connection",
Packit ae235b
                                                        "Connection",
Packit ae235b
                                                        "The connection to export objects on",
Packit ae235b
                                                        G_TYPE_DBUS_CONNECTION,
Packit ae235b
                                                        G_PARAM_READABLE |
Packit ae235b
                                                        G_PARAM_WRITABLE |
Packit ae235b
                                                        G_PARAM_STATIC_STRINGS));
Packit ae235b
Packit ae235b
  /**
Packit ae235b
   * GDBusObjectManagerServer:object-path:
Packit ae235b
   *
Packit ae235b
   * The object path to register the manager object at.
Packit ae235b
   *
Packit ae235b
   * Since: 2.30
Packit ae235b
   */
Packit ae235b
  g_object_class_install_property (gobject_class,
Packit ae235b
                                   PROP_OBJECT_PATH,
Packit ae235b
                                   g_param_spec_string ("object-path",
Packit ae235b
                                                        "Object Path",
Packit ae235b
                                                        "The object path to register the manager object at",
Packit ae235b
                                                        NULL,
Packit ae235b
                                                        G_PARAM_READABLE |
Packit ae235b
                                                        G_PARAM_WRITABLE |
Packit ae235b
                                                        G_PARAM_CONSTRUCT_ONLY |
Packit ae235b
                                                        G_PARAM_STATIC_STRINGS));
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_init (GDBusObjectManagerServer *manager)
Packit ae235b
{
Packit ae235b
  manager->priv = g_dbus_object_manager_server_get_instance_private (manager);
Packit ae235b
  g_mutex_init (&manager->priv->lock);
Packit ae235b
  manager->priv->map_object_path_to_data = g_hash_table_new_full (g_str_hash,
Packit ae235b
                                                                  g_str_equal,
Packit ae235b
                                                                  g_free,
Packit ae235b
                                                                  (GDestroyNotify) registration_data_free);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_dbus_object_manager_server_new:
Packit ae235b
 * @object_path: The object path to export the manager object at.
Packit ae235b
 *
Packit ae235b
 * Creates a new #GDBusObjectManagerServer object.
Packit ae235b
 *
Packit ae235b
 * The returned server isn't yet exported on any connection. To do so,
Packit ae235b
 * use g_dbus_object_manager_server_set_connection(). Normally you
Packit ae235b
 * want to export all of your objects before doing so to avoid
Packit ae235b
 * [InterfacesAdded](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
Packit ae235b
 * signals being emitted.
Packit ae235b
 *
Packit ae235b
 * Returns: A #GDBusObjectManagerServer object. Free with g_object_unref().
Packit ae235b
 *
Packit ae235b
 * Since: 2.30
Packit ae235b
 */
Packit ae235b
GDBusObjectManagerServer *
Packit ae235b
g_dbus_object_manager_server_new (const gchar     *object_path)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
Packit ae235b
  return G_DBUS_OBJECT_MANAGER_SERVER (g_object_new (G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
Packit ae235b
                                                     "object-path", object_path,
Packit ae235b
                                                     NULL));
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_dbus_object_manager_server_set_connection:
Packit ae235b
 * @manager: A #GDBusObjectManagerServer.
Packit ae235b
 * @connection: (nullable): A #GDBusConnection or %NULL.
Packit ae235b
 *
Packit ae235b
 * Exports all objects managed by @manager on @connection. If
Packit ae235b
 * @connection is %NULL, stops exporting objects.
Packit ae235b
 */
Packit ae235b
void
Packit ae235b
g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer  *manager,
Packit ae235b
                                             GDBusConnection           *connection)
Packit ae235b
{
Packit ae235b
  g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
Packit ae235b
  g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
Packit ae235b
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  if (manager->priv->connection == connection)
Packit ae235b
    {
Packit ae235b
      g_mutex_unlock (&manager->priv->lock);
Packit ae235b
      goto out;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (manager->priv->connection != NULL)
Packit ae235b
    {
Packit ae235b
      unexport_all (manager, FALSE);
Packit ae235b
      g_object_unref (manager->priv->connection);
Packit ae235b
      manager->priv->connection = NULL;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  manager->priv->connection = connection != NULL ? g_object_ref (connection) : NULL;
Packit ae235b
  if (manager->priv->connection != NULL)
Packit ae235b
    export_all (manager);
Packit ae235b
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  g_object_notify (G_OBJECT (manager), "connection");
Packit ae235b
 out:
Packit ae235b
  ;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_dbus_object_manager_server_get_connection:
Packit ae235b
 * @manager: A #GDBusObjectManagerServer
Packit ae235b
 *
Packit ae235b
 * Gets the #GDBusConnection used by @manager.
Packit ae235b
 *
Packit ae235b
 * Returns: (transfer full): A #GDBusConnection object or %NULL if
Packit ae235b
 *   @manager isn't exported on a connection. The returned object should
Packit ae235b
 *   be freed with g_object_unref().
Packit ae235b
 *
Packit ae235b
 * Since: 2.30
Packit ae235b
 */
Packit ae235b
GDBusConnection *
Packit ae235b
g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer *manager)
Packit ae235b
{
Packit ae235b
  GDBusConnection *ret;
Packit ae235b
  g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), NULL);
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
  ret = manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL;
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static void
Packit ae235b
registration_data_export_interface (RegistrationData        *data,
Packit ae235b
                                    GDBusInterfaceSkeleton  *interface_skeleton,
Packit ae235b
                                    const gchar             *object_path)
Packit ae235b
{
Packit ae235b
  GDBusInterfaceInfo *info;
Packit ae235b
  GError *error;
Packit ae235b
Packit ae235b
  info = g_dbus_interface_skeleton_get_info (interface_skeleton);
Packit ae235b
  error = NULL;
Packit ae235b
  if (data->manager->priv->connection != NULL)
Packit ae235b
    {
Packit ae235b
      if (!g_dbus_interface_skeleton_export (interface_skeleton,
Packit ae235b
                                             data->manager->priv->connection,
Packit ae235b
                                             object_path,
Packit ae235b
                                             &error))
Packit ae235b
        {
Packit ae235b
          g_warning ("%s: Error registering object at %s with interface %s: %s",
Packit ae235b
                     G_STRLOC,
Packit ae235b
                     object_path,
Packit ae235b
                     info->name,
Packit ae235b
                     error->message);
Packit ae235b
          g_error_free (error);
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_assert (g_hash_table_lookup (data->map_iface_name_to_iface, info->name) == NULL);
Packit ae235b
  g_hash_table_insert (data->map_iface_name_to_iface,
Packit ae235b
                       info->name,
Packit ae235b
                       g_object_ref (interface_skeleton));
Packit ae235b
Packit ae235b
  /* if we are already exported, then... */
Packit ae235b
  if (data->exported)
Packit ae235b
    {
Packit ae235b
      const gchar *interfaces[2];
Packit ae235b
      /* emit InterfacesAdded on the ObjectManager object */
Packit ae235b
      interfaces[0] = info->name;
Packit ae235b
      interfaces[1] = NULL;
Packit ae235b
      g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces, object_path);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
registration_data_unexport_interface (RegistrationData       *data,
Packit ae235b
                                      GDBusInterfaceSkeleton *interface_skeleton)
Packit ae235b
{
Packit ae235b
  GDBusInterfaceInfo *info;
Packit ae235b
  GDBusInterfaceSkeleton *iface;
Packit ae235b
Packit ae235b
  info = g_dbus_interface_skeleton_get_info (interface_skeleton);
Packit ae235b
  iface = g_hash_table_lookup (data->map_iface_name_to_iface, info->name);
Packit ae235b
  g_assert (iface != NULL);
Packit ae235b
Packit ae235b
  if (data->manager->priv->connection != NULL)
Packit ae235b
    g_dbus_interface_skeleton_unexport (iface);
Packit ae235b
Packit ae235b
  g_warn_if_fail (g_hash_table_remove (data->map_iface_name_to_iface, info->name));
Packit ae235b
Packit ae235b
  /* if we are already exported, then... */
Packit ae235b
  if (data->exported)
Packit ae235b
    {
Packit ae235b
      const gchar *interfaces[2];
Packit ae235b
      /* emit InterfacesRemoved on the ObjectManager object */
Packit ae235b
      interfaces[0] = info->name;
Packit ae235b
      interfaces[1] = NULL;
Packit ae235b
      g_dbus_object_manager_server_emit_interfaces_removed (data->manager, data, interfaces);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static void
Packit ae235b
on_interface_added (GDBusObject    *object,
Packit ae235b
                    GDBusInterface *interface,
Packit ae235b
                    gpointer        user_data)
Packit ae235b
{
Packit ae235b
  RegistrationData *data = user_data;
Packit ae235b
  const gchar *object_path;
Packit ae235b
  g_mutex_lock (&data->manager->priv->lock);
Packit ae235b
  object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
Packit ae235b
  registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface), object_path);
Packit ae235b
  g_mutex_unlock (&data->manager->priv->lock);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
on_interface_removed (GDBusObject    *object,
Packit ae235b
                      GDBusInterface *interface,
Packit ae235b
                      gpointer        user_data)
Packit ae235b
{
Packit ae235b
  RegistrationData *data = user_data;
Packit ae235b
  g_mutex_lock (&data->manager->priv->lock);
Packit ae235b
  registration_data_unexport_interface (data, G_DBUS_INTERFACE_SKELETON (interface));
Packit ae235b
  g_mutex_unlock (&data->manager->priv->lock);
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
Packit ae235b
static void
Packit ae235b
registration_data_free (RegistrationData *data)
Packit ae235b
{
Packit ae235b
  GHashTableIter iter;
Packit ae235b
  GDBusInterfaceSkeleton *iface;
Packit ae235b
Packit ae235b
  data->exported = FALSE;
Packit ae235b
Packit ae235b
  g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
Packit ae235b
  while (g_hash_table_iter_next (&iter, NULL, (gpointer) &iface))
Packit ae235b
    {
Packit ae235b
      if (data->manager->priv->connection != NULL)
Packit ae235b
        g_dbus_interface_skeleton_unexport (iface);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_added), data);
Packit ae235b
  g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_removed), data);
Packit ae235b
  g_object_unref (data->object);
Packit ae235b
  g_hash_table_destroy (data->map_iface_name_to_iface);
Packit ae235b
  g_free (data);
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer  *manager,
Packit ae235b
                                              GDBusObjectSkeleton       *object,
Packit ae235b
                                              const gchar               *object_path)
Packit ae235b
{
Packit ae235b
  RegistrationData *data;
Packit ae235b
  GList *existing_interfaces;
Packit ae235b
  GList *l;
Packit ae235b
  GPtrArray *interface_names;
Packit ae235b
Packit ae235b
  g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
Packit ae235b
  g_return_if_fail (G_IS_DBUS_OBJECT (object));
Packit ae235b
  g_return_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash));
Packit ae235b
Packit ae235b
  interface_names = g_ptr_array_new ();
Packit ae235b
Packit ae235b
  data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
Packit ae235b
  if (data != NULL)
Packit ae235b
    g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
Packit ae235b
Packit ae235b
  data = g_new0 (RegistrationData, 1);
Packit ae235b
  data->object = g_object_ref (object);
Packit ae235b
  data->manager = manager;
Packit ae235b
  data->map_iface_name_to_iface = g_hash_table_new_full (g_str_hash,
Packit ae235b
                                                         g_str_equal,
Packit ae235b
                                                         NULL,
Packit ae235b
                                                         (GDestroyNotify) g_object_unref);
Packit ae235b
Packit ae235b
  g_signal_connect (object,
Packit ae235b
                    "interface-added",
Packit ae235b
                    G_CALLBACK (on_interface_added),
Packit ae235b
                    data);
Packit ae235b
  g_signal_connect (object,
Packit ae235b
                    "interface-removed",
Packit ae235b
                    G_CALLBACK (on_interface_removed),
Packit ae235b
                    data);
Packit ae235b
Packit ae235b
  /* Register all known interfaces - note that data->exported is FALSE so
Packit ae235b
   * we don't emit any InterfacesAdded signals.
Packit ae235b
   */
Packit ae235b
  existing_interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
Packit ae235b
  for (l = existing_interfaces; l != NULL; l = l->next)
Packit ae235b
    {
Packit ae235b
      GDBusInterfaceSkeleton *interface_skeleton = G_DBUS_INTERFACE_SKELETON (l->data);
Packit ae235b
      registration_data_export_interface (data, interface_skeleton, object_path);
Packit ae235b
      g_ptr_array_add (interface_names, g_dbus_interface_skeleton_get_info (interface_skeleton)->name);
Packit ae235b
    }
Packit ae235b
  g_list_free_full (existing_interfaces, g_object_unref);
Packit ae235b
  g_ptr_array_add (interface_names, NULL);
Packit ae235b
Packit ae235b
  data->exported = TRUE;
Packit ae235b
Packit ae235b
  /* now emit InterfacesAdded() for all the interfaces */
Packit ae235b
  g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata, object_path);
Packit ae235b
  g_ptr_array_unref (interface_names);
Packit ae235b
Packit ae235b
  g_hash_table_insert (manager->priv->map_object_path_to_data,
Packit ae235b
                       g_strdup (object_path),
Packit ae235b
                       data);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_dbus_object_manager_server_export:
Packit ae235b
 * @manager: A #GDBusObjectManagerServer.
Packit ae235b
 * @object: A #GDBusObjectSkeleton.
Packit ae235b
 *
Packit ae235b
 * Exports @object on @manager.
Packit ae235b
 *
Packit ae235b
 * If there is already a #GDBusObject exported at the object path,
Packit ae235b
 * then the old object is removed.
Packit ae235b
 *
Packit ae235b
 * The object path for @object must be in the hierarchy rooted by the
Packit ae235b
 * object path for @manager.
Packit ae235b
 *
Packit ae235b
 * Note that @manager will take a reference on @object for as long as
Packit ae235b
 * it is exported.
Packit ae235b
 *
Packit ae235b
 * Since: 2.30
Packit ae235b
 */
Packit ae235b
void
Packit ae235b
g_dbus_object_manager_server_export (GDBusObjectManagerServer  *manager,
Packit ae235b
                                     GDBusObjectSkeleton       *object)
Packit ae235b
{
Packit ae235b
  g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
  g_dbus_object_manager_server_export_unlocked (manager, object,
Packit ae235b
                                                g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_dbus_object_manager_server_export_uniquely:
Packit ae235b
 * @manager: A #GDBusObjectManagerServer.
Packit ae235b
 * @object: An object.
Packit ae235b
 *
Packit ae235b
 * Like g_dbus_object_manager_server_export() but appends a string of
Packit ae235b
 * the form _N (with N being a natural number) to @object's object path
Packit ae235b
 * if an object with the given path already exists. As such, the
Packit ae235b
 * #GDBusObjectProxy:g-object-path property of @object may be modified.
Packit ae235b
 *
Packit ae235b
 * Since: 2.30
Packit ae235b
 */
Packit ae235b
void
Packit ae235b
g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager,
Packit ae235b
                                              GDBusObjectSkeleton      *object)
Packit ae235b
{
Packit ae235b
  gchar *orig_object_path;
Packit ae235b
  gchar *object_path;
Packit ae235b
  guint count;
Packit ae235b
  gboolean modified;
Packit ae235b
Packit ae235b
  orig_object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
Packit ae235b
Packit ae235b
  g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
Packit ae235b
  g_return_if_fail (G_IS_DBUS_OBJECT (object));
Packit ae235b
  g_return_if_fail (g_str_has_prefix (orig_object_path, manager->priv->object_path_ending_in_slash));
Packit ae235b
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  object_path = g_strdup (orig_object_path);
Packit ae235b
  count = 1;
Packit ae235b
  modified = FALSE;
Packit ae235b
  while (TRUE)
Packit ae235b
    {
Packit ae235b
      RegistrationData *data;
Packit ae235b
      data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
Packit ae235b
      if (data == NULL)
Packit ae235b
        {
Packit ae235b
          break;
Packit ae235b
        }
Packit ae235b
      g_free (object_path);
Packit ae235b
      object_path = g_strdup_printf ("%s_%d", orig_object_path, count++);
Packit ae235b
      modified = TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_dbus_object_manager_server_export_unlocked (manager, object, object_path);
Packit ae235b
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  if (modified)
Packit ae235b
    g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path);
Packit ae235b
Packit ae235b
  g_free (object_path);
Packit ae235b
  g_free (orig_object_path);
Packit ae235b
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_dbus_object_manager_server_is_exported:
Packit ae235b
 * @manager: A #GDBusObjectManagerServer.
Packit ae235b
 * @object: An object.
Packit ae235b
 *
Packit ae235b
 * Returns whether @object is currently exported on @manager.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @object is exported
Packit ae235b
 *
Packit ae235b
 * Since: 2.34
Packit ae235b
 **/
Packit ae235b
gboolean
Packit ae235b
g_dbus_object_manager_server_is_exported (GDBusObjectManagerServer *manager,
Packit ae235b
                                          GDBusObjectSkeleton      *object)
Packit ae235b
{
Packit ae235b
  RegistrationData *data = NULL;
Packit ae235b
  const gchar *object_path;
Packit ae235b
  gboolean object_is_exported;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
Packit ae235b
  g_return_val_if_fail (G_IS_DBUS_OBJECT (object), FALSE);
Packit ae235b
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
Packit ae235b
  if (object_path != NULL)
Packit ae235b
    data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
Packit ae235b
  object_is_exported = (data != NULL);
Packit ae235b
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  return object_is_exported;
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer  *manager,
Packit ae235b
                                                const gchar               *object_path)
Packit ae235b
{
Packit ae235b
  RegistrationData *data;
Packit ae235b
  gboolean ret;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
Packit ae235b
  g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
Packit ae235b
  g_return_val_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash), FALSE);
Packit ae235b
Packit ae235b
  ret = FALSE;
Packit ae235b
Packit ae235b
  data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
Packit ae235b
  if (data != NULL)
Packit ae235b
    {
Packit ae235b
      GPtrArray *interface_names;
Packit ae235b
      GHashTableIter iter;
Packit ae235b
      const gchar *iface_name;
Packit ae235b
Packit ae235b
      interface_names = g_ptr_array_new ();
Packit ae235b
      g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
Packit ae235b
      while (g_hash_table_iter_next (&iter, (gpointer) &iface_name, NULL))
Packit ae235b
        g_ptr_array_add (interface_names, (gpointer) iface_name);
Packit ae235b
      g_ptr_array_add (interface_names, NULL);
Packit ae235b
      /* now emit InterfacesRemoved() for all the interfaces */
Packit ae235b
      g_dbus_object_manager_server_emit_interfaces_removed (manager, data, (const gchar *const *) interface_names->pdata);
Packit ae235b
      g_ptr_array_unref (interface_names);
Packit ae235b
Packit ae235b
      g_hash_table_remove (manager->priv->map_object_path_to_data, object_path);
Packit ae235b
      ret = TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_dbus_object_manager_server_unexport:
Packit ae235b
 * @manager: A #GDBusObjectManagerServer.
Packit ae235b
 * @object_path: An object path.
Packit ae235b
 *
Packit ae235b
 * If @manager has an object at @path, removes the object. Otherwise
Packit ae235b
 * does nothing.
Packit ae235b
 *
Packit ae235b
 * Note that @object_path must be in the hierarchy rooted by the
Packit ae235b
 * object path for @manager.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
Packit ae235b
 *
Packit ae235b
 * Since: 2.30
Packit ae235b
 */
Packit ae235b
gboolean
Packit ae235b
g_dbus_object_manager_server_unexport (GDBusObjectManagerServer  *manager,
Packit ae235b
                                       const gchar         *object_path)
Packit ae235b
{
Packit ae235b
  gboolean ret;
Packit ae235b
  g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
  ret = g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static const GDBusArgInfo manager_interfaces_added_signal_info_arg0 =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "object_path",
Packit ae235b
  "o",
Packit ae235b
  (GDBusAnnotationInfo**) NULL,
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusArgInfo manager_interfaces_added_signal_info_arg1 =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "interfaces_and_properties",
Packit ae235b
  "a{sa{sv}}",
Packit ae235b
  (GDBusAnnotationInfo**) NULL,
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusArgInfo * const manager_interfaces_added_signal_info_arg_pointers[] =
Packit ae235b
{
Packit ae235b
  &manager_interfaces_added_signal_info_arg0,
Packit ae235b
  &manager_interfaces_added_signal_info_arg1,
Packit ae235b
  NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusSignalInfo manager_interfaces_added_signal_info =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "InterfacesAdded",
Packit ae235b
  (GDBusArgInfo**) &manager_interfaces_added_signal_info_arg_pointers,
Packit ae235b
  (GDBusAnnotationInfo**) NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
/* ---------- */
Packit ae235b
Packit ae235b
static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0 =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "object_path",
Packit ae235b
  "o",
Packit ae235b
  (GDBusAnnotationInfo**) NULL,
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1 =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "interfaces",
Packit ae235b
  "as",
Packit ae235b
  (GDBusAnnotationInfo**) NULL,
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusArgInfo * const manager_interfaces_removed_signal_info_arg_pointers[] =
Packit ae235b
{
Packit ae235b
  &manager_interfaces_removed_signal_info_arg0,
Packit ae235b
  &manager_interfaces_removed_signal_info_arg1,
Packit ae235b
  NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusSignalInfo manager_interfaces_removed_signal_info =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "InterfacesRemoved",
Packit ae235b
  (GDBusArgInfo**) &manager_interfaces_removed_signal_info_arg_pointers,
Packit ae235b
  (GDBusAnnotationInfo**) NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
/* ---------- */
Packit ae235b
Packit ae235b
static const GDBusSignalInfo * const manager_signal_info_pointers[] =
Packit ae235b
{
Packit ae235b
  &manager_interfaces_added_signal_info,
Packit ae235b
  &manager_interfaces_removed_signal_info,
Packit ae235b
  NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
/* ---------- */
Packit ae235b
Packit ae235b
static const GDBusArgInfo manager_get_all_method_info_out_arg0 =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "object_paths_interfaces_and_properties",
Packit ae235b
  "a{oa{sa{sv}}}",
Packit ae235b
  (GDBusAnnotationInfo**) NULL,
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusArgInfo * const manager_get_all_method_info_out_arg_pointers[] =
Packit ae235b
{
Packit ae235b
  &manager_get_all_method_info_out_arg0,
Packit ae235b
  NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusMethodInfo manager_get_all_method_info =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "GetManagedObjects",
Packit ae235b
  (GDBusArgInfo**) NULL,
Packit ae235b
  (GDBusArgInfo**) &manager_get_all_method_info_out_arg_pointers,
Packit ae235b
  (GDBusAnnotationInfo**) NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
static const GDBusMethodInfo * const manager_method_info_pointers[] =
Packit ae235b
{
Packit ae235b
  &manager_get_all_method_info,
Packit ae235b
  NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
/* ---------- */
Packit ae235b
Packit ae235b
static const GDBusInterfaceInfo manager_interface_info =
Packit ae235b
{
Packit ae235b
  -1,
Packit ae235b
  "org.freedesktop.DBus.ObjectManager",
Packit ae235b
  (GDBusMethodInfo **) manager_method_info_pointers,
Packit ae235b
  (GDBusSignalInfo **) manager_signal_info_pointers,
Packit ae235b
  (GDBusPropertyInfo **) NULL,
Packit ae235b
  (GDBusAnnotationInfo **) NULL
Packit ae235b
};
Packit ae235b
Packit ae235b
static void
Packit ae235b
manager_method_call (GDBusConnection       *connection,
Packit ae235b
                     const gchar           *sender,
Packit ae235b
                     const gchar           *object_path,
Packit ae235b
                     const gchar           *interface_name,
Packit ae235b
                     const gchar           *method_name,
Packit ae235b
                     GVariant              *parameters,
Packit ae235b
                     GDBusMethodInvocation *invocation,
Packit ae235b
                     gpointer               user_data)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (user_data);
Packit ae235b
  GVariantBuilder array_builder;
Packit ae235b
  GHashTableIter object_iter;
Packit ae235b
  RegistrationData *data;
Packit ae235b
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  if (g_strcmp0 (method_name, "GetManagedObjects") == 0)
Packit ae235b
    {
Packit ae235b
      g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
Packit ae235b
      g_hash_table_iter_init (&object_iter, manager->priv->map_object_path_to_data);
Packit ae235b
      while (g_hash_table_iter_next (&object_iter, NULL, (gpointer) &data))
Packit ae235b
        {
Packit ae235b
          GVariantBuilder interfaces_builder;
Packit ae235b
          GHashTableIter interface_iter;
Packit ae235b
          GDBusInterfaceSkeleton *iface;
Packit ae235b
          const gchar *iter_object_path;
Packit ae235b
Packit ae235b
          g_variant_builder_init (&interfaces_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
Packit ae235b
          g_hash_table_iter_init (&interface_iter, data->map_iface_name_to_iface);
Packit ae235b
          while (g_hash_table_iter_next (&interface_iter, NULL, (gpointer) &iface))
Packit ae235b
            {
Packit ae235b
              GVariant *properties = g_dbus_interface_skeleton_get_properties (iface);
Packit ae235b
              g_variant_builder_add (&interfaces_builder, "{s@a{sv}}",
Packit ae235b
                                     g_dbus_interface_skeleton_get_info (iface)->name,
Packit ae235b
                                     properties);
Packit ae235b
              g_variant_unref (properties);
Packit ae235b
            }
Packit ae235b
          iter_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
Packit ae235b
          g_variant_builder_add (&array_builder,
Packit ae235b
                                 "{oa{sa{sv}}}",
Packit ae235b
                                 iter_object_path,
Packit ae235b
                                 &interfaces_builder);
Packit ae235b
        }
Packit ae235b
Packit ae235b
      g_dbus_method_invocation_return_value (invocation,
Packit ae235b
                                             g_variant_new ("(a{oa{sa{sv}}})",
Packit ae235b
                                                            &array_builder));
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
                                             G_DBUS_ERROR,
Packit ae235b
                                             G_DBUS_ERROR_UNKNOWN_METHOD,
Packit ae235b
                                             "Unknown method %s - only GetManagedObjects() is supported",
Packit ae235b
                                             method_name);
Packit ae235b
    }
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
}
Packit ae235b
Packit ae235b
static const GDBusInterfaceVTable manager_interface_vtable =
Packit ae235b
{
Packit ae235b
  manager_method_call, /* handle_method_call */
Packit ae235b
  NULL, /* get_property */
Packit ae235b
  NULL  /* set_property */
Packit ae235b
};
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_constructed (GObject *object)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
Packit ae235b
Packit ae235b
  if (manager->priv->connection != NULL)
Packit ae235b
    export_all (manager);
Packit ae235b
Packit ae235b
  if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed != NULL)
Packit ae235b
    G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed (object);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
Packit ae235b
                                                    RegistrationData   *data,
Packit ae235b
                                                    const gchar *const *interfaces,
Packit ae235b
                                                    const gchar *object_path)
Packit ae235b
{
Packit ae235b
  GVariantBuilder array_builder;
Packit ae235b
  GError *error;
Packit ae235b
  guint n;
Packit ae235b
Packit ae235b
  if (data->manager->priv->connection == NULL)
Packit ae235b
    goto out;
Packit ae235b
Packit ae235b
  g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
Packit ae235b
  for (n = 0; interfaces[n] != NULL; n++)
Packit ae235b
    {
Packit ae235b
      GDBusInterfaceSkeleton *iface;
Packit ae235b
      GVariant *properties;
Packit ae235b
Packit ae235b
      iface = g_hash_table_lookup (data->map_iface_name_to_iface, interfaces[n]);
Packit ae235b
      g_assert (iface != NULL);
Packit ae235b
      properties = g_dbus_interface_skeleton_get_properties (iface);
Packit ae235b
      g_variant_builder_add (&array_builder, "{s@a{sv}}", interfaces[n], properties);
Packit ae235b
      g_variant_unref (properties);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  error = NULL;
Packit ae235b
  g_dbus_connection_emit_signal (data->manager->priv->connection,
Packit ae235b
                                 NULL, /* destination_bus_name */
Packit ae235b
                                 manager->priv->object_path,
Packit ae235b
                                 manager_interface_info.name,
Packit ae235b
                                 "InterfacesAdded",
Packit ae235b
                                 g_variant_new ("(oa{sa{sv}})",
Packit ae235b
                                                object_path,
Packit ae235b
                                                &array_builder),
Packit ae235b
                                 &error);
Packit ae235b
  if (error)
Packit ae235b
    {
Packit ae235b
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
Packit ae235b
        g_warning ("Couldn't emit InterfacesAdded signal: %s", error->message);
Packit ae235b
      g_error_free (error);
Packit ae235b
    }
Packit ae235b
 out:
Packit ae235b
  ;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
Packit ae235b
                                                      RegistrationData   *data,
Packit ae235b
                                                      const gchar *const *interfaces)
Packit ae235b
{
Packit ae235b
  GVariantBuilder array_builder;
Packit ae235b
  GError *error;
Packit ae235b
  guint n;
Packit ae235b
  const gchar *object_path;
Packit ae235b
Packit ae235b
  if (data->manager->priv->connection == NULL)
Packit ae235b
    goto out;
Packit ae235b
Packit ae235b
  g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
Packit ae235b
  for (n = 0; interfaces[n] != NULL; n++)
Packit ae235b
    g_variant_builder_add (&array_builder, "s", interfaces[n]);
Packit ae235b
Packit ae235b
  error = NULL;
Packit ae235b
  object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
Packit ae235b
  g_dbus_connection_emit_signal (data->manager->priv->connection,
Packit ae235b
                                 NULL, /* destination_bus_name */
Packit ae235b
                                 manager->priv->object_path,
Packit ae235b
                                 manager_interface_info.name,
Packit ae235b
                                 "InterfacesRemoved",
Packit ae235b
                                 g_variant_new ("(oas)",
Packit ae235b
                                                object_path,
Packit ae235b
                                                &array_builder),
Packit ae235b
                                 &error);
Packit ae235b
  if (error)
Packit ae235b
    {
Packit ae235b
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
Packit ae235b
        g_warning ("Couldn't emit InterfacesRemoved signal: %s", error->message);
Packit ae235b
      g_error_free (error);
Packit ae235b
    }
Packit ae235b
 out:
Packit ae235b
  ;
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static GList *
Packit ae235b
g_dbus_object_manager_server_get_objects (GDBusObjectManager  *_manager)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
Packit ae235b
  GList *ret;
Packit ae235b
  GHashTableIter iter;
Packit ae235b
  RegistrationData *data;
Packit ae235b
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  ret = NULL;
Packit ae235b
  g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
Packit ae235b
  while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
Packit ae235b
    {
Packit ae235b
      ret = g_list_prepend (ret, g_object_ref (data->object));
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
static const gchar *
Packit ae235b
g_dbus_object_manager_server_get_object_path (GDBusObjectManager *_manager)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
Packit ae235b
  return manager->priv->object_path;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GDBusObject *
Packit ae235b
g_dbus_object_manager_server_get_object (GDBusObjectManager *_manager,
Packit ae235b
                                         const gchar        *object_path)
Packit ae235b
{
Packit ae235b
  GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
Packit ae235b
  GDBusObject *ret;
Packit ae235b
  RegistrationData *data;
Packit ae235b
Packit ae235b
  ret = NULL;
Packit ae235b
Packit ae235b
  g_mutex_lock (&manager->priv->lock);
Packit ae235b
  data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
Packit ae235b
  if (data != NULL)
Packit ae235b
    ret = g_object_ref (G_DBUS_OBJECT (data->object));
Packit ae235b
  g_mutex_unlock (&manager->priv->lock);
Packit ae235b
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GDBusInterface *
Packit ae235b
g_dbus_object_manager_server_get_interface  (GDBusObjectManager  *_manager,
Packit ae235b
                                             const gchar         *object_path,
Packit ae235b
                                             const gchar         *interface_name)
Packit ae235b
{
Packit ae235b
  GDBusInterface *ret;
Packit ae235b
  GDBusObject *object;
Packit ae235b
Packit ae235b
  ret = NULL;
Packit ae235b
Packit ae235b
  object = g_dbus_object_manager_get_object (_manager, object_path);
Packit ae235b
  if (object == NULL)
Packit ae235b
    goto out;
Packit ae235b
Packit ae235b
  ret = g_dbus_object_get_interface (object, interface_name);
Packit ae235b
  g_object_unref (object);
Packit ae235b
Packit ae235b
 out:
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
Packit ae235b
{
Packit ae235b
  iface->get_object_path = g_dbus_object_manager_server_get_object_path;
Packit ae235b
  iface->get_objects     = g_dbus_object_manager_server_get_objects;
Packit ae235b
  iface->get_object      = g_dbus_object_manager_server_get_object;
Packit ae235b
  iface->get_interface   = g_dbus_object_manager_server_get_interface;
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */
Packit ae235b
Packit ae235b
static void
Packit ae235b
export_all (GDBusObjectManagerServer *manager)
Packit ae235b
{
Packit ae235b
  GHashTableIter iter;
Packit ae235b
  const gchar *object_path;
Packit ae235b
  RegistrationData *data;
Packit ae235b
  GHashTableIter iface_iter;
Packit ae235b
  GDBusInterfaceSkeleton *iface;
Packit ae235b
  GError *error;
Packit ae235b
Packit ae235b
  g_return_if_fail (manager->priv->connection != NULL);
Packit ae235b
Packit ae235b
  error = NULL;
Packit ae235b
  g_warn_if_fail (manager->priv->manager_reg_id == 0);
Packit ae235b
  manager->priv->manager_reg_id = g_dbus_connection_register_object (manager->priv->connection,
Packit ae235b
                                                                     manager->priv->object_path,
Packit ae235b
                                                                     (GDBusInterfaceInfo *) &manager_interface_info,
Packit ae235b
                                                                     &manager_interface_vtable,
Packit ae235b
                                                                     manager,
Packit ae235b
                                                                     NULL, /* user_data_free_func */
Packit ae235b
                                                                     &error);
Packit ae235b
  if (manager->priv->manager_reg_id == 0)
Packit ae235b
    {
Packit ae235b
      g_warning ("%s: Error registering manager at %s: %s",
Packit ae235b
                 G_STRLOC,
Packit ae235b
                 manager->priv->object_path,
Packit ae235b
                 error->message);
Packit ae235b
      g_error_free (error);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
Packit ae235b
  while (g_hash_table_iter_next (&iter, (gpointer) &object_path, (gpointer) &data))
Packit ae235b
    {
Packit ae235b
      g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
Packit ae235b
      while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
Packit ae235b
        {
Packit ae235b
          g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) == NULL);
Packit ae235b
          error = NULL;
Packit ae235b
          if (!g_dbus_interface_skeleton_export (iface,
Packit ae235b
                                                 manager->priv->connection,
Packit ae235b
                                                 object_path,
Packit ae235b
                                                 &error))
Packit ae235b
            {
Packit ae235b
              g_warning ("%s: Error registering object at %s with interface %s: %s",
Packit ae235b
                         G_STRLOC,
Packit ae235b
                         object_path,
Packit ae235b
                         g_dbus_interface_skeleton_get_info (iface)->name,
Packit ae235b
                         error->message);
Packit ae235b
              g_error_free (error);
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager)
Packit ae235b
{
Packit ae235b
  GHashTableIter iter;
Packit ae235b
  RegistrationData *data;
Packit ae235b
  GHashTableIter iface_iter;
Packit ae235b
  GDBusInterfaceSkeleton *iface;
Packit ae235b
Packit ae235b
  g_return_if_fail (manager->priv->connection != NULL);
Packit ae235b
Packit ae235b
  g_warn_if_fail (manager->priv->manager_reg_id > 0);
Packit ae235b
  if (manager->priv->manager_reg_id > 0)
Packit ae235b
    {
Packit ae235b
      g_warn_if_fail (g_dbus_connection_unregister_object (manager->priv->connection,
Packit ae235b
                                                           manager->priv->manager_reg_id));
Packit ae235b
      manager->priv->manager_reg_id = 0;
Packit ae235b
    }
Packit ae235b
  if (only_manager)
Packit ae235b
    goto out;
Packit ae235b
Packit ae235b
  g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
Packit ae235b
  while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
Packit ae235b
    {
Packit ae235b
      g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
Packit ae235b
      while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
Packit ae235b
        {
Packit ae235b
          g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) != NULL);
Packit ae235b
          g_dbus_interface_skeleton_unexport (iface);
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
 out:
Packit ae235b
  ;
Packit ae235b
}
Packit ae235b
Packit ae235b
/* ---------------------------------------------------------------------------------------------------- */