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 "gdbusobject.h"
26 : : #include "gdbusobjectproxy.h"
27 : : #include "gdbusconnection.h"
28 : : #include "gdbusprivate.h"
29 : : #include "gdbusutils.h"
30 : : #include "gdbusproxy.h"
31 : :
32 : : #include "glibintl.h"
33 : :
34 : : /**
35 : : * GDBusObjectProxy:
36 : : *
37 : : * A `GDBusObjectProxy` is an object used to represent a remote object
38 : : * with one or more D-Bus interfaces. Normally, you don’t instantiate
39 : : * a `GDBusObjectProxy` yourself — typically [class@Gio.DBusObjectManagerClient]
40 : : * is used to obtain it.
41 : : *
42 : : * Since: 2.30
43 : : */
44 : :
45 : : struct _GDBusObjectProxyPrivate
46 : : {
47 : : GMutex lock;
48 : : GHashTable *map_name_to_iface;
49 : : gchar *object_path;
50 : : GDBusConnection *connection;
51 : : };
52 : :
53 : : enum
54 : : {
55 : : PROP_0,
56 : : PROP_G_OBJECT_PATH,
57 : : PROP_G_CONNECTION
58 : : };
59 : :
60 : : static void dbus_object_interface_init (GDBusObjectIface *iface);
61 : :
62 : 333 : G_DEFINE_TYPE_WITH_CODE (GDBusObjectProxy, g_dbus_object_proxy, G_TYPE_OBJECT,
63 : : G_ADD_PRIVATE (GDBusObjectProxy)
64 : : G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, dbus_object_interface_init))
65 : :
66 : : static void
67 : 23 : g_dbus_object_proxy_finalize (GObject *object)
68 : : {
69 : 23 : GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
70 : :
71 : 23 : g_hash_table_unref (proxy->priv->map_name_to_iface);
72 : :
73 : 23 : g_clear_object (&proxy->priv->connection);
74 : :
75 : 23 : g_free (proxy->priv->object_path);
76 : :
77 : 23 : g_mutex_clear (&proxy->priv->lock);
78 : :
79 : 23 : if (G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize != NULL)
80 : 23 : G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize (object);
81 : 23 : }
82 : :
83 : : static void
84 : 2 : g_dbus_object_proxy_get_property (GObject *object,
85 : : guint prop_id,
86 : : GValue *value,
87 : : GParamSpec *pspec)
88 : : {
89 : 2 : GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
90 : :
91 : 2 : switch (prop_id)
92 : : {
93 : 1 : case PROP_G_OBJECT_PATH:
94 : 1 : g_mutex_lock (&proxy->priv->lock);
95 : 1 : g_value_set_string (value, proxy->priv->object_path);
96 : 1 : g_mutex_unlock (&proxy->priv->lock);
97 : 1 : break;
98 : :
99 : 1 : case PROP_G_CONNECTION:
100 : 1 : g_value_set_object (value, g_dbus_object_proxy_get_connection (proxy));
101 : 1 : break;
102 : :
103 : 0 : default:
104 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
105 : 0 : break;
106 : : }
107 : 2 : }
108 : :
109 : : static void
110 : 46 : g_dbus_object_proxy_set_property (GObject *object,
111 : : guint prop_id,
112 : : const GValue *value,
113 : : GParamSpec *pspec)
114 : : {
115 : 46 : GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
116 : :
117 : 46 : switch (prop_id)
118 : : {
119 : 23 : case PROP_G_OBJECT_PATH:
120 : 23 : g_mutex_lock (&proxy->priv->lock);
121 : 23 : proxy->priv->object_path = g_value_dup_string (value);
122 : 23 : g_mutex_unlock (&proxy->priv->lock);
123 : 23 : break;
124 : :
125 : 23 : case PROP_G_CONNECTION:
126 : 23 : g_mutex_lock (&proxy->priv->lock);
127 : 23 : proxy->priv->connection = g_value_dup_object (value);
128 : 23 : g_mutex_unlock (&proxy->priv->lock);
129 : 23 : break;
130 : :
131 : 0 : default:
132 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
133 : 0 : break;
134 : : }
135 : 46 : }
136 : :
137 : : static void
138 : 6 : g_dbus_object_proxy_class_init (GDBusObjectProxyClass *klass)
139 : : {
140 : 6 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
141 : :
142 : 6 : gobject_class->finalize = g_dbus_object_proxy_finalize;
143 : 6 : gobject_class->set_property = g_dbus_object_proxy_set_property;
144 : 6 : gobject_class->get_property = g_dbus_object_proxy_get_property;
145 : :
146 : : /**
147 : : * GDBusObjectProxy:g-object-path:
148 : : *
149 : : * The object path of the proxy.
150 : : *
151 : : * Since: 2.30
152 : : */
153 : 6 : g_object_class_install_property (gobject_class,
154 : : PROP_G_OBJECT_PATH,
155 : : g_param_spec_string ("g-object-path", NULL, NULL,
156 : : NULL,
157 : : G_PARAM_READWRITE |
158 : : G_PARAM_CONSTRUCT_ONLY |
159 : : G_PARAM_STATIC_STRINGS));
160 : :
161 : : /**
162 : : * GDBusObjectProxy:g-connection:
163 : : *
164 : : * The connection of the proxy.
165 : : *
166 : : * Since: 2.30
167 : : */
168 : 6 : g_object_class_install_property (gobject_class,
169 : : PROP_G_CONNECTION,
170 : : g_param_spec_object ("g-connection", NULL, NULL,
171 : : G_TYPE_DBUS_CONNECTION,
172 : : G_PARAM_READWRITE |
173 : : G_PARAM_CONSTRUCT_ONLY |
174 : : G_PARAM_STATIC_STRINGS));
175 : 6 : }
176 : :
177 : : static void
178 : 23 : g_dbus_object_proxy_init (GDBusObjectProxy *proxy)
179 : : {
180 : 23 : proxy->priv = g_dbus_object_proxy_get_instance_private (proxy);
181 : 23 : g_mutex_init (&proxy->priv->lock);
182 : 23 : proxy->priv->map_name_to_iface = g_hash_table_new_full (g_str_hash,
183 : : g_str_equal,
184 : : g_free,
185 : : (GDestroyNotify) g_object_unref);
186 : 23 : }
187 : :
188 : : static const gchar *
189 : 6 : g_dbus_object_proxy_get_object_path (GDBusObject *object)
190 : : {
191 : 6 : GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
192 : : const gchar *ret;
193 : 6 : g_mutex_lock (&proxy->priv->lock);
194 : 6 : ret = proxy->priv->object_path;
195 : 6 : g_mutex_unlock (&proxy->priv->lock);
196 : 6 : return ret;
197 : : }
198 : :
199 : : /**
200 : : * g_dbus_object_proxy_get_connection:
201 : : * @proxy: a #GDBusObjectProxy
202 : : *
203 : : * Gets the connection that @proxy is for.
204 : : *
205 : : * Returns: (transfer none): A #GDBusConnection. Do not free, the
206 : : * object is owned by @proxy.
207 : : *
208 : : * Since: 2.30
209 : : */
210 : : GDBusConnection *
211 : 1 : g_dbus_object_proxy_get_connection (GDBusObjectProxy *proxy)
212 : : {
213 : : GDBusConnection *ret;
214 : 1 : g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
215 : 1 : g_mutex_lock (&proxy->priv->lock);
216 : 1 : ret = proxy->priv->connection;
217 : 1 : g_mutex_unlock (&proxy->priv->lock);
218 : 1 : return ret;
219 : : }
220 : :
221 : : static GDBusInterface *
222 : 46 : g_dbus_object_proxy_get_interface (GDBusObject *object,
223 : : const gchar *interface_name)
224 : : {
225 : 46 : GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
226 : : GDBusProxy *ret;
227 : :
228 : 46 : g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
229 : 46 : g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
230 : :
231 : 46 : g_mutex_lock (&proxy->priv->lock);
232 : 46 : ret = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
233 : 46 : if (ret != NULL)
234 : 37 : g_object_ref (ret);
235 : 46 : g_mutex_unlock (&proxy->priv->lock);
236 : :
237 : 46 : return (GDBusInterface *) ret; /* TODO: proper cast */
238 : : }
239 : :
240 : : static GList *
241 : 21 : g_dbus_object_proxy_get_interfaces (GDBusObject *object)
242 : : {
243 : 21 : GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
244 : : GList *ret;
245 : :
246 : 21 : g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
247 : :
248 : 21 : ret = NULL;
249 : :
250 : 21 : g_mutex_lock (&proxy->priv->lock);
251 : 21 : ret = g_hash_table_get_values (proxy->priv->map_name_to_iface);
252 : 21 : g_list_foreach (ret, (GFunc) g_object_ref, NULL);
253 : 21 : g_mutex_unlock (&proxy->priv->lock);
254 : :
255 : 21 : return ret;
256 : : }
257 : :
258 : : /* ---------------------------------------------------------------------------------------------------- */
259 : :
260 : : /**
261 : : * g_dbus_object_proxy_new:
262 : : * @connection: a #GDBusConnection
263 : : * @object_path: the object path
264 : : *
265 : : * Creates a new #GDBusObjectProxy for the given connection and
266 : : * object path.
267 : : *
268 : : * Returns: a new #GDBusObjectProxy
269 : : *
270 : : * Since: 2.30
271 : : */
272 : : GDBusObjectProxy *
273 : 0 : g_dbus_object_proxy_new (GDBusConnection *connection,
274 : : const gchar *object_path)
275 : : {
276 : 0 : g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
277 : 0 : g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
278 : 0 : return G_DBUS_OBJECT_PROXY (g_object_new (G_TYPE_DBUS_OBJECT_PROXY,
279 : : "g-object-path", object_path,
280 : : "g-connection", connection,
281 : : NULL));
282 : : }
283 : :
284 : : void
285 : 28 : _g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy,
286 : : GDBusProxy *interface_proxy)
287 : : {
288 : : const gchar *interface_name;
289 : : GDBusProxy *interface_proxy_to_remove;
290 : :
291 : 28 : g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
292 : 28 : g_return_if_fail (G_IS_DBUS_PROXY (interface_proxy));
293 : :
294 : 28 : g_mutex_lock (&proxy->priv->lock);
295 : :
296 : 28 : interface_name = g_dbus_proxy_get_interface_name (interface_proxy);
297 : 28 : interface_proxy_to_remove = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
298 : 28 : if (interface_proxy_to_remove != NULL)
299 : : {
300 : 0 : g_object_ref (interface_proxy_to_remove);
301 : 0 : g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
302 : : }
303 : 28 : g_hash_table_insert (proxy->priv->map_name_to_iface,
304 : 28 : g_strdup (interface_name),
305 : : g_object_ref (interface_proxy));
306 : 28 : g_object_ref (interface_proxy);
307 : :
308 : 28 : g_mutex_unlock (&proxy->priv->lock);
309 : :
310 : 28 : if (interface_proxy_to_remove != NULL)
311 : : {
312 : 0 : g_signal_emit_by_name (proxy, "interface-removed", interface_proxy_to_remove);
313 : 0 : g_object_unref (interface_proxy_to_remove);
314 : : }
315 : :
316 : 28 : g_signal_emit_by_name (proxy, "interface-added", interface_proxy);
317 : 28 : g_object_unref (interface_proxy);
318 : : }
319 : :
320 : : void
321 : 3 : _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy,
322 : : const gchar *interface_name)
323 : : {
324 : : GDBusProxy *interface_proxy;
325 : :
326 : 3 : g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
327 : 3 : g_return_if_fail (g_dbus_is_interface_name (interface_name));
328 : :
329 : 3 : g_mutex_lock (&proxy->priv->lock);
330 : :
331 : 3 : interface_proxy = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
332 : 3 : if (interface_proxy != NULL)
333 : : {
334 : 3 : g_object_ref (interface_proxy);
335 : 3 : g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
336 : 3 : g_mutex_unlock (&proxy->priv->lock);
337 : 3 : g_signal_emit_by_name (proxy, "interface-removed", interface_proxy);
338 : 3 : g_object_unref (interface_proxy);
339 : : }
340 : : else
341 : : {
342 : 0 : g_mutex_unlock (&proxy->priv->lock);
343 : : }
344 : : }
345 : :
346 : : static void
347 : 6 : dbus_object_interface_init (GDBusObjectIface *iface)
348 : : {
349 : 6 : iface->get_object_path = g_dbus_object_proxy_get_object_path;
350 : 6 : iface->get_interfaces = g_dbus_object_proxy_get_interfaces;
351 : 6 : iface->get_interface = g_dbus_object_proxy_get_interface;
352 : 6 : }
|