service: add new 'string set' utility pseudoclass
[dconf.git] / service / dconf-service.c
blobc769936395b20edca013b446fa687e26ffef3cf8
1 /*
2 * Copyright © 2012 Canonical Limited
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the licence, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Author: Ryan Lortie <desrt@desrt.ca>
22 #include "dconf-service.h"
24 #include "dconf-generated.h"
25 #include "dconf-writer.h"
26 #include "dconf-blame.h"
28 #include <string.h>
29 #include <fcntl.h>
31 typedef GApplicationClass DConfServiceClass;
32 typedef struct
34 GApplication parent_instance;
36 DConfBlame *blame;
37 GHashTable *writers;
38 guint subtree_id;
39 } DConfService;
41 G_DEFINE_TYPE (DConfService, dconf_service, G_TYPE_APPLICATION)
43 static gboolean
44 dconf_service_signalled (gpointer user_data)
46 DConfService *service = user_data;
48 g_application_release (G_APPLICATION (service));
50 return G_SOURCE_REMOVE;
53 static gchar **
54 string_set_free (GHashTable *set)
56 GHashTableIter iter;
57 gchar **result;
58 gint n_items;
59 gpointer key;
60 gint i = 0;
62 n_items = g_hash_table_size (set);
63 result = g_new (gchar *, n_items + 1);
65 g_hash_table_iter_init (&iter, set);
66 while (g_hash_table_iter_next (&iter, &key, NULL))
68 result[i++] = key;
69 g_hash_table_iter_steal (&iter);
71 result[i] = NULL;
73 g_assert_cmpint (n_items, ==, i);
74 g_hash_table_unref (set);
76 return result;
79 static GHashTable *
80 string_set_new (void)
82 return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
85 static void
86 string_set_add (GHashTable *set,
87 const gchar *string)
89 g_hash_table_add (set, g_strdup (string));
92 static gchar **
93 dconf_service_subtree_enumerate (GDBusConnection *connection,
94 const gchar *sender,
95 const gchar *object_path,
96 gpointer user_data)
98 DConfService *service = user_data;
99 GHashTableIter iter;
100 GHashTable *set;
101 gpointer key;
103 set = string_set_new ();
104 g_hash_table_iter_init (&iter, service->writers);
105 while (g_hash_table_iter_next (&iter, &key, NULL))
106 string_set_add (set, key);
108 return string_set_free (set);
111 GDBusInterfaceInfo **
112 dconf_service_subtree_introspect (GDBusConnection *connection,
113 const gchar *sender,
114 const gchar *object_path,
115 const gchar *node,
116 gpointer user_data)
118 GDBusInterfaceInfo **result;
120 if (node == NULL)
121 return NULL;
123 result = g_new (GDBusInterfaceInfo *, 2);
124 result[0] = dconf_dbus_writer_interface_info ();
125 result[1] = NULL;
127 return result;
130 static gpointer
131 dconf_service_get_writer (DConfService *service,
132 GDBusConnection *connection,
133 const gchar *base_path,
134 const gchar *name)
136 GDBusInterfaceSkeleton *writer;
138 writer = g_hash_table_lookup (service->writers, name);
140 if (writer == NULL)
142 GError *error = NULL;
143 gchar *object_path;
145 writer = dconf_writer_new (DCONF_TYPE_WRITER, name);
146 g_hash_table_insert (service->writers, g_strdup (name), writer);
147 object_path = g_strjoin ("/", base_path, name, NULL);
148 g_dbus_interface_skeleton_export (writer, connection, object_path, &error);
149 g_assert_no_error (error);
150 g_free (object_path);
153 return writer;
156 const GDBusInterfaceVTable *
157 dconf_service_subtree_dispatch (GDBusConnection *connection,
158 const gchar *sender,
159 const gchar *object_path,
160 const gchar *interface_name,
161 const gchar *node,
162 gpointer *out_user_data,
163 gpointer user_data)
165 DConfService *service = user_data;
167 g_assert_cmpstr (interface_name, ==, "ca.desrt.dconf.Writer");
168 g_assert (node != NULL);
170 *out_user_data = dconf_service_get_writer (service, connection, object_path, node);
172 return g_dbus_interface_skeleton_get_vtable (*out_user_data);
175 static gboolean
176 dconf_service_dbus_register (GApplication *application,
177 GDBusConnection *connection,
178 const gchar *object_path,
179 GError **error)
181 const GDBusSubtreeVTable subtree_vtable = {
182 dconf_service_subtree_enumerate,
183 dconf_service_subtree_introspect,
184 dconf_service_subtree_dispatch
186 DConfService *service = DCONF_SERVICE (application);
187 GError *local_error = NULL;
189 service->blame = dconf_blame_get ();
190 if (service->blame)
192 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (service->blame),
193 connection, object_path, &local_error);
194 g_assert_no_error (local_error);
197 service->subtree_id = g_dbus_connection_register_subtree (connection, "/ca/desrt/dconf/Writer", &subtree_vtable,
198 G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES,
199 g_object_ref (service), g_object_unref, &local_error);
200 g_assert_no_error (local_error);
202 return TRUE;
205 static void
206 dconf_service_dbus_unregister (GApplication *application,
207 GDBusConnection *connection,
208 const gchar *object_path)
210 DConfService *service = DCONF_SERVICE (application);
212 if (service->blame)
214 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (service->blame));
215 g_object_unref (service->blame);
216 service->blame = NULL;
219 g_dbus_connection_unregister_subtree (connection, service->subtree_id);
220 service->subtree_id = 0;
223 static void
224 dconf_service_startup (GApplication *application)
226 DConfService *service = DCONF_SERVICE (application);
228 G_APPLICATION_CLASS (dconf_service_parent_class)
229 ->startup (application);
231 g_unix_signal_add (SIGTERM, dconf_service_signalled, service);
232 g_unix_signal_add (SIGINT, dconf_service_signalled, service);
233 g_unix_signal_add (SIGHUP, dconf_service_signalled, service);
235 g_application_hold (application);
238 static void
239 dconf_service_shutdown (GApplication *application)
241 G_APPLICATION_CLASS (dconf_service_parent_class)
242 ->shutdown (application);
245 static void
246 dconf_service_init (DConfService *service)
248 service->writers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
251 static void
252 dconf_service_class_init (GApplicationClass *class)
254 class->dbus_register = dconf_service_dbus_register;
255 class->dbus_unregister = dconf_service_dbus_unregister;
256 class->startup = dconf_service_startup;
257 class->shutdown = dconf_service_shutdown;
260 GApplication *
261 dconf_service_new (void)
263 return g_object_new (DCONF_TYPE_SERVICE,
264 "application-id", "ca.desrt.dconf",
265 "flags", G_APPLICATION_IS_SERVICE,
266 NULL);