1 /* libsecret - GLib wrapper for Secret Service
3 * Copyright 2011 Collabora Ltd.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation; either version 2.1 of the licence or (at
8 * your option) any later version.
10 * See the included COPYING file for more information.
12 * Author: Stef Walter <stefw@gnome.org>
17 #include "secret-private.h"
18 #include "secret-types.h"
23 * SECTION:secret-error
25 * @short_description: libsecret errors
27 * Various errors reported by the libsecret library. No error returned from
28 * the libsecret API is suitable for direct display to the user. It is up
29 * to the application to handle them appropriately.
37 * The error domain quark which denotes libsecret specific errors from the
38 * #SecretError enumeration.
43 * @SECRET_ERROR_PROTOCOL: received an invalid data or message from the Secret
45 * @SECRET_ERROR_IS_LOCKED: the item or collection is locked and the operation
47 * @SECRET_ERROR_NO_SUCH_OBJECT: no such item or collection found in the
49 * @SECRET_ERROR_ALREADY_EXISTS: a relevant item or collection already exists
51 * Errors returned by the Secret Service. None of the errors are appropriate
52 * for display to the user.
56 list_unref_free (GList *reflist)
59 for (l = reflist; l; l = g_list_next (l)) {
60 g_return_if_fail (G_IS_OBJECT (l->data));
61 g_object_unref (l->data);
63 g_list_free (reflist);
67 list_ref_copy (GList *reflist)
69 GList *l, *copy = g_list_copy (reflist);
70 for (l = copy; l; l = g_list_next (l)) {
71 g_return_val_if_fail (G_IS_OBJECT (l->data), NULL);
72 g_object_ref (l->data);
78 _secret_list_get_type (void)
80 static GType type = 0;
82 type = g_boxed_type_register_static ("SecretObjectList",
83 (GBoxedCopyFunc)list_ref_copy,
84 (GBoxedFreeFunc)list_unref_free);
90 secret_error_get_quark (void)
92 static volatile gsize quark = 0;
94 static const GDBusErrorEntry entries[] = {
95 { SECRET_ERROR_IS_LOCKED, "org.freedesktop.Secret.Error.IsLocked", },
96 { SECRET_ERROR_NO_SUCH_OBJECT, "org.freedesktop.Secret.Error.NoSuchObject", },
97 { SECRET_ERROR_ALREADY_EXISTS, "org.freedesktop.Secret.Error.AlreadyExists" },
100 g_dbus_error_register_error_domain ("secret-error", &quark,
101 entries, G_N_ELEMENTS (entries));
107 _secret_util_propagate_error (GSimpleAsyncResult *async,
110 if (!g_simple_async_result_propagate_error (async, error))
113 _secret_util_strip_remote_error (error);
118 _secret_util_strip_remote_error (GError **error)
122 if (error == NULL || *error == NULL)
125 remote = g_dbus_error_get_remote_error (*error);
127 if (g_dbus_error_strip_remote_error (*error)) {
128 g_message ("Remote error from secret service: %s: %s",
129 remote, (*error)->message);
136 _secret_util_parent_path (const gchar *path)
140 g_return_val_if_fail (path != NULL, NULL);
142 pos = strrchr (path, '/');
143 g_return_val_if_fail (pos != NULL, NULL);
144 g_return_val_if_fail (pos != path, NULL);
146 return g_strndup (path, pos - path);
150 _secret_util_empty_path (const gchar *path)
152 g_return_val_if_fail (path != NULL, TRUE);
153 return (g_str_equal (path, "") || g_str_equal (path, "/"));
157 _secret_util_collection_to_path (const gchar *collection)
159 if (collection == NULL)
160 collection = SECRET_COLLECTION_DEFAULT;
161 if (strchr (collection, '/') == NULL)
162 return g_strdup_printf ("/org/freedesktop/secrets/aliases/%s", collection);
163 return g_strdup (collection);
167 _secret_util_variant_for_properties (GHashTable *properties)
170 GVariantBuilder builder;
174 g_return_val_if_fail (properties != NULL, NULL);
176 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
178 g_hash_table_iter_init (&iter, properties);
179 while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&value))
180 g_variant_builder_add (&builder, "{sv}", name, value);
182 return g_variant_builder_end (&builder);
186 process_get_all_reply (GDBusProxy *proxy,
189 const gchar *invalidated_properties[1] = { NULL };
190 GVariant *changed_properties;
195 if (!g_variant_is_of_type (retval, G_VARIANT_TYPE ("(a{sv})"))) {
196 g_warning ("Value for GetAll reply with type `%s' does not match `(a{sv})'",
197 g_variant_get_type_string (retval));
201 g_variant_get (retval, "(a{sv})", &iter);
202 while (g_variant_iter_loop (iter, "{sv}", &key, &value))
203 g_dbus_proxy_set_cached_property (proxy, key, value);
204 g_variant_iter_free (iter);
206 g_variant_get (retval, "(@a{sv})", &changed_properties);
207 g_signal_emit_by_name (proxy, "g-properties-changed",
208 changed_properties, invalidated_properties);
209 g_variant_unref (changed_properties);
213 on_get_properties (GObject *source,
214 GAsyncResult *result,
217 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
218 GDBusProxy *proxy = G_DBUS_PROXY (g_async_result_get_source_object (user_data));
219 GError *error = NULL;
222 retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
225 process_get_all_reply (proxy, retval);
227 g_simple_async_result_take_error (res, error);
230 g_variant_unref (retval);
232 g_simple_async_result_complete (res);
233 g_object_unref (proxy);
234 g_object_unref (res);
238 _secret_util_get_properties (GDBusProxy *proxy,
240 GCancellable *cancellable,
241 GAsyncReadyCallback callback,
244 GSimpleAsyncResult *res;
246 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
248 res = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, result_tag);
250 g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
251 g_dbus_proxy_get_name (proxy),
252 g_dbus_proxy_get_object_path (proxy),
253 "org.freedesktop.DBus.Properties", "GetAll",
254 g_variant_new ("(s)", g_dbus_proxy_get_interface_name (proxy)),
255 G_VARIANT_TYPE ("(a{sv})"),
256 G_DBUS_CALL_FLAGS_NONE, -1,
257 cancellable, on_get_properties,
260 g_object_unref (res);
264 _secret_util_get_properties_finish (GDBusProxy *proxy,
266 GAsyncResult *result,
269 GSimpleAsyncResult *res;
271 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), result_tag), FALSE);
272 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
274 res = G_SIMPLE_ASYNC_RESULT (result);
276 if (_secret_util_propagate_error (res, error))
289 set_closure_free (gpointer data)
291 SetClosure *closure = data;
292 g_free (closure->property);
293 g_variant_unref (closure->value);
294 g_slice_free (SetClosure, closure);
298 on_set_property (GObject *source,
299 GAsyncResult *result,
302 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
303 SetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
304 GDBusProxy *proxy = G_DBUS_PROXY (g_async_result_get_source_object (user_data));
305 GError *error = NULL;
308 retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
311 g_simple_async_result_take_error (res, error);
314 g_variant_unref (retval);
316 closure->result = retval != NULL;
318 g_dbus_proxy_set_cached_property (proxy, closure->property, closure->value);
320 g_simple_async_result_complete (res);
321 g_object_unref (proxy);
322 g_object_unref (res);
326 _secret_util_set_property (GDBusProxy *proxy,
327 const gchar *property,
330 GCancellable *cancellable,
331 GAsyncReadyCallback callback,
334 GSimpleAsyncResult *res;
337 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
339 res = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, result_tag);
340 closure = g_slice_new0 (SetClosure);
341 closure->property = g_strdup (property);
342 closure->value = g_variant_ref_sink (value);
343 g_simple_async_result_set_op_res_gpointer (res, closure, set_closure_free);
345 g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
346 g_dbus_proxy_get_name (proxy),
347 g_dbus_proxy_get_object_path (proxy),
348 SECRET_PROPERTIES_INTERFACE,
350 g_variant_new ("(ssv)",
351 g_dbus_proxy_get_interface_name (proxy),
354 G_VARIANT_TYPE ("()"),
355 G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
356 cancellable, on_set_property,
359 g_object_unref (res);
363 _secret_util_set_property_finish (GDBusProxy *proxy,
365 GAsyncResult *result,
368 GSimpleAsyncResult *res;
371 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), result_tag), FALSE);
372 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
374 res = G_SIMPLE_ASYNC_RESULT (result);
376 if (_secret_util_propagate_error (res, error))
379 closure = g_simple_async_result_get_op_res_gpointer (res);
380 return closure->result;
384 _secret_util_set_property_sync (GDBusProxy *proxy,
385 const gchar *property,
387 GCancellable *cancellable,
390 gboolean result = FALSE;
393 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
394 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
396 g_variant_ref_sink (value);
398 retval = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (proxy),
399 g_dbus_proxy_get_name (proxy),
400 g_dbus_proxy_get_object_path (proxy),
401 SECRET_PROPERTIES_INTERFACE,
403 g_variant_new ("(ssv)",
404 g_dbus_proxy_get_interface_name (proxy),
407 G_VARIANT_TYPE ("()"),
408 G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
411 if (retval != NULL) {
413 g_variant_unref (retval);
414 g_dbus_proxy_set_cached_property (proxy, property, value);
417 g_variant_unref (value);
423 _secret_util_have_cached_properties (GDBusProxy *proxy)
427 names = g_dbus_proxy_get_cached_property_names (proxy);
430 return names != NULL;
434 _secret_sync_new (void)
438 sync = g_new0 (SecretSync, 1);
440 sync->context = g_main_context_new ();
441 sync->loop = g_main_loop_new (sync->context, FALSE);
447 _secret_sync_free (gpointer data)
449 SecretSync *sync = data;
451 while (g_main_context_iteration (sync->context, FALSE));
453 g_clear_object (&sync->result);
454 g_main_loop_unref (sync->loop);
455 g_main_context_unref (sync->context);
459 _secret_sync_on_result (GObject *source,
460 GAsyncResult *result,
463 SecretSync *sync = user_data;
464 g_assert (sync->result == NULL);
465 sync->result = g_object_ref (result);
466 g_main_loop_quit (sync->loop);