• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20 
21 #include "config.h"
22 
23 #include "gdbusobject.h"
24 #include "gdbusobjectproxy.h"
25 #include "gdbusconnection.h"
26 #include "gdbusprivate.h"
27 #include "gdbusutils.h"
28 #include "gdbusproxy.h"
29 
30 #include "glibintl.h"
31 
32 /**
33  * SECTION:gdbusobjectproxy
34  * @short_description: Client-side D-Bus object
35  * @include: gio/gio.h
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 #GDBusObjectManagerClient
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 
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))62 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 g_dbus_object_proxy_finalize (GObject *object)
68 {
69   GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
70 
71   g_hash_table_unref (proxy->priv->map_name_to_iface);
72 
73   g_clear_object (&proxy->priv->connection);
74 
75   g_free (proxy->priv->object_path);
76 
77   g_mutex_clear (&proxy->priv->lock);
78 
79   if (G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize != NULL)
80     G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize (object);
81 }
82 
83 static void
g_dbus_object_proxy_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)84 g_dbus_object_proxy_get_property (GObject    *object,
85                                   guint       prop_id,
86                                   GValue     *value,
87                                   GParamSpec *pspec)
88 {
89   GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
90 
91   switch (prop_id)
92     {
93     case PROP_G_OBJECT_PATH:
94       g_mutex_lock (&proxy->priv->lock);
95       g_value_set_string (value, proxy->priv->object_path);
96       g_mutex_unlock (&proxy->priv->lock);
97       break;
98 
99     case PROP_G_CONNECTION:
100       g_value_set_object (value, g_dbus_object_proxy_get_connection (proxy));
101       break;
102 
103     default:
104       G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
105       break;
106     }
107 }
108 
109 static void
g_dbus_object_proxy_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)110 g_dbus_object_proxy_set_property (GObject       *object,
111                                   guint          prop_id,
112                                   const GValue  *value,
113                                   GParamSpec    *pspec)
114 {
115   GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
116 
117   switch (prop_id)
118     {
119     case PROP_G_OBJECT_PATH:
120       g_mutex_lock (&proxy->priv->lock);
121       proxy->priv->object_path = g_value_dup_string (value);
122       g_mutex_unlock (&proxy->priv->lock);
123       break;
124 
125     case PROP_G_CONNECTION:
126       g_mutex_lock (&proxy->priv->lock);
127       proxy->priv->connection = g_value_dup_object (value);
128       g_mutex_unlock (&proxy->priv->lock);
129       break;
130 
131     default:
132       G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
133       break;
134     }
135 }
136 
137 static void
g_dbus_object_proxy_class_init(GDBusObjectProxyClass * klass)138 g_dbus_object_proxy_class_init (GDBusObjectProxyClass *klass)
139 {
140   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
141 
142   gobject_class->finalize     = g_dbus_object_proxy_finalize;
143   gobject_class->set_property = g_dbus_object_proxy_set_property;
144   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   g_object_class_install_property (gobject_class,
154                                    PROP_G_OBJECT_PATH,
155                                    g_param_spec_string ("g-object-path",
156                                                         "Object Path",
157                                                         "The object path of the proxy",
158                                                         NULL,
159                                                         G_PARAM_READWRITE |
160                                                         G_PARAM_CONSTRUCT_ONLY |
161                                                         G_PARAM_STATIC_STRINGS));
162 
163   /**
164    * GDBusObjectProxy:g-connection:
165    *
166    * The connection of the proxy.
167    *
168    * Since: 2.30
169    */
170   g_object_class_install_property (gobject_class,
171                                    PROP_G_CONNECTION,
172                                    g_param_spec_object ("g-connection",
173                                                         "Connection",
174                                                         "The connection of the proxy",
175                                                         G_TYPE_DBUS_CONNECTION,
176                                                         G_PARAM_READWRITE |
177                                                         G_PARAM_CONSTRUCT_ONLY |
178                                                         G_PARAM_STATIC_STRINGS));
179 }
180 
181 static void
g_dbus_object_proxy_init(GDBusObjectProxy * proxy)182 g_dbus_object_proxy_init (GDBusObjectProxy *proxy)
183 {
184   proxy->priv = g_dbus_object_proxy_get_instance_private (proxy);
185   g_mutex_init (&proxy->priv->lock);
186   proxy->priv->map_name_to_iface = g_hash_table_new_full (g_str_hash,
187                                                           g_str_equal,
188                                                           g_free,
189                                                           (GDestroyNotify) g_object_unref);
190 }
191 
192 static const gchar *
g_dbus_object_proxy_get_object_path(GDBusObject * object)193 g_dbus_object_proxy_get_object_path (GDBusObject *object)
194 {
195   GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
196   const gchar *ret;
197   g_mutex_lock (&proxy->priv->lock);
198   ret = proxy->priv->object_path;
199   g_mutex_unlock (&proxy->priv->lock);
200   return ret;
201 }
202 
203 /**
204  * g_dbus_object_proxy_get_connection:
205  * @proxy: a #GDBusObjectProxy
206  *
207  * Gets the connection that @proxy is for.
208  *
209  * Returns: (transfer none): A #GDBusConnection. Do not free, the
210  *   object is owned by @proxy.
211  *
212  * Since: 2.30
213  */
214 GDBusConnection *
g_dbus_object_proxy_get_connection(GDBusObjectProxy * proxy)215 g_dbus_object_proxy_get_connection (GDBusObjectProxy *proxy)
216 {
217   GDBusConnection *ret;
218   g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
219   g_mutex_lock (&proxy->priv->lock);
220   ret = proxy->priv->connection;
221   g_mutex_unlock (&proxy->priv->lock);
222   return ret;
223 }
224 
225 static GDBusInterface *
g_dbus_object_proxy_get_interface(GDBusObject * object,const gchar * interface_name)226 g_dbus_object_proxy_get_interface (GDBusObject *object,
227                                    const gchar *interface_name)
228 {
229   GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
230   GDBusProxy *ret;
231 
232   g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
233   g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
234 
235   g_mutex_lock (&proxy->priv->lock);
236   ret = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
237   if (ret != NULL)
238     g_object_ref (ret);
239   g_mutex_unlock (&proxy->priv->lock);
240 
241   return (GDBusInterface *) ret; /* TODO: proper cast */
242 }
243 
244 static GList *
g_dbus_object_proxy_get_interfaces(GDBusObject * object)245 g_dbus_object_proxy_get_interfaces (GDBusObject *object)
246 {
247   GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
248   GList *ret;
249 
250   g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
251 
252   ret = NULL;
253 
254   g_mutex_lock (&proxy->priv->lock);
255   ret = g_hash_table_get_values (proxy->priv->map_name_to_iface);
256   g_list_foreach (ret, (GFunc) g_object_ref, NULL);
257   g_mutex_unlock (&proxy->priv->lock);
258 
259   return ret;
260 }
261 
262 /* ---------------------------------------------------------------------------------------------------- */
263 
264 /**
265  * g_dbus_object_proxy_new:
266  * @connection: a #GDBusConnection
267  * @object_path: the object path
268  *
269  * Creates a new #GDBusObjectProxy for the given connection and
270  * object path.
271  *
272  * Returns: a new #GDBusObjectProxy
273  *
274  * Since: 2.30
275  */
276 GDBusObjectProxy *
g_dbus_object_proxy_new(GDBusConnection * connection,const gchar * object_path)277 g_dbus_object_proxy_new (GDBusConnection *connection,
278                          const gchar     *object_path)
279 {
280   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
281   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
282   return G_DBUS_OBJECT_PROXY (g_object_new (G_TYPE_DBUS_OBJECT_PROXY,
283                                             "g-object-path", object_path,
284                                             "g-connection", connection,
285                                             NULL));
286 }
287 
288 void
_g_dbus_object_proxy_add_interface(GDBusObjectProxy * proxy,GDBusProxy * interface_proxy)289 _g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy,
290                                     GDBusProxy       *interface_proxy)
291 {
292   const gchar *interface_name;
293   GDBusProxy *interface_proxy_to_remove;
294 
295   g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
296   g_return_if_fail (G_IS_DBUS_PROXY (interface_proxy));
297 
298   g_mutex_lock (&proxy->priv->lock);
299 
300   interface_name = g_dbus_proxy_get_interface_name (interface_proxy);
301   interface_proxy_to_remove = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
302   if (interface_proxy_to_remove != NULL)
303     {
304       g_object_ref (interface_proxy_to_remove);
305       g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
306     }
307   g_hash_table_insert (proxy->priv->map_name_to_iface,
308                        g_strdup (interface_name),
309                        g_object_ref (interface_proxy));
310   g_object_ref (interface_proxy);
311 
312   g_mutex_unlock (&proxy->priv->lock);
313 
314   if (interface_proxy_to_remove != NULL)
315     {
316       g_signal_emit_by_name (proxy, "interface-removed", interface_proxy_to_remove);
317       g_object_unref (interface_proxy_to_remove);
318     }
319 
320   g_signal_emit_by_name (proxy, "interface-added", interface_proxy);
321   g_object_unref (interface_proxy);
322 }
323 
324 void
_g_dbus_object_proxy_remove_interface(GDBusObjectProxy * proxy,const gchar * interface_name)325 _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy,
326                                        const gchar      *interface_name)
327 {
328   GDBusProxy *interface_proxy;
329 
330   g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
331   g_return_if_fail (g_dbus_is_interface_name (interface_name));
332 
333   g_mutex_lock (&proxy->priv->lock);
334 
335   interface_proxy = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
336   if (interface_proxy != NULL)
337     {
338       g_object_ref (interface_proxy);
339       g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
340       g_mutex_unlock (&proxy->priv->lock);
341       g_signal_emit_by_name (proxy, "interface-removed", interface_proxy);
342       g_object_unref (interface_proxy);
343     }
344   else
345     {
346       g_mutex_unlock (&proxy->priv->lock);
347     }
348 }
349 
350 static void
dbus_object_interface_init(GDBusObjectIface * iface)351 dbus_object_interface_init (GDBusObjectIface *iface)
352 {
353   iface->get_object_path       = g_dbus_object_proxy_get_object_path;
354   iface->get_interfaces        = g_dbus_object_proxy_get_interfaces;
355   iface->get_interface         = g_dbus_object_proxy_get_interface;
356 }
357