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.
36 * @SECRET_ERROR_PROTOCOL: received an invalid data or message from the Secret
38 * @SECRET_ERROR_IS_LOCKED: the item or collection is locked and the operation
40 * @SECRET_ERROR_NO_SUCH_OBJECT: no such item or collection found in the
42 * @SECRET_ERROR_ALREADY_EXISTS: a relevant item or collection already exists
44 * Errors returned by the Secret Service. None of the errors are appropriate
45 * for display to the user.
49 list_unref_free (GList *reflist)
52 for (l = reflist; l; l = g_list_next (l)) {
53 g_return_if_fail (G_IS_OBJECT (l->data));
54 g_object_unref (l->data);
56 g_list_free (reflist);
60 list_ref_copy (GList *reflist)
62 GList *l, *copy = g_list_copy (reflist);
63 for (l = copy; l; l = g_list_next (l)) {
64 g_return_val_if_fail (G_IS_OBJECT (l->data), NULL);
65 g_object_ref (l->data);
71 _secret_list_get_type (void)
73 static GType type = 0;
75 type = g_boxed_type_register_static ("SecretObjectList",
76 (GBoxedCopyFunc)list_ref_copy,
77 (GBoxedFreeFunc)list_unref_free);
83 secret_error_get_quark (void)
85 static volatile gsize quark = 0;
87 static const GDBusErrorEntry entries[] = {
88 { SECRET_ERROR_IS_LOCKED, "org.freedesktop.Secret.Error.IsLocked", },
89 { SECRET_ERROR_NO_SUCH_OBJECT, "org.freedesktop.Secret.Error.NoSuchObject", },
90 { SECRET_ERROR_ALREADY_EXISTS, "org.freedesktop.Secret.Error.AlreadyExists" },
93 g_dbus_error_register_error_domain ("secret-error", &quark,
94 entries, G_N_ELEMENTS (entries));
100 _secret_util_propagate_error (GSimpleAsyncResult *async,
103 if (!g_simple_async_result_propagate_error (async, error))
106 _secret_util_strip_remote_error (error);
111 _secret_util_strip_remote_error (GError **error)
115 if (error == NULL || *error == NULL)
118 remote = g_dbus_error_get_remote_error (*error);
120 if (g_dbus_error_strip_remote_error (*error)) {
121 g_message ("Remote error from secret service: %s: %s",
122 remote, (*error)->message);
129 _secret_util_parent_path (const gchar *path)
133 g_return_val_if_fail (path != NULL, NULL);
135 pos = strrchr (path, '/');
136 g_return_val_if_fail (pos != NULL, NULL);
137 g_return_val_if_fail (pos != path, NULL);
139 return g_strndup (path, pos - path);
143 _secret_util_empty_path (const gchar *path)
145 g_return_val_if_fail (path != NULL, TRUE);
146 return (g_str_equal (path, "") || g_str_equal (path, "/"));
150 _secret_util_collection_to_path (const gchar *collection)
152 if (collection == NULL)
153 collection = SECRET_COLLECTION_DEFAULT;
154 if (strchr (collection, '/') == NULL)
155 return g_strdup_printf ("/org/freedesktop/secrets/aliases/%s", collection);
156 return g_strdup (collection);
160 _secret_util_variant_for_properties (GHashTable *properties)
163 GVariantBuilder builder;
167 g_return_val_if_fail (properties != NULL, NULL);
169 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
171 g_hash_table_iter_init (&iter, properties);
172 while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&value))
173 g_variant_builder_add (&builder, "{sv}", name, value);
175 return g_variant_builder_end (&builder);
179 process_get_all_reply (GDBusProxy *proxy,
182 const gchar *invalidated_properties[1] = { NULL };
183 GVariant *changed_properties;
188 if (!g_variant_is_of_type (retval, G_VARIANT_TYPE ("(a{sv})"))) {
189 g_warning ("Value for GetAll reply with type `%s' does not match `(a{sv})'",
190 g_variant_get_type_string (retval));
194 g_variant_get (retval, "(a{sv})", &iter);
195 while (g_variant_iter_loop (iter, "{sv}", &key, &value))
196 g_dbus_proxy_set_cached_property (proxy, key, value);
197 g_variant_iter_free (iter);
199 g_variant_get (retval, "(@a{sv})", &changed_properties);
200 g_signal_emit_by_name (proxy, "g-properties-changed",
201 changed_properties, invalidated_properties);
202 g_variant_unref (changed_properties);
206 on_get_properties (GObject *source,
207 GAsyncResult *result,
210 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
211 GDBusProxy *proxy = G_DBUS_PROXY (g_async_result_get_source_object (user_data));
212 GError *error = NULL;
215 retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
218 process_get_all_reply (proxy, retval);
220 g_simple_async_result_take_error (res, error);
223 g_variant_unref (retval);
225 g_simple_async_result_complete (res);
226 g_object_unref (proxy);
227 g_object_unref (res);
231 _secret_util_get_properties (GDBusProxy *proxy,
233 GCancellable *cancellable,
234 GAsyncReadyCallback callback,
237 GSimpleAsyncResult *res;
239 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
241 res = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, result_tag);
243 g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
244 g_dbus_proxy_get_name (proxy),
245 g_dbus_proxy_get_object_path (proxy),
246 "org.freedesktop.DBus.Properties", "GetAll",
247 g_variant_new ("(s)", g_dbus_proxy_get_interface_name (proxy)),
248 G_VARIANT_TYPE ("(a{sv})"),
249 G_DBUS_CALL_FLAGS_NONE, -1,
250 cancellable, on_get_properties,
253 g_object_unref (res);
257 _secret_util_get_properties_finish (GDBusProxy *proxy,
259 GAsyncResult *result,
262 GSimpleAsyncResult *res;
264 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), result_tag), FALSE);
265 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
267 res = G_SIMPLE_ASYNC_RESULT (result);
269 if (_secret_util_propagate_error (res, error))
282 set_closure_free (gpointer data)
284 SetClosure *closure = data;
285 g_free (closure->property);
286 g_variant_unref (closure->value);
287 g_slice_free (SetClosure, closure);
291 on_set_property (GObject *source,
292 GAsyncResult *result,
295 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
296 SetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
297 GDBusProxy *proxy = G_DBUS_PROXY (g_async_result_get_source_object (user_data));
298 GError *error = NULL;
301 retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
304 g_simple_async_result_take_error (res, error);
307 g_variant_unref (retval);
309 closure->result = retval != NULL;
311 g_dbus_proxy_set_cached_property (proxy, closure->property, closure->value);
313 g_simple_async_result_complete (res);
314 g_object_unref (proxy);
315 g_object_unref (res);
319 _secret_util_set_property (GDBusProxy *proxy,
320 const gchar *property,
323 GCancellable *cancellable,
324 GAsyncReadyCallback callback,
327 GSimpleAsyncResult *res;
330 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
332 res = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, result_tag);
333 closure = g_slice_new0 (SetClosure);
334 closure->property = g_strdup (property);
335 closure->value = g_variant_ref_sink (value);
336 g_simple_async_result_set_op_res_gpointer (res, closure, set_closure_free);
338 g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
339 g_dbus_proxy_get_name (proxy),
340 g_dbus_proxy_get_object_path (proxy),
341 SECRET_PROPERTIES_INTERFACE,
343 g_variant_new ("(ssv)",
344 g_dbus_proxy_get_interface_name (proxy),
347 G_VARIANT_TYPE ("()"),
348 G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
349 cancellable, on_set_property,
352 g_object_unref (res);
356 _secret_util_set_property_finish (GDBusProxy *proxy,
358 GAsyncResult *result,
361 GSimpleAsyncResult *res;
364 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), result_tag), FALSE);
365 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
367 res = G_SIMPLE_ASYNC_RESULT (result);
369 if (_secret_util_propagate_error (res, error))
372 closure = g_simple_async_result_get_op_res_gpointer (res);
373 return closure->result;
377 _secret_util_set_property_sync (GDBusProxy *proxy,
378 const gchar *property,
380 GCancellable *cancellable,
383 gboolean result = FALSE;
386 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
387 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
389 g_variant_ref_sink (value);
391 retval = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (proxy),
392 g_dbus_proxy_get_name (proxy),
393 g_dbus_proxy_get_object_path (proxy),
394 SECRET_PROPERTIES_INTERFACE,
396 g_variant_new ("(ssv)",
397 g_dbus_proxy_get_interface_name (proxy),
400 G_VARIANT_TYPE ("()"),
401 G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
404 if (retval != NULL) {
406 g_variant_unref (retval);
407 g_dbus_proxy_set_cached_property (proxy, property, value);
410 g_variant_unref (value);
416 _secret_util_have_cached_properties (GDBusProxy *proxy)
420 names = g_dbus_proxy_get_cached_property_names (proxy);
423 return names != NULL;
427 _secret_sync_new (void)
431 sync = g_new0 (SecretSync, 1);
433 sync->context = g_main_context_new ();
434 sync->loop = g_main_loop_new (sync->context, FALSE);
440 _secret_sync_free (gpointer data)
442 SecretSync *sync = data;
444 g_clear_object (&sync->result);
445 g_main_loop_unref (sync->loop);
446 g_main_context_unref (sync->context);
450 _secret_sync_on_result (GObject *source,
451 GAsyncResult *result,
454 SecretSync *sync = user_data;
455 g_assert (sync->result == NULL);
456 sync->result = g_object_ref (result);
457 g_main_loop_quit (sync->loop);