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