| /* GDBus - GLib D-Bus Library | |
| * | |
| * Copyright (C) 2008-2010 Red Hat, Inc. | |
| * | |
| * SPDX-License-Identifier: LGPL-2.1-or-later | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General | |
| * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
| * | |
| * Author: David Zeuthen <davidz@redhat.com> | |
| */ | |
| #include "config.h" | |
| #include "gdbusobject.h" | |
| #include "gdbusobjectproxy.h" | |
| #include "gdbusconnection.h" | |
| #include "gdbusprivate.h" | |
| #include "gdbusutils.h" | |
| #include "gdbusproxy.h" | |
| #include "glibintl.h" | |
| /** | |
| * GDBusObjectProxy: | |
| * | |
| * A `GDBusObjectProxy` is an object used to represent a remote object | |
| * with one or more D-Bus interfaces. Normally, you don’t instantiate | |
| * a `GDBusObjectProxy` yourself — typically [class@Gio.DBusObjectManagerClient] | |
| * is used to obtain it. | |
| * | |
| * Since: 2.30 | |
| */ | |
| struct _GDBusObjectProxyPrivate | |
| { | |
| GMutex lock; | |
| GHashTable *map_name_to_iface; | |
| gchar *object_path; | |
| GDBusConnection *connection; | |
| }; | |
| enum | |
| { | |
| PROP_0, | |
| PROP_G_OBJECT_PATH, | |
| PROP_G_CONNECTION | |
| }; | |
| static void dbus_object_interface_init (GDBusObjectIface *iface); | |
| G_DEFINE_TYPE_WITH_CODE (GDBusObjectProxy, g_dbus_object_proxy, G_TYPE_OBJECT, | |
| G_ADD_PRIVATE (GDBusObjectProxy) | |
| G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, dbus_object_interface_init)) | |
| static void | |
| g_dbus_object_proxy_finalize (GObject *object) | |
| { | |
| GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object); | |
| g_hash_table_unref (proxy->priv->map_name_to_iface); | |
| g_clear_object (&proxy->priv->connection); | |
| g_free (proxy->priv->object_path); | |
| g_mutex_clear (&proxy->priv->lock); | |
| if (G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize != NULL) | |
| G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize (object); | |
| } | |
| static void | |
| g_dbus_object_proxy_get_property (GObject *object, | |
| guint prop_id, | |
| GValue *value, | |
| GParamSpec *pspec) | |
| { | |
| GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object); | |
| switch (prop_id) | |
| { | |
| case PROP_G_OBJECT_PATH: | |
| g_mutex_lock (&proxy->priv->lock); | |
| g_value_set_string (value, proxy->priv->object_path); | |
| g_mutex_unlock (&proxy->priv->lock); | |
| break; | |
| case PROP_G_CONNECTION: | |
| g_value_set_object (value, g_dbus_object_proxy_get_connection (proxy)); | |
| break; | |
| default: | |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec); | |
| break; | |
| } | |
| } | |
| static void | |
| g_dbus_object_proxy_set_property (GObject *object, | |
| guint prop_id, | |
| const GValue *value, | |
| GParamSpec *pspec) | |
| { | |
| GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object); | |
| switch (prop_id) | |
| { | |
| case PROP_G_OBJECT_PATH: | |
| g_mutex_lock (&proxy->priv->lock); | |
| proxy->priv->object_path = g_value_dup_string (value); | |
| g_mutex_unlock (&proxy->priv->lock); | |
| break; | |
| case PROP_G_CONNECTION: | |
| g_mutex_lock (&proxy->priv->lock); | |
| proxy->priv->connection = g_value_dup_object (value); | |
| g_mutex_unlock (&proxy->priv->lock); | |
| break; | |
| default: | |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec); | |
| break; | |
| } | |
| } | |
| static void | |
| g_dbus_object_proxy_class_init (GDBusObjectProxyClass *klass) | |
| { | |
| GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | |
| gobject_class->finalize = g_dbus_object_proxy_finalize; | |
| gobject_class->set_property = g_dbus_object_proxy_set_property; | |
| gobject_class->get_property = g_dbus_object_proxy_get_property; | |
| /** | |
| * GDBusObjectProxy:g-object-path: | |
| * | |
| * The object path of the proxy. | |
| * | |
| * Since: 2.30 | |
| */ | |
| g_object_class_install_property (gobject_class, | |
| PROP_G_OBJECT_PATH, | |
| g_param_spec_string ("g-object-path", NULL, NULL, | |
| NULL, | |
| G_PARAM_READWRITE | | |
| G_PARAM_CONSTRUCT_ONLY | | |
| G_PARAM_STATIC_STRINGS)); | |
| /** | |
| * GDBusObjectProxy:g-connection: | |
| * | |
| * The connection of the proxy. | |
| * | |
| * Since: 2.30 | |
| */ | |
| g_object_class_install_property (gobject_class, | |
| PROP_G_CONNECTION, | |
| g_param_spec_object ("g-connection", NULL, NULL, | |
| G_TYPE_DBUS_CONNECTION, | |
| G_PARAM_READWRITE | | |
| G_PARAM_CONSTRUCT_ONLY | | |
| G_PARAM_STATIC_STRINGS)); | |
| } | |
| static void | |
| g_dbus_object_proxy_init (GDBusObjectProxy *proxy) | |
| { | |
| proxy->priv = g_dbus_object_proxy_get_instance_private (proxy); | |
| g_mutex_init (&proxy->priv->lock); | |
| proxy->priv->map_name_to_iface = g_hash_table_new_full (g_str_hash, | |
| g_str_equal, | |
| g_free, | |
| (GDestroyNotify) g_object_unref); | |
| } | |
| static const gchar * | |
| g_dbus_object_proxy_get_object_path (GDBusObject *object) | |
| { | |
| GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object); | |
| const gchar *ret; | |
| g_mutex_lock (&proxy->priv->lock); | |
| ret = proxy->priv->object_path; | |
| g_mutex_unlock (&proxy->priv->lock); | |
| return ret; | |
| } | |
| /** | |
| * g_dbus_object_proxy_get_connection: | |
| * @proxy: a #GDBusObjectProxy | |
| * | |
| * Gets the connection that @proxy is for. | |
| * | |
| * Returns: (transfer none): A #GDBusConnection. Do not free, the | |
| * object is owned by @proxy. | |
| * | |
| * Since: 2.30 | |
| */ | |
| GDBusConnection * | |
| g_dbus_object_proxy_get_connection (GDBusObjectProxy *proxy) | |
| { | |
| GDBusConnection *ret; | |
| g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL); | |
| g_mutex_lock (&proxy->priv->lock); | |
| ret = proxy->priv->connection; | |
| g_mutex_unlock (&proxy->priv->lock); | |
| return ret; | |
| } | |
| static GDBusInterface * | |
| g_dbus_object_proxy_get_interface (GDBusObject *object, | |
| const gchar *interface_name) | |
| { | |
| GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object); | |
| GDBusProxy *ret; | |
| g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL); | |
| g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL); | |
| g_mutex_lock (&proxy->priv->lock); | |
| ret = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name); | |
| if (ret != NULL) | |
| g_object_ref (ret); | |
| g_mutex_unlock (&proxy->priv->lock); | |
| return (GDBusInterface *) ret; /* TODO: proper cast */ | |
| } | |
| static GList * | |
| g_dbus_object_proxy_get_interfaces (GDBusObject *object) | |
| { | |
| GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object); | |
| GList *ret; | |
| g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL); | |
| ret = NULL; | |
| g_mutex_lock (&proxy->priv->lock); | |
| ret = g_hash_table_get_values (proxy->priv->map_name_to_iface); | |
| g_list_foreach (ret, (GFunc) g_object_ref, NULL); | |
| g_mutex_unlock (&proxy->priv->lock); | |
| return ret; | |
| } | |
| /* ---------------------------------------------------------------------------------------------------- */ | |
| /** | |
| * g_dbus_object_proxy_new: | |
| * @connection: a #GDBusConnection | |
| * @object_path: the object path | |
| * | |
| * Creates a new #GDBusObjectProxy for the given connection and | |
| * object path. | |
| * | |
| * Returns: a new #GDBusObjectProxy | |
| * | |
| * Since: 2.30 | |
| */ | |
| GDBusObjectProxy * | |
| g_dbus_object_proxy_new (GDBusConnection *connection, | |
| const gchar *object_path) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); | |
| g_return_val_if_fail (g_variant_is_object_path (object_path), NULL); | |
| return G_DBUS_OBJECT_PROXY (g_object_new (G_TYPE_DBUS_OBJECT_PROXY, | |
| "g-object-path", object_path, | |
| "g-connection", connection, | |
| NULL)); | |
| } | |
| void | |
| _g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy, | |
| GDBusProxy *interface_proxy) | |
| { | |
| const gchar *interface_name; | |
| GDBusProxy *interface_proxy_to_remove; | |
| g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy)); | |
| g_return_if_fail (G_IS_DBUS_PROXY (interface_proxy)); | |
| g_mutex_lock (&proxy->priv->lock); | |
| interface_name = g_dbus_proxy_get_interface_name (interface_proxy); | |
| interface_proxy_to_remove = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name); | |
| if (interface_proxy_to_remove != NULL) | |
| { | |
| g_object_ref (interface_proxy_to_remove); | |
| g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name)); | |
| } | |
| g_hash_table_insert (proxy->priv->map_name_to_iface, | |
| g_strdup (interface_name), | |
| g_object_ref (interface_proxy)); | |
| g_object_ref (interface_proxy); | |
| g_mutex_unlock (&proxy->priv->lock); | |
| if (interface_proxy_to_remove != NULL) | |
| { | |
| g_signal_emit_by_name (proxy, "interface-removed", interface_proxy_to_remove); | |
| g_object_unref (interface_proxy_to_remove); | |
| } | |
| g_signal_emit_by_name (proxy, "interface-added", interface_proxy); | |
| g_object_unref (interface_proxy); | |
| } | |
| void | |
| _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy, | |
| const gchar *interface_name) | |
| { | |
| GDBusProxy *interface_proxy; | |
| g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy)); | |
| g_return_if_fail (g_dbus_is_interface_name (interface_name)); | |
| g_mutex_lock (&proxy->priv->lock); | |
| interface_proxy = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name); | |
| if (interface_proxy != NULL) | |
| { | |
| g_object_ref (interface_proxy); | |
| g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name)); | |
| g_mutex_unlock (&proxy->priv->lock); | |
| g_signal_emit_by_name (proxy, "interface-removed", interface_proxy); | |
| g_object_unref (interface_proxy); | |
| } | |
| else | |
| { | |
| g_mutex_unlock (&proxy->priv->lock); | |
| } | |
| } | |
| static void | |
| dbus_object_interface_init (GDBusObjectIface *iface) | |
| { | |
| iface->get_object_path = g_dbus_object_proxy_get_object_path; | |
| iface->get_interfaces = g_dbus_object_proxy_get_interfaces; | |
| iface->get_interface = g_dbus_object_proxy_get_interface; | |
| } |