1 /* libsecret - GLib wrapper for Secret Service
3 * Copyright 2012 Red Hat Inc.
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-collection.h"
18 #include "secret-dbus-generated.h"
19 #include "secret-enum-types.h"
20 #include "secret-item.h"
21 #include "secret-paths.h"
22 #include "secret-private.h"
23 #include "secret-service.h"
24 #include "secret-types.h"
26 #include <glib/gi18n-lib.h>
29 * SECTION:secret-collection
30 * @title: SecretCollection
31 * @short_description: A collection of secret items
33 * #SecretCollection represents a collection of secret items stored in the
36 * A collection can be in a locked or unlocked state. Use secret_service_lock()
37 * or secret_service_unlock() to lock or unlock the collection.
39 * Use the SecretCollection::items property or secret_collection_get_items() to
40 * lookup the items in the collection. There may not be any items exposed when
41 * the collection is locked.
43 * These functions have an unstable API and may change across versions. Use
44 * <literal>libsecret-unstable</literal> package to access them.
52 * A proxy object representing a collection of secrets in the Secret Service.
56 * SecretCollectionClass:
57 * @parent_class: the parent class
59 * The class for #SecretCollection.
63 * SecretCollectionFlags:
64 * @SECRET_COLLECTION_NONE: no flags
65 * @SECRET_COLLECTION_LOAD_ITEMS: items have or should be loaded
67 * Flags which determine which parts of the #SecretCollection proxy are initialized.
71 * SecretCollectionCreateFlags:
72 * @SECRET_COLLECTION_CREATE_NONE: no flags
74 * Flags for secret_collection_create().
78 * SECRET_COLLECTION_DEFAULT:
80 * An alias to the default collection. This can be passed to secret_password_store()
81 * secret_collection_for_alias().
85 * SECRET_COLLECTION_SESSION:
87 * An alias to the session collection, which will be cleared when the user ends
88 * the session. This can be passed to secret_password_store(),
89 * secret_collection_for_alias() or similar functions.
103 struct _SecretCollectionPrivate {
104 /* Doesn't change between construct and finalize */
105 SecretService *service;
106 GCancellable *cancellable;
107 gboolean constructing;
108 SecretCollectionFlags init_flags;
110 /* Protected by mutex */
115 static GInitableIface *secret_collection_initable_parent_iface = NULL;
117 static GAsyncInitableIface *secret_collection_async_initable_parent_iface = NULL;
119 static void secret_collection_initable_iface (GInitableIface *iface);
121 static void secret_collection_async_initable_iface (GAsyncInitableIface *iface);
123 G_DEFINE_TYPE_WITH_CODE (SecretCollection, secret_collection, G_TYPE_DBUS_PROXY,
124 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, secret_collection_initable_iface);
125 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, secret_collection_async_initable_iface);
129 items_table_new (void)
131 return g_hash_table_new_full (g_str_hash, g_str_equal,
132 g_free, g_object_unref);
136 secret_collection_init (SecretCollection *self)
138 self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SECRET_TYPE_COLLECTION,
139 SecretCollectionPrivate);
141 g_mutex_init (&self->pv->mutex);
142 self->pv->cancellable = g_cancellable_new ();
143 self->pv->items = items_table_new ();
144 self->pv->constructing = TRUE;
148 on_set_label (GObject *source,
149 GAsyncResult *result,
152 SecretCollection *self = SECRET_COLLECTION (user_data);
153 GError *error = NULL;
155 secret_collection_set_label_finish (self, result, &error);
157 g_warning ("couldn't set SecretCollection Label: %s", error->message);
158 g_error_free (error);
161 g_object_unref (self);
165 collection_take_service (SecretCollection *self,
166 SecretService *service)
171 g_return_if_fail (self->pv->service == NULL);
173 self->pv->service = service;
174 g_object_add_weak_pointer (G_OBJECT (self->pv->service),
175 (gpointer *)&self->pv->service);
177 /* Yes, we expect that the service will stay around */
178 g_object_unref (service);
182 secret_collection_set_property (GObject *obj,
187 SecretCollection *self = SECRET_COLLECTION (obj);
191 collection_take_service (self, g_value_dup_object (value));
194 self->pv->init_flags = g_value_get_flags (value);
197 secret_collection_set_label (self, g_value_get_string (value),
198 self->pv->cancellable, on_set_label,
199 g_object_ref (self));
202 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
208 secret_collection_get_property (GObject *obj,
213 SecretCollection *self = SECRET_COLLECTION (obj);
217 g_value_set_object (value, self->pv->service);
220 g_value_set_flags (value, secret_collection_get_flags (self));
223 g_value_take_boxed (value, secret_collection_get_items (self));
226 g_value_take_string (value, secret_collection_get_label (self));
229 g_value_set_boolean (value, secret_collection_get_locked (self));
232 g_value_set_uint64 (value, secret_collection_get_created (self));
235 g_value_set_uint64 (value, secret_collection_get_modified (self));
238 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
244 secret_collection_dispose (GObject *obj)
246 SecretCollection *self = SECRET_COLLECTION (obj);
248 g_cancellable_cancel (self->pv->cancellable);
250 G_OBJECT_CLASS (secret_collection_parent_class)->dispose (obj);
254 secret_collection_finalize (GObject *obj)
256 SecretCollection *self = SECRET_COLLECTION (obj);
258 if (self->pv->service)
259 g_object_remove_weak_pointer (G_OBJECT (self->pv->service),
260 (gpointer *)&self->pv->service);
262 g_mutex_clear (&self->pv->mutex);
263 g_hash_table_destroy (self->pv->items);
264 g_object_unref (self->pv->cancellable);
266 G_OBJECT_CLASS (secret_collection_parent_class)->finalize (obj);
270 collection_lookup_item (SecretCollection *self,
273 SecretItem *item = NULL;
275 g_mutex_lock (&self->pv->mutex);
277 item = g_hash_table_lookup (self->pv->items, path);
281 g_mutex_unlock (&self->pv->mutex);
287 collection_update_items (SecretCollection *self,
290 GHashTable *previous;
292 g_hash_table_ref (items);
294 g_mutex_lock (&self->pv->mutex);
295 previous = self->pv->items;
296 self->pv->items = items;
297 g_mutex_unlock (&self->pv->mutex);
299 g_hash_table_unref (previous);
300 g_object_notify (G_OBJECT (self), "items");
304 handle_property_changed (SecretCollection *self,
305 const gchar *property_name,
310 if (g_str_equal (property_name, "Label")) {
311 g_object_notify (G_OBJECT (self), "label");
313 } else if (g_str_equal (property_name, "Locked")) {
314 g_object_notify (G_OBJECT (self), "locked");
316 } else if (g_str_equal (property_name, "Created")) {
317 g_object_notify (G_OBJECT (self), "created");
319 } else if (g_str_equal (property_name, "Modified")) {
320 g_object_notify (G_OBJECT (self), "modified");
322 } else if (g_str_equal (property_name, "Items") && !self->pv->constructing) {
323 g_mutex_lock (&self->pv->mutex);
324 perform = self->pv->items != NULL;
325 g_mutex_unlock (&self->pv->mutex);
328 secret_collection_load_items (self, self->pv->cancellable, NULL, NULL);
333 secret_collection_properties_changed (GDBusProxy *proxy,
334 GVariant *changed_properties,
335 const gchar* const *invalidated_properties)
337 SecretCollection *self = SECRET_COLLECTION (proxy);
338 gchar *property_name;
342 g_object_freeze_notify (G_OBJECT (self));
344 g_variant_iter_init (&iter, changed_properties);
345 while (g_variant_iter_loop (&iter, "{sv}", &property_name, &value))
346 handle_property_changed (self, property_name, value);
348 g_object_thaw_notify (G_OBJECT (self));
352 secret_collection_signal (GDBusProxy *proxy,
353 const gchar *sender_name,
354 const gchar *signal_name,
355 GVariant *parameters)
357 SecretCollection *self = SECRET_COLLECTION (proxy);
359 const gchar *item_path;
360 GVariantBuilder builder;
361 gboolean found = FALSE;
368 * Remember that these signals come from a time before PropertiesChanged.
369 * We support them because they're in the spec, and ksecretservice uses them.
372 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
374 /* A new collection was added, add it to the Collections property */
375 if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CREATED)) {
376 g_variant_get (parameters, "(@o)", &value);
377 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
378 g_variant_iter_init (&iter, paths);
379 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
380 if (g_variant_equal (path, value)) {
384 g_variant_builder_add_value (&builder, path);
385 g_variant_unref (path);
388 g_variant_builder_add_value (&builder, value);
389 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
391 g_variant_builder_clear (&builder);
392 g_variant_unref (value);
394 /* A collection was deleted, remove it from the Collections property */
395 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_DELETED)) {
396 g_variant_get (parameters, "(@o)", &value);
397 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
398 g_variant_iter_init (&iter, paths);
399 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
400 if (g_variant_equal (path, value))
403 g_variant_builder_add_value (&builder, path);
404 g_variant_unref (path);
407 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
408 g_variant_unref (value);
410 /* The collection changed, update it */
411 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CHANGED)) {
412 g_variant_get (parameters, "(&o)", &item_path);
414 g_mutex_lock (&self->pv->mutex);
417 item = g_hash_table_lookup (self->pv->items, item_path);
423 g_mutex_unlock (&self->pv->mutex);
426 secret_item_refresh (item);
427 g_object_unref (item);
431 g_variant_unref (paths);
435 secret_collection_class_init (SecretCollectionClass *klass)
437 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
438 GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass);
440 gobject_class->get_property = secret_collection_get_property;
441 gobject_class->set_property = secret_collection_set_property;
442 gobject_class->dispose = secret_collection_dispose;
443 gobject_class->finalize = secret_collection_finalize;
445 proxy_class->g_properties_changed = secret_collection_properties_changed;
446 proxy_class->g_signal = secret_collection_signal;
449 * SecretCollection:service:
451 * The #SecretService object that this collection is associated with and
452 * uses to interact with the actual D-Bus Secret Service.
454 g_object_class_install_property (gobject_class, PROP_SERVICE,
455 g_param_spec_object ("service", "Service", "Secret Service",
456 SECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
459 * SecretCollection:flags:
461 * A set of flags describing which parts of the secret collection have
464 g_object_class_install_property (gobject_class, PROP_FLAGS,
465 g_param_spec_flags ("flags", "Flags", "Collection flags",
466 secret_collection_flags_get_type (), SECRET_COLLECTION_NONE,
467 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
470 * SecretCollection:items:
472 * A list of #SecretItem objects representing the items that are in
473 * this collection. This list will be empty if the collection is locked.
475 g_object_class_install_property (gobject_class, PROP_ITEMS,
476 g_param_spec_boxed ("items", "Items", "Items in collection",
477 _secret_list_get_type (), G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
480 * SecretCollection:label:
482 * The human readable label for the collection.
484 * Setting this property will result in the label of the collection being
485 * set asynchronously. To properly track the changing of the label use the
486 * secret_collection_set_label() function.
488 g_object_class_install_property (gobject_class, PROP_LABEL,
489 g_param_spec_string ("label", "Label", "Item label",
490 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
493 * SecretCollection:locked:
495 * Whether the collection is locked or not.
497 * To lock or unlock a collection use the secret_service_lock() or
498 * secret_service_unlock() functions.
500 g_object_class_install_property (gobject_class, PROP_LOCKED,
501 g_param_spec_boolean ("locked", "Locked", "Item locked",
502 TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
505 * SecretCollection:created:
507 * The date and time (in seconds since the UNIX epoch) that this
508 * collection was created.
510 g_object_class_install_property (gobject_class, PROP_CREATED,
511 g_param_spec_uint64 ("created", "Created", "Item creation date",
512 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
515 * SecretCollection:modified:
517 * The date and time (in seconds since the UNIX epoch) that this
518 * collection was last modified.
520 g_object_class_install_property (gobject_class, PROP_MODIFIED,
521 g_param_spec_uint64 ("modified", "Modified", "Item modified date",
522 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
524 g_type_class_add_private (gobject_class, sizeof (SecretCollectionPrivate));
528 secret_collection_initable_init (GInitable *initable,
529 GCancellable *cancellable,
532 SecretCollection *self;
533 SecretService *service;
536 if (!secret_collection_initable_parent_iface->init (initable, cancellable, error))
539 proxy = G_DBUS_PROXY (initable);
541 if (!_secret_util_have_cached_properties (proxy)) {
542 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
543 "No such secret collection at path: %s",
544 g_dbus_proxy_get_object_path (proxy));
548 self = SECRET_COLLECTION (initable);
550 if (self->pv->service == NULL) {
551 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
555 collection_take_service (self, service);
558 if (self->pv->init_flags & SECRET_COLLECTION_LOAD_ITEMS) {
559 if (!secret_collection_load_items_sync (self, cancellable, error))
563 self->pv->constructing = FALSE;
568 secret_collection_initable_iface (GInitableIface *iface)
570 secret_collection_initable_parent_iface = g_type_interface_peek_parent (iface);
572 iface->init = secret_collection_initable_init;
576 GCancellable *cancellable;
580 init_closure_free (gpointer data)
582 InitClosure *closure = data;
583 g_clear_object (&closure->cancellable);
584 g_slice_free (InitClosure, closure);
588 on_init_items (GObject *source,
589 GAsyncResult *result,
592 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
593 SecretCollection *self = SECRET_COLLECTION (source);
594 GError *error = NULL;
596 if (!secret_collection_load_items_finish (self, result, &error))
597 g_simple_async_result_take_error (res, error);
599 g_simple_async_result_complete (res);
600 g_object_unref (res);
604 collection_ensure_for_flags_async (SecretCollection *self,
605 SecretCollectionFlags flags,
606 GSimpleAsyncResult *async)
608 InitClosure *init = g_simple_async_result_get_op_res_gpointer (async);
610 if (flags & SECRET_COLLECTION_LOAD_ITEMS)
611 secret_collection_load_items (self, init->cancellable,
612 on_init_items, g_object_ref (async));
615 g_simple_async_result_complete (async);
619 on_init_service (GObject *source,
620 GAsyncResult *result,
623 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
624 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
625 SecretService *service;
626 GError *error = NULL;
628 service = secret_service_get_finish (result, &error);
630 collection_take_service (self, service);
631 collection_ensure_for_flags_async (self, self->pv->init_flags, async);
634 g_simple_async_result_take_error (async, error);
635 g_simple_async_result_complete (async);
638 g_object_unref (self);
639 g_object_unref (async);
643 on_init_base (GObject *source,
644 GAsyncResult *result,
647 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
648 SecretCollection *self = SECRET_COLLECTION (source);
649 InitClosure *init = g_simple_async_result_get_op_res_gpointer (res);
650 GDBusProxy *proxy = G_DBUS_PROXY (self);
651 GError *error = NULL;
653 if (!secret_collection_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
655 g_simple_async_result_take_error (res, error);
656 g_simple_async_result_complete (res);
658 } else if (!_secret_util_have_cached_properties (proxy)) {
659 g_simple_async_result_set_error (res, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
660 "No such secret collection at path: %s",
661 g_dbus_proxy_get_object_path (proxy));
662 g_simple_async_result_complete (res);
664 } else if (self->pv->service == NULL) {
665 secret_service_get (SECRET_SERVICE_NONE, init->cancellable,
666 on_init_service, g_object_ref (res));
669 collection_ensure_for_flags_async (self, self->pv->init_flags, res);
672 g_object_unref (res);
676 secret_collection_async_initable_init_async (GAsyncInitable *initable,
678 GCancellable *cancellable,
679 GAsyncReadyCallback callback,
682 GSimpleAsyncResult *res;
683 InitClosure *closure;
685 res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data,
686 secret_collection_async_initable_init_async);
687 closure = g_slice_new0 (InitClosure);
688 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
689 g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free);
691 secret_collection_async_initable_parent_iface->init_async (initable, io_priority,
696 g_object_unref (res);
700 secret_collection_async_initable_init_finish (GAsyncInitable *initable,
701 GAsyncResult *result,
704 SecretCollection *self = SECRET_COLLECTION (initable);
706 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable),
707 secret_collection_async_initable_init_async), FALSE);
709 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
712 self->pv->constructing = FALSE;
717 secret_collection_async_initable_iface (GAsyncInitableIface *iface)
719 secret_collection_async_initable_parent_iface = g_type_interface_peek_parent (iface);
721 iface->init_async = secret_collection_async_initable_init_async;
722 iface->init_finish = secret_collection_async_initable_init_finish;
726 GCancellable *cancellable;
732 items_closure_free (gpointer data)
734 ItemsClosure *closure = data;
735 g_clear_object (&closure->cancellable);
736 g_hash_table_unref (closure->items);
737 g_slice_free (ItemsClosure, closure);
741 on_load_item (GObject *source,
742 GAsyncResult *result,
745 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
746 ItemsClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
747 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
749 GError *error = NULL;
752 closure->items_loading--;
754 item = secret_item_new_for_dbus_path_finish (result, &error);
757 g_simple_async_result_take_error (res, error);
760 path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
761 g_hash_table_insert (closure->items, g_strdup (path), item);
764 if (closure->items_loading == 0) {
765 collection_update_items (self, closure->items);
766 g_simple_async_result_complete_in_idle (res);
769 g_object_unref (self);
770 g_object_unref (res);
774 * secret_collection_load_items:
775 * @self: the secret collection
776 * @cancellable: optional cancellation object
777 * @callback: called when the operation completes
778 * @user_data: data to be passed to the callback
780 * Ensure that the #SecretCollection proxy has loaded all the items present
781 * in the Secret Service. This affects the result of
782 * secret_collection_get_items().
784 * For collections returned from secret_service_get_collections() the items
785 * will have already been loaded.
787 * This method will return immediately and complete asynchronously.
790 secret_collection_load_items (SecretCollection *self,
791 GCancellable *cancellable,
792 GAsyncReadyCallback callback,
795 ItemsClosure *closure;
797 GSimpleAsyncResult *res;
802 g_return_if_fail (SECRET_IS_COLLECTION (self));
803 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
805 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
806 g_return_if_fail (paths != NULL);
808 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
809 secret_collection_load_items);
810 closure = g_slice_new0 (ItemsClosure);
811 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
812 closure->items = items_table_new ();
813 g_simple_async_result_set_op_res_gpointer (res, closure, items_closure_free);
815 g_variant_iter_init (&iter, paths);
816 while (g_variant_iter_loop (&iter, "&o", &path)) {
817 item = collection_lookup_item (self, path);
819 /* No such collection yet create a new one */
821 secret_item_new_for_dbus_path (self->pv->service, path, SECRET_ITEM_NONE,
822 cancellable, on_load_item, g_object_ref (res));
823 closure->items_loading++;
826 g_hash_table_insert (closure->items, g_strdup (path), item);
830 if (closure->items_loading == 0) {
831 collection_update_items (self, closure->items);
832 g_simple_async_result_complete_in_idle (res);
835 g_variant_unref (paths);
836 g_object_unref (res);
840 * secret_collection_load_items_finish:
841 * @self: the secret collection
842 * @result: the asynchronous result passed to the callback
843 * @error: location to place an error on failure
845 * Complete an asynchronous operation to ensure that the #SecretCollection proxy
846 * has loaded all the items present in the Secret Service.
848 * Returns: whether the load was successful or not
851 secret_collection_load_items_finish (SecretCollection *self,
852 GAsyncResult *result,
855 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
856 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
857 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
858 secret_collection_load_items), FALSE);
860 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
867 * secret_collection_load_items_sync:
868 * @self: the secret collection
869 * @cancellable: optional cancellation object
870 * @error: location to place an error on failure
872 * Ensure that the #SecretCollection proxy has loaded all the items present
873 * in the Secret Service. This affects the result of
874 * secret_collection_get_items().
876 * For collections returned from secret_service_get_collections() the items
877 * will have already been loaded.
879 * This method may block indefinitely and should not be used in user interface
882 * Returns: whether the load was successful or not
885 secret_collection_load_items_sync (SecretCollection *self,
886 GCancellable *cancellable,
896 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
897 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
898 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
900 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
901 g_return_val_if_fail (paths != NULL, FALSE);
903 items = items_table_new ();
905 g_variant_iter_init (&iter, paths);
906 while (g_variant_iter_next (&iter, "&o", &path)) {
907 item = collection_lookup_item (self, path);
909 /* No such collection yet create a new one */
911 item = secret_item_new_for_dbus_path_sync (self->pv->service, path,
920 g_hash_table_insert (items, g_strdup (path), item);
924 collection_update_items (self, items);
926 g_hash_table_unref (items);
927 g_variant_unref (paths);
932 * secret_collection_refresh:
933 * @self: the collection
935 * Refresh the properties on this collection. This fires off a request to
936 * refresh, and the properties will be updated later.
938 * Calling this method is not normally necessary, as the secret service
939 * will notify the client when properties change.
942 secret_collection_refresh (SecretCollection *self)
944 g_return_if_fail (SECRET_IS_COLLECTION (self));
946 _secret_util_get_properties (G_DBUS_PROXY (self),
947 secret_collection_refresh,
948 self->pv->cancellable, NULL, NULL);
952 GCancellable *cancellable;
953 SecretCollection *collection;
954 GHashTable *properties;
956 SecretCollectionCreateFlags flags;
960 create_closure_free (gpointer data)
962 CreateClosure *closure = data;
963 g_clear_object (&closure->cancellable);
964 g_clear_object (&closure->collection);
965 g_hash_table_unref (closure->properties);
966 g_free (closure->alias);
967 g_slice_free (CreateClosure, closure);
971 on_create_collection (GObject *source,
972 GAsyncResult *result,
975 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
976 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
977 GError *error = NULL;
979 closure->collection = secret_collection_new_for_dbus_path_finish (result, &error);
981 g_simple_async_result_take_error (res, error);
983 g_simple_async_result_complete (res);
984 g_object_unref (res);
988 on_create_path (GObject *source,
989 GAsyncResult *result,
992 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
993 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
994 SecretService *service = SECRET_SERVICE (source);
995 GError *error = NULL;
998 path = secret_service_create_collection_dbus_path_finish (service, result, &error);
1000 secret_collection_new_for_dbus_path (service, path, SECRET_COLLECTION_LOAD_ITEMS,
1001 closure->cancellable,
1002 on_create_collection, g_object_ref (res));
1004 g_simple_async_result_take_error (res, error);
1005 g_simple_async_result_complete (res);
1008 g_object_unref (res);
1012 on_create_service (GObject *source,
1013 GAsyncResult *result,
1016 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1017 CreateClosure *create = g_simple_async_result_get_op_res_gpointer (async);
1018 GError *error = NULL;
1019 SecretService *service;
1021 service = secret_service_get_finish (result, &error);
1022 if (error == NULL) {
1023 secret_service_create_collection_dbus_path (service, create->properties,
1024 create->alias, create->flags,
1025 create->cancellable,
1026 on_create_path, g_object_ref (async));
1027 g_object_unref (service);
1030 g_simple_async_result_take_error (async, error);
1031 g_simple_async_result_complete (async);
1034 g_object_unref (async);
1038 collection_properties_new (const gchar *label)
1040 GHashTable *properties;
1043 properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
1044 (GDestroyNotify)g_variant_unref);
1045 value = g_variant_new_string (label);
1046 g_hash_table_insert (properties,
1047 SECRET_COLLECTION_INTERFACE ".Label",
1048 g_variant_ref_sink (value));
1054 * secret_collection_create:
1055 * @service: (allow-none): a secret service object
1056 * @label: label for the new collection
1057 * @alias: (allow-none): alias to assign to the collection
1058 * @flags: currently unused
1059 * @cancellable: optional cancellation object
1060 * @callback: called when the operation completes
1061 * @user_data: data to pass to the callback
1063 * Create a new collection in the secret service.
1065 * This method returns immediately and completes asynchronously. The secret
1066 * service may prompt the user. secret_service_prompt() will be used to handle
1067 * any prompts that are required.
1069 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1070 * default collection to store items in). This allows other applications to
1071 * easily identify and share a collection. If you specify an @alias, and a
1072 * collection with that alias already exists, then a new collection will not
1073 * be created. The previous one will be returned instead.
1075 * If @service is NULL, then secret_service_get() will be called to get
1076 * the default #SecretService proxy.
1080 secret_collection_create (SecretService *service,
1083 SecretCollectionCreateFlags flags,
1084 GCancellable *cancellable,
1085 GAsyncReadyCallback callback,
1088 GSimpleAsyncResult *res;
1089 CreateClosure *closure;
1091 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
1092 g_return_if_fail (label != NULL);
1093 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1095 res = g_simple_async_result_new (NULL, callback, user_data,
1096 secret_collection_create);
1097 closure = g_slice_new0 (CreateClosure);
1098 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1099 closure->properties = collection_properties_new (label);
1100 closure->alias = g_strdup (alias);
1101 closure->flags = flags;
1102 g_simple_async_result_set_op_res_gpointer (res, closure, create_closure_free);
1104 if (service == NULL) {
1105 secret_service_get (SECRET_SERVICE_NONE, cancellable,
1106 on_create_service, g_object_ref (res));
1109 secret_service_create_collection_dbus_path (service, closure->properties,
1110 closure->alias, closure->flags,
1111 closure->cancellable,
1112 on_create_path, g_object_ref (res));
1115 g_object_unref (res);
1119 * secret_collection_create_finish:
1120 * @result: the asynchronous result passed to the callback
1121 * @error: location to place an error on failure
1123 * Finish operation to create a new collection in the secret service.
1125 * Returns: (transfer full): the new collection, which should be unreferenced
1126 * with g_object_unref()
1129 secret_collection_create_finish (GAsyncResult *result,
1132 GSimpleAsyncResult *res;
1133 CreateClosure *closure;
1135 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
1136 secret_collection_create), NULL);
1137 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1139 res = G_SIMPLE_ASYNC_RESULT (result);
1141 if (g_simple_async_result_propagate_error (res, error))
1144 closure = g_simple_async_result_get_op_res_gpointer (res);
1145 if (closure->collection == NULL)
1148 return g_object_ref (closure->collection);
1152 * secret_collection_create_sync:
1153 * @service: (allow-none): a secret service object
1154 * @label: label for the new collection
1155 * @alias: (allow-none): alias to assign to the collection
1156 * @flags: currently unused
1157 * @cancellable: optional cancellation object
1158 * @error: location to place an error on failure
1160 * Create a new collection in the secret service.
1162 * This method may block indefinitely and should not be used in user interface
1163 * threads. The secret service may prompt the user. secret_service_prompt()
1164 * will be used to handle any prompts that are required.
1166 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1167 * default collection to store items in). This allows other applications to
1168 * easily identify and share a collection. If you specify an @alias, and a
1169 * collection with that alias already exists, then a new collection will not
1170 * be created. The previous one will be returned instead.
1172 * If @service is NULL, then secret_service_get_sync() will be called to get
1173 * the default #SecretService proxy.
1175 * Returns: (transfer full): the new collection, which should be unreferenced
1176 * with g_object_unref()
1179 secret_collection_create_sync (SecretService *service,
1182 SecretCollectionCreateFlags flags,
1183 GCancellable *cancellable,
1186 SecretCollection *collection;
1187 GHashTable *properties;
1190 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
1191 g_return_val_if_fail (label != NULL, NULL);
1192 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1193 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1195 if (service == NULL) {
1196 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
1197 if (service == NULL)
1200 g_object_ref (service);
1203 properties = collection_properties_new (label);
1205 path = secret_service_create_collection_dbus_path_sync (service, properties, alias,
1206 flags, cancellable, error);
1208 g_hash_table_unref (properties);
1211 g_object_unref (service);
1215 collection = secret_collection_new_for_dbus_path_sync (service, path,
1216 SECRET_COLLECTION_LOAD_ITEMS,
1217 cancellable, error);
1219 g_object_unref (service);
1226 SecretCollection *collection;
1227 GCancellable *cancellable;
1231 SecretSearchFlags flags;
1235 search_closure_free (gpointer data)
1237 SearchClosure *closure = data;
1238 g_object_unref (closure->collection);
1239 g_clear_object (&closure->cancellable);
1240 g_hash_table_unref (closure->items);
1241 g_strfreev (closure->paths);
1242 g_slice_free (SearchClosure, closure);
1246 search_closure_take_item (SearchClosure *closure,
1249 const gchar *path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
1250 g_hash_table_insert (closure->items, (gpointer)path, item);
1254 on_search_secrets (GObject *source,
1255 GAsyncResult *result,
1258 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1260 /* Note that we ignore any unlock failure */
1261 secret_item_load_secrets_finish (result, NULL);
1263 g_simple_async_result_complete (async);
1264 g_object_unref (async);
1268 on_search_unlocked (GObject *source,
1269 GAsyncResult *result,
1272 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1273 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1276 /* Note that we ignore any unlock failure */
1277 secret_service_unlock_finish (SECRET_SERVICE (source), result, NULL, NULL);
1279 /* If loading secrets ... locked items automatically ignored */
1280 if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1281 items = g_hash_table_get_values (search->items);
1282 secret_item_load_secrets (items, search->cancellable,
1283 on_search_secrets, g_object_ref (async));
1284 g_list_free (items);
1286 /* No additional options, just complete */
1288 g_simple_async_result_complete (async);
1291 g_object_unref (async);
1295 secret_search_unlock_load_or_complete (GSimpleAsyncResult *async,
1296 SearchClosure *search)
1300 /* If unlocking then unlock all the locked items */
1301 if (search->flags & SECRET_SEARCH_UNLOCK) {
1302 items = g_hash_table_get_values (search->items);
1303 secret_service_unlock (secret_collection_get_service (search->collection),
1304 items, search->cancellable,
1305 on_search_unlocked, g_object_ref (async));
1306 g_list_free (items);
1308 /* If loading secrets ... locked items automatically ignored */
1309 } else if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1310 items = g_hash_table_get_values (search->items);
1311 secret_item_load_secrets (items, search->cancellable,
1312 on_search_secrets, g_object_ref (async));
1313 g_list_free (items);
1315 /* No additional options, just complete */
1317 g_simple_async_result_complete (async);
1322 on_search_loaded (GObject *source,
1323 GAsyncResult *result,
1326 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1327 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1328 GError *error = NULL;
1333 item = secret_item_new_for_dbus_path_finish (result, &error);
1335 g_simple_async_result_take_error (async, error);
1338 search_closure_take_item (search, item);
1340 /* We're done loading, lets go to the next step */
1341 if (search->loading == 0)
1342 secret_search_unlock_load_or_complete (async, search);
1344 g_object_unref (async);
1348 on_search_paths (GObject *source,
1349 GAsyncResult *result,
1352 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1353 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1354 SecretCollection *self = search->collection;
1355 SecretService *service = secret_collection_get_service (self);
1356 GError *error = NULL;
1361 search->paths = secret_collection_search_for_dbus_paths_finish (self, result, &error);
1362 if (error == NULL) {
1364 if (search->flags & SECRET_SEARCH_ALL)
1367 for (i = 0; i < want && search->paths[i] != NULL; i++) {
1368 item = _secret_collection_find_item_instance (self, search->paths[i]);
1370 secret_item_new_for_dbus_path (service, search->paths[i], SECRET_ITEM_NONE,
1371 search->cancellable, on_search_loaded,
1372 g_object_ref (async));
1375 search_closure_take_item (search, item);
1380 /* No items loading, complete operation now */
1381 if (search->loading == 0)
1382 secret_search_unlock_load_or_complete (async, search);
1385 g_simple_async_result_take_error (async, error);
1386 g_simple_async_result_complete (async);
1389 g_object_unref (async);
1393 * secret_collection_search:
1394 * @self: a secret collection
1395 * @schema: (allow-none): the schema for the attributes
1396 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1397 * @flags: search option flags
1398 * @cancellable: optional cancellation object
1399 * @callback: called when the operation completes
1400 * @user_data: data to pass to the callback
1402 * Search for items matching the @attributes in the @collection.
1403 * The @attributes should be a table of string keys and string values.
1405 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1406 * search will be returned. Otherwise only the first item will be returned.
1407 * This is almost always the unlocked item that was most recently stored.
1409 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1410 * if necessary. In either case, locked and unlocked items will match the
1411 * search and be returned. If the unlock fails, the search does not fail.
1413 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1414 * their secret values loaded and available via secret_item_get_secret().
1416 * This function returns immediately and completes asynchronously.
1419 secret_collection_search (SecretCollection *self,
1420 const SecretSchema *schema,
1421 GHashTable *attributes,
1422 SecretSearchFlags flags,
1423 GCancellable *cancellable,
1424 GAsyncReadyCallback callback,
1427 GSimpleAsyncResult *async;
1428 SearchClosure *search;
1430 g_return_if_fail (SECRET_IS_COLLECTION (self));
1431 g_return_if_fail (attributes != NULL);
1432 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1434 /* Warnings raised already */
1435 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1438 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1439 secret_collection_search);
1440 search = g_slice_new0 (SearchClosure);
1441 search->collection = g_object_ref (self);
1442 search->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1443 search->items = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
1444 search->flags = flags;
1445 g_simple_async_result_set_op_res_gpointer (async, search, search_closure_free);
1447 secret_collection_search_for_dbus_paths (self, schema, attributes,
1448 cancellable, on_search_paths,
1449 g_object_ref (async));
1451 g_object_unref (async);
1455 * secret_collection_search_finish:
1456 * @self: the secret collection
1457 * @result: asynchronous result passed to callback
1458 * @error: location to place error on failure
1460 * Complete asynchronous operation to search for items in a collection.
1462 * Returns: (transfer full) (element-type SecretUnstable.Item):
1463 * a list of items that matched the search
1466 secret_collection_search_finish (SecretCollection *self,
1467 GAsyncResult *result,
1470 GSimpleAsyncResult *async;
1471 SearchClosure *search;
1472 GList *items = NULL;
1476 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1477 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1478 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1479 secret_collection_search), NULL);
1481 async = G_SIMPLE_ASYNC_RESULT (result);
1482 if (g_simple_async_result_propagate_error (async, error))
1485 search = g_simple_async_result_get_op_res_gpointer (async);
1487 for (i = 0; search->paths[i]; i++) {
1488 item = g_hash_table_lookup (search->items, search->paths[i]);
1490 items = g_list_prepend (items, g_object_ref (item));
1493 return g_list_reverse (items);
1497 collection_load_items_sync (SecretCollection *self,
1498 GCancellable *cancellable,
1504 SecretService *service = secret_collection_get_service (self);
1509 for (i = 0; have < want && paths[i] != NULL; i++) {
1510 item = _secret_collection_find_item_instance (self, paths[i]);
1512 item = secret_item_new_for_dbus_path_sync (service, paths[i], SECRET_ITEM_NONE,
1513 cancellable, error);
1518 *items = g_list_prepend (*items, item);
1527 * secret_collection_search_sync:
1528 * @self: a secret collection
1529 * @schema: (allow-none): the schema for the attributes
1530 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1531 * @flags: search option flags
1532 * @cancellable: optional cancellation object
1533 * @error: location to place error on failure
1535 * Search for items matching the @attributes in the @collection.
1536 * The @attributes should be a table of string keys and string values.
1538 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1539 * search will be returned. Otherwise only the first item will be returned.
1540 * This is almost always the unlocked item that was most recently stored.
1542 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1543 * if necessary. In either case, locked and unlocked items will match the
1544 * search and be returned. If the unlock fails, the search does not fail.
1546 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1547 * their secret values loaded and available via secret_item_get_secret().
1549 * This function may block indefinetely. Use the asynchronous version
1550 * in user interface threads.
1552 * Returns: (transfer full) (element-type SecretUnstable.Item):
1553 * a list of items that matched the search
1556 secret_collection_search_sync (SecretCollection *self,
1557 const SecretSchema *schema,
1558 GHashTable *attributes,
1559 SecretSearchFlags flags,
1560 GCancellable *cancellable,
1563 gchar **paths = NULL;
1564 GList *items = NULL;
1568 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1569 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1570 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1572 /* Warnings raised already */
1573 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1576 paths = secret_collection_search_for_dbus_paths_sync (self, schema, attributes,
1577 cancellable, error);
1584 if (flags & SECRET_SEARCH_ALL)
1587 ret = collection_load_items_sync (self, cancellable, paths,
1588 &items, want, error);
1595 if (flags & SECRET_SEARCH_UNLOCK) {
1596 secret_service_unlock_sync (secret_collection_get_service (self),
1597 items, cancellable, NULL, NULL);
1600 if (flags & SECRET_SEARCH_LOAD_SECRETS)
1601 secret_item_load_secrets_sync (items, NULL, NULL);
1607 on_service_delete_path (GObject *source,
1608 GAsyncResult *result,
1611 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1612 GError *error = NULL;
1614 _secret_service_delete_path_finish (SECRET_SERVICE (source), result, &error);
1616 g_simple_async_result_take_error (async, error);
1617 g_simple_async_result_complete (async);
1618 g_object_unref (async);
1621 * secret_collection_delete:
1622 * @self: a collection
1623 * @cancellable: optional cancellation object
1624 * @callback: called when the operation completes
1625 * @user_data: data to pass to the callback
1627 * Delete this collection.
1629 * This method returns immediately and completes asynchronously. The secret
1630 * service may prompt the user. secret_service_prompt() will be used to handle
1631 * any prompts that show up.
1634 secret_collection_delete (SecretCollection *self,
1635 GCancellable *cancellable,
1636 GAsyncReadyCallback callback,
1639 GSimpleAsyncResult *async;
1640 const gchar *object_path;
1642 g_return_if_fail (SECRET_IS_COLLECTION (self));
1643 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1645 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1646 secret_collection_delete);
1648 object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
1649 _secret_service_delete_path (self->pv->service, object_path, FALSE,
1650 cancellable, on_service_delete_path,
1651 g_object_ref (async));
1653 g_object_unref (async);
1657 * secret_collection_delete_finish:
1658 * @self: a collection
1659 * @result: asynchronous result passed to the callback
1660 * @error: location to place an error on failure
1662 * Complete operation to delete this collection.
1664 * Returns: whether the collection was successfully deleted or not
1667 secret_collection_delete_finish (SecretCollection *self,
1668 GAsyncResult *result,
1671 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1672 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1673 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1674 secret_collection_delete), FALSE);
1676 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
1683 * secret_collection_delete_sync:
1684 * @self: a collection
1685 * @cancellable: optional cancellation object
1686 * @error: location to place an error on failure
1688 * Delete this collection.
1690 * This method may block indefinitely and should not be used in user
1691 * interface threads. The secret service may prompt the user.
1692 * secret_service_prompt() will be used to handle any prompts that show up.
1694 * Returns: whether the collection was successfully deleted or not
1697 secret_collection_delete_sync (SecretCollection *self,
1698 GCancellable *cancellable,
1704 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1705 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1706 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1708 sync = _secret_sync_new ();
1709 g_main_context_push_thread_default (sync->context);
1711 secret_collection_delete (self, cancellable, _secret_sync_on_result, sync);
1713 g_main_loop_run (sync->loop);
1715 ret = secret_collection_delete_finish (self, sync->result, error);
1717 g_main_context_pop_thread_default (sync->context);
1718 _secret_sync_free (sync);
1724 * secret_collection_get_service:
1725 * @self: a collection
1727 * Get the Secret Service object that this collection was created with.
1729 * Returns: (transfer none): the Secret Service object
1732 secret_collection_get_service (SecretCollection *self)
1734 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1735 return self->pv->service;
1739 * secret_collection_get_flags:
1740 * @self: the secret collection proxy
1742 * Get the flags representing what features of the #SecretCollection proxy
1743 * have been initialized.
1745 * Use secret_collection_load_items() to initialize further features
1746 * and change the flags.
1748 * Returns: the flags for features initialized
1750 SecretCollectionFlags
1751 secret_collection_get_flags (SecretCollection *self)
1753 SecretCollectionFlags flags = 0;
1755 g_return_val_if_fail (SECRET_IS_COLLECTION (self), SECRET_COLLECTION_NONE);
1757 g_mutex_lock (&self->pv->mutex);
1759 if (self->pv->items)
1760 flags |= SECRET_COLLECTION_LOAD_ITEMS;
1762 g_mutex_unlock (&self->pv->mutex);
1768 * secret_collection_get_items:
1769 * @self: a collection
1771 * Get the list of items in this collection.
1773 * Returns: (transfer full) (element-type SecretUnstable.Item): a list of items,
1774 * when done, the list should be freed with g_list_free, and each item should
1775 * be released with g_object_unref()
1778 secret_collection_get_items (SecretCollection *self)
1782 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1784 g_mutex_lock (&self->pv->mutex);
1785 items = g_hash_table_get_values (self->pv->items);
1786 for (l = items; l != NULL; l = g_list_next (l))
1787 g_object_ref (l->data);
1788 g_mutex_unlock (&self->pv->mutex);
1794 _secret_collection_find_item_instance (SecretCollection *self,
1795 const gchar *item_path)
1799 g_mutex_lock (&self->pv->mutex);
1800 item = g_hash_table_lookup (self->pv->items, item_path);
1802 g_object_ref (item);
1803 g_mutex_unlock (&self->pv->mutex);
1809 * secret_collection_get_label:
1810 * @self: a collection
1812 * Get the label of this collection.
1814 * Returns: (transfer full): the label, which should be freed with g_free()
1817 secret_collection_get_label (SecretCollection *self)
1822 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1824 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Label");
1825 g_return_val_if_fail (variant != NULL, NULL);
1827 label = g_variant_dup_string (variant, NULL);
1828 g_variant_unref (variant);
1834 * secret_collection_set_label:
1835 * @self: a collection
1836 * @label: a new label
1837 * @cancellable: optional cancellation object
1838 * @callback: called when the operation completes
1839 * @user_data: data to pass to the callback
1841 * Set the label of this collection.
1843 * This function returns immediately and completes asynchronously.
1846 secret_collection_set_label (SecretCollection *self,
1848 GCancellable *cancellable,
1849 GAsyncReadyCallback callback,
1852 g_return_if_fail (SECRET_IS_COLLECTION (self));
1853 g_return_if_fail (label != NULL);
1855 _secret_util_set_property (G_DBUS_PROXY (self), "Label",
1856 g_variant_new_string (label),
1857 secret_collection_set_label,
1858 cancellable, callback, user_data);
1862 * secret_collection_set_label_finish:
1863 * @self: a collection
1864 * @result: asynchronous result passed to callback
1865 * @error: location to place error on failure
1867 * Complete asynchronous operation to set the label of this collection.
1869 * Returns: whether the change was successful or not
1872 secret_collection_set_label_finish (SecretCollection *self,
1873 GAsyncResult *result,
1876 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1878 return _secret_util_set_property_finish (G_DBUS_PROXY (self),
1879 secret_collection_set_label,
1884 * secret_collection_set_label_sync:
1885 * @self: a collection
1886 * @label: a new label
1887 * @cancellable: optional cancellation object
1888 * @error: location to place error on failure
1890 * Set the label of this collection.
1892 * This function may block indefinetely. Use the asynchronous version
1893 * in user interface threads.
1895 * Returns: whether the change was successful or not
1898 secret_collection_set_label_sync (SecretCollection *self,
1900 GCancellable *cancellable,
1903 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1904 g_return_val_if_fail (label != NULL, FALSE);
1906 return _secret_util_set_property_sync (G_DBUS_PROXY (self), "Label",
1907 g_variant_new_string (label),
1908 cancellable, error);
1912 * secret_collection_get_locked:
1913 * @self: a collection
1915 * Get whether the collection is locked or not.
1917 * Use secret_service_lock() or secret_service_unlock() to lock or unlock the
1920 * Returns: whether the collection is locked or not
1923 secret_collection_get_locked (SecretCollection *self)
1928 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1930 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Locked");
1931 g_return_val_if_fail (variant != NULL, TRUE);
1933 locked = g_variant_get_boolean (variant);
1934 g_variant_unref (variant);
1940 * secret_collection_get_created:
1941 * @self: a collection
1943 * Get the created date and time of the collection. The return value is
1944 * the number of seconds since the unix epoch, January 1st 1970.
1946 * Returns: the created date and time
1949 secret_collection_get_created (SecretCollection *self)
1954 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1956 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Created");
1957 g_return_val_if_fail (variant != NULL, 0);
1959 created = g_variant_get_uint64 (variant);
1960 g_variant_unref (variant);
1966 * secret_collection_get_modified:
1967 * @self: a collection
1969 * Get the modified date and time of the collection. The return value is
1970 * the number of seconds since the unix epoch, January 1st 1970.
1972 * Returns: the modified date and time
1975 secret_collection_get_modified (SecretCollection *self)
1980 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1982 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Modified");
1983 g_return_val_if_fail (variant != NULL, 0);
1985 modified = g_variant_get_uint64 (variant);
1986 g_variant_unref (variant);
1993 GCancellable *cancellable;
1995 SecretCollection *collection;
1999 read_closure_free (gpointer data)
2001 ReadClosure *read = data;
2002 g_free (read->alias);
2003 if (read->collection)
2004 g_object_unref (read->collection);
2005 if (read->cancellable)
2006 g_object_unref (read->cancellable);
2007 g_slice_free (ReadClosure, read);
2011 on_read_alias_collection (GObject *source,
2012 GAsyncResult *result,
2015 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2016 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2017 GError *error = NULL;
2019 read->collection = secret_collection_new_for_dbus_path_finish (result, &error);
2021 g_simple_async_result_take_error (async, error);
2023 g_simple_async_result_complete (async);
2024 g_object_unref (async);
2028 on_read_alias_path (GObject *source,
2029 GAsyncResult *result,
2032 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2033 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2034 SecretService *self = SECRET_SERVICE (source);
2035 GError *error = NULL;
2036 gchar *collection_path;
2038 collection_path = secret_service_read_alias_dbus_path_finish (self, result, &error);
2039 if (error == NULL) {
2041 /* No collection for this alias */
2042 if (collection_path == NULL) {
2043 g_simple_async_result_complete (async);
2046 read->collection = _secret_service_find_collection_instance (self,
2048 if (read->collection != NULL) {
2049 g_simple_async_result_complete (async);
2051 /* No collection loaded, but valid path, load */
2053 secret_collection_new_for_dbus_path (self, collection_path,
2054 SECRET_COLLECTION_NONE,
2056 on_read_alias_collection,
2057 g_object_ref (async));
2062 g_simple_async_result_take_error (async, error);
2063 g_simple_async_result_complete (async);
2066 g_free (collection_path);
2067 g_object_unref (async);
2071 on_read_alias_service (GObject *source,
2072 GAsyncResult *result,
2075 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2076 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2077 SecretService *service;
2078 GError *error = NULL;
2080 service = secret_service_get_finish (result, &error);
2081 if (error == NULL) {
2082 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2083 on_read_alias_path, g_object_ref (async));
2084 g_object_unref (service);
2087 g_simple_async_result_take_error (async, error);
2088 g_simple_async_result_complete (async);
2091 g_object_unref (async);
2095 * secret_collection_for_alias:
2096 * @service: (allow-none): a secret service object
2097 * @alias: the alias to lookup
2098 * @cancellable: (allow-none): optional cancellation object
2099 * @callback: called when the operation completes
2100 * @user_data: data to pass to the callback
2102 * Lookup which collection is assigned to this alias. Aliases help determine
2103 * well known collections, such as 'default'.
2105 * If @service is NULL, then secret_service_get() will be called to get
2106 * the default #SecretService proxy.
2108 * This method will return immediately and complete asynchronously.
2111 secret_collection_for_alias (SecretService *service,
2113 GCancellable *cancellable,
2114 GAsyncReadyCallback callback,
2117 GSimpleAsyncResult *async;
2120 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
2121 g_return_if_fail (alias != NULL);
2122 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2124 async = g_simple_async_result_new (NULL, callback, user_data,
2125 secret_collection_for_alias);
2126 read = g_slice_new0 (ReadClosure);
2127 read->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
2128 read->alias = g_strdup (alias);
2129 g_simple_async_result_set_op_res_gpointer (async, read, read_closure_free);
2131 if (service == NULL) {
2132 secret_service_get (SECRET_SERVICE_NONE, cancellable,
2133 on_read_alias_service, g_object_ref (async));
2135 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2136 on_read_alias_path, g_object_ref (async));
2139 g_object_unref (async);
2143 * secret_collection_for_alias_finish:
2144 * @result: asynchronous result passed to callback
2145 * @error: location to place error on failure
2147 * Finish an asynchronous operation to lookup which collection is assigned
2150 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2153 secret_collection_for_alias_finish (GAsyncResult *result,
2156 GSimpleAsyncResult *async;
2159 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
2160 secret_collection_for_alias), NULL);
2161 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2163 async = G_SIMPLE_ASYNC_RESULT (result);
2164 if (g_simple_async_result_propagate_error (async, error))
2166 read = g_simple_async_result_get_op_res_gpointer (async);
2167 if (read->collection)
2168 g_object_ref (read->collection);
2169 return read->collection;
2173 * secret_collection_for_alias_sync:
2174 * @service: (allow-none): a secret service object
2175 * @alias: the alias to lookup
2176 * @cancellable: (allow-none): optional cancellation object
2177 * @error: location to place error on failure
2179 * Lookup which collection is assigned to this alias. Aliases help determine
2180 * well known collections, such as 'default'.
2182 * If @service is NULL, then secret_service_get_sync() will be called to get
2183 * the default #SecretService proxy.
2185 * This method may block and should not be used in user interface threads.
2187 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2190 secret_collection_for_alias_sync (SecretService *service,
2192 GCancellable *cancellable,
2195 SecretCollection *collection;
2196 gchar *collection_path;
2198 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
2199 g_return_val_if_fail (alias != NULL, NULL);
2200 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2201 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2203 collection_path = secret_service_read_alias_dbus_path_sync (service, alias,
2204 cancellable, error);
2205 if (collection_path == NULL)
2208 /* No collection for this alias */
2209 if (collection_path == NULL) {
2213 collection = _secret_service_find_collection_instance (service,
2216 /* No collection loaded, but valid path, load */
2217 if (collection == NULL) {
2218 collection = secret_collection_new_for_dbus_path_sync (service, collection_path,
2219 SECRET_COLLECTION_LOAD_ITEMS,
2220 cancellable, error);
2224 g_free (collection_path);