Coverage Report

Created: 2025-10-10 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib/gio/gdbusobjectproxy.c
Line
Count
Source
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
62
0
G_DEFINE_TYPE_WITH_CODE (GDBusObjectProxy, g_dbus_object_proxy, G_TYPE_OBJECT,
63
0
                         G_ADD_PRIVATE (GDBusObjectProxy)
64
0
                         G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, dbus_object_interface_init))
65
0
66
0
static void
67
0
g_dbus_object_proxy_finalize (GObject *object)
68
0
{
69
0
  GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
70
71
0
  g_hash_table_unref (proxy->priv->map_name_to_iface);
72
73
0
  g_clear_object (&proxy->priv->connection);
74
75
0
  g_free (proxy->priv->object_path);
76
77
0
  g_mutex_clear (&proxy->priv->lock);
78
79
0
  if (G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize != NULL)
80
0
    G_OBJECT_CLASS (g_dbus_object_proxy_parent_class)->finalize (object);
81
0
}
82
83
static void
84
g_dbus_object_proxy_get_property (GObject    *object,
85
                                  guint       prop_id,
86
                                  GValue     *value,
87
                                  GParamSpec *pspec)
88
0
{
89
0
  GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
90
91
0
  switch (prop_id)
92
0
    {
93
0
    case PROP_G_OBJECT_PATH:
94
0
      g_mutex_lock (&proxy->priv->lock);
95
0
      g_value_set_string (value, proxy->priv->object_path);
96
0
      g_mutex_unlock (&proxy->priv->lock);
97
0
      break;
98
99
0
    case PROP_G_CONNECTION:
100
0
      g_value_set_object (value, g_dbus_object_proxy_get_connection (proxy));
101
0
      break;
102
103
0
    default:
104
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
105
0
      break;
106
0
    }
107
0
}
108
109
static void
110
g_dbus_object_proxy_set_property (GObject       *object,
111
                                  guint          prop_id,
112
                                  const GValue  *value,
113
                                  GParamSpec    *pspec)
114
0
{
115
0
  GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
116
117
0
  switch (prop_id)
118
0
    {
119
0
    case PROP_G_OBJECT_PATH:
120
0
      g_mutex_lock (&proxy->priv->lock);
121
0
      proxy->priv->object_path = g_value_dup_string (value);
122
0
      g_mutex_unlock (&proxy->priv->lock);
123
0
      break;
124
125
0
    case PROP_G_CONNECTION:
126
0
      g_mutex_lock (&proxy->priv->lock);
127
0
      proxy->priv->connection = g_value_dup_object (value);
128
0
      g_mutex_unlock (&proxy->priv->lock);
129
0
      break;
130
131
0
    default:
132
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
133
0
      break;
134
0
    }
135
0
}
136
137
static void
138
g_dbus_object_proxy_class_init (GDBusObjectProxyClass *klass)
139
0
{
140
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
141
142
0
  gobject_class->finalize     = g_dbus_object_proxy_finalize;
143
0
  gobject_class->set_property = g_dbus_object_proxy_set_property;
144
0
  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
0
  g_object_class_install_property (gobject_class,
154
0
                                   PROP_G_OBJECT_PATH,
155
0
                                   g_param_spec_string ("g-object-path",
156
0
                                                        "Object Path",
157
0
                                                        "The object path of the proxy",
158
0
                                                        NULL,
159
0
                                                        G_PARAM_READWRITE |
160
0
                                                        G_PARAM_CONSTRUCT_ONLY |
161
0
                                                        G_PARAM_STATIC_STRINGS));
162
163
  /**
164
   * GDBusObjectProxy:g-connection:
165
   *
166
   * The connection of the proxy.
167
   *
168
   * Since: 2.30
169
   */
170
0
  g_object_class_install_property (gobject_class,
171
0
                                   PROP_G_CONNECTION,
172
0
                                   g_param_spec_object ("g-connection",
173
0
                                                        "Connection",
174
0
                                                        "The connection of the proxy",
175
0
                                                        G_TYPE_DBUS_CONNECTION,
176
0
                                                        G_PARAM_READWRITE |
177
0
                                                        G_PARAM_CONSTRUCT_ONLY |
178
0
                                                        G_PARAM_STATIC_STRINGS));
179
0
}
180
181
static void
182
g_dbus_object_proxy_init (GDBusObjectProxy *proxy)
183
0
{
184
0
  proxy->priv = g_dbus_object_proxy_get_instance_private (proxy);
185
0
  g_mutex_init (&proxy->priv->lock);
186
0
  proxy->priv->map_name_to_iface = g_hash_table_new_full (g_str_hash,
187
0
                                                          g_str_equal,
188
0
                                                          g_free,
189
0
                                                          (GDestroyNotify) g_object_unref);
190
0
}
191
192
static const gchar *
193
g_dbus_object_proxy_get_object_path (GDBusObject *object)
194
0
{
195
0
  GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
196
0
  const gchar *ret;
197
0
  g_mutex_lock (&proxy->priv->lock);
198
0
  ret = proxy->priv->object_path;
199
0
  g_mutex_unlock (&proxy->priv->lock);
200
0
  return ret;
201
0
}
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 *
215
g_dbus_object_proxy_get_connection (GDBusObjectProxy *proxy)
216
0
{
217
0
  GDBusConnection *ret;
218
0
  g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
219
0
  g_mutex_lock (&proxy->priv->lock);
220
0
  ret = proxy->priv->connection;
221
0
  g_mutex_unlock (&proxy->priv->lock);
222
0
  return ret;
223
0
}
224
225
static GDBusInterface *
226
g_dbus_object_proxy_get_interface (GDBusObject *object,
227
                                   const gchar *interface_name)
228
0
{
229
0
  GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
230
0
  GDBusProxy *ret;
231
232
0
  g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
233
0
  g_return_val_if_fail (g_dbus_is_interface_name (interface_name), NULL);
234
235
0
  g_mutex_lock (&proxy->priv->lock);
236
0
  ret = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
237
0
  if (ret != NULL)
238
0
    g_object_ref (ret);
239
0
  g_mutex_unlock (&proxy->priv->lock);
240
241
0
  return (GDBusInterface *) ret; /* TODO: proper cast */
242
0
}
243
244
static GList *
245
g_dbus_object_proxy_get_interfaces (GDBusObject *object)
246
0
{
247
0
  GDBusObjectProxy *proxy = G_DBUS_OBJECT_PROXY (object);
248
0
  GList *ret;
249
250
0
  g_return_val_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy), NULL);
251
252
0
  ret = NULL;
253
254
0
  g_mutex_lock (&proxy->priv->lock);
255
0
  ret = g_hash_table_get_values (proxy->priv->map_name_to_iface);
256
0
  g_list_foreach (ret, (GFunc) g_object_ref, NULL);
257
0
  g_mutex_unlock (&proxy->priv->lock);
258
259
0
  return ret;
260
0
}
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 *
277
g_dbus_object_proxy_new (GDBusConnection *connection,
278
                         const gchar     *object_path)
279
0
{
280
0
  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
281
0
  g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
282
0
  return G_DBUS_OBJECT_PROXY (g_object_new (G_TYPE_DBUS_OBJECT_PROXY,
283
0
                                            "g-object-path", object_path,
284
0
                                            "g-connection", connection,
285
0
                                            NULL));
286
0
}
287
288
void
289
_g_dbus_object_proxy_add_interface (GDBusObjectProxy *proxy,
290
                                    GDBusProxy       *interface_proxy)
291
0
{
292
0
  const gchar *interface_name;
293
0
  GDBusProxy *interface_proxy_to_remove;
294
295
0
  g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
296
0
  g_return_if_fail (G_IS_DBUS_PROXY (interface_proxy));
297
298
0
  g_mutex_lock (&proxy->priv->lock);
299
300
0
  interface_name = g_dbus_proxy_get_interface_name (interface_proxy);
301
0
  interface_proxy_to_remove = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
302
0
  if (interface_proxy_to_remove != NULL)
303
0
    {
304
0
      g_object_ref (interface_proxy_to_remove);
305
0
      g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
306
0
    }
307
0
  g_hash_table_insert (proxy->priv->map_name_to_iface,
308
0
                       g_strdup (interface_name),
309
0
                       g_object_ref (interface_proxy));
310
0
  g_object_ref (interface_proxy);
311
312
0
  g_mutex_unlock (&proxy->priv->lock);
313
314
0
  if (interface_proxy_to_remove != NULL)
315
0
    {
316
0
      g_signal_emit_by_name (proxy, "interface-removed", interface_proxy_to_remove);
317
0
      g_object_unref (interface_proxy_to_remove);
318
0
    }
319
320
0
  g_signal_emit_by_name (proxy, "interface-added", interface_proxy);
321
0
  g_object_unref (interface_proxy);
322
0
}
323
324
void
325
_g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy,
326
                                       const gchar      *interface_name)
327
0
{
328
0
  GDBusProxy *interface_proxy;
329
330
0
  g_return_if_fail (G_IS_DBUS_OBJECT_PROXY (proxy));
331
0
  g_return_if_fail (g_dbus_is_interface_name (interface_name));
332
333
0
  g_mutex_lock (&proxy->priv->lock);
334
335
0
  interface_proxy = g_hash_table_lookup (proxy->priv->map_name_to_iface, interface_name);
336
0
  if (interface_proxy != NULL)
337
0
    {
338
0
      g_object_ref (interface_proxy);
339
0
      g_warn_if_fail (g_hash_table_remove (proxy->priv->map_name_to_iface, interface_name));
340
0
      g_mutex_unlock (&proxy->priv->lock);
341
0
      g_signal_emit_by_name (proxy, "interface-removed", interface_proxy);
342
0
      g_object_unref (interface_proxy);
343
0
    }
344
0
  else
345
0
    {
346
0
      g_mutex_unlock (&proxy->priv->lock);
347
0
    }
348
0
}
349
350
static void
351
dbus_object_interface_init (GDBusObjectIface *iface)
352
0
{
353
0
  iface->get_object_path       = g_dbus_object_proxy_get_object_path;
354
0
  iface->get_interfaces        = g_dbus_object_proxy_get_interfaces;
355
0
  iface->get_interface         = g_dbus_object_proxy_get_interface;
356
0
}