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-item.h"
20 #include "secret-paths.h"
21 #include "secret-private.h"
22 #include "secret-service.h"
23 #include "secret-types.h"
25 #include "libsecret/secret-enum-types.h"
27 #include <glib/gi18n-lib.h>
30 * SECTION:secret-collection
31 * @title: SecretCollection
32 * @short_description: A collection of secret items
34 * #SecretCollection represents a collection of secret items stored in the
37 * A collection can be in a locked or unlocked state. Use secret_service_lock()
38 * or secret_service_unlock() to lock or unlock the collection.
40 * Use the SecretCollection::items property or secret_collection_get_items() to
41 * lookup the items in the collection. There may not be any items exposed when
42 * the collection is locked.
50 * A proxy object representing a collection of secrets in the Secret Service.
54 * SecretCollectionClass:
55 * @parent_class: the parent class
57 * The class for #SecretCollection.
61 * SecretCollectionFlags:
62 * @SECRET_COLLECTION_NONE: no flags
63 * @SECRET_COLLECTION_LOAD_ITEMS: items have or should be loaded
65 * Flags which determine which parts of the #SecretCollection proxy are initialized.
69 * SecretCollectionCreateFlags:
70 * @SECRET_COLLECTION_CREATE_NONE: no flags
72 * Flags for secret_collection_create().
76 * SECRET_COLLECTION_DEFAULT:
78 * An alias to the default collection. This can be passed to secret_password_store()
79 * secret_collection_for_alias().
83 * SECRET_COLLECTION_SESSION:
85 * An alias to the session collection, which will be cleared when the user ends
86 * the session. This can be passed to secret_password_store(),
87 * secret_collection_for_alias() or similar functions.
101 struct _SecretCollectionPrivate {
102 /* Doesn't change between construct and finalize */
103 SecretService *service;
104 GCancellable *cancellable;
105 gboolean constructing;
106 SecretCollectionFlags init_flags;
108 /* Protected by mutex */
113 static GInitableIface *secret_collection_initable_parent_iface = NULL;
115 static GAsyncInitableIface *secret_collection_async_initable_parent_iface = NULL;
117 static void secret_collection_initable_iface (GInitableIface *iface);
119 static void secret_collection_async_initable_iface (GAsyncInitableIface *iface);
121 G_DEFINE_TYPE_WITH_CODE (SecretCollection, secret_collection, G_TYPE_DBUS_PROXY,
122 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, secret_collection_initable_iface);
123 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, secret_collection_async_initable_iface);
127 items_table_new (void)
129 return g_hash_table_new_full (g_str_hash, g_str_equal,
130 g_free, g_object_unref);
134 secret_collection_init (SecretCollection *self)
136 self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SECRET_TYPE_COLLECTION,
137 SecretCollectionPrivate);
139 g_mutex_init (&self->pv->mutex);
140 self->pv->cancellable = g_cancellable_new ();
141 self->pv->constructing = TRUE;
145 on_set_label (GObject *source,
146 GAsyncResult *result,
149 SecretCollection *self = SECRET_COLLECTION (user_data);
150 GError *error = NULL;
152 secret_collection_set_label_finish (self, result, &error);
154 g_warning ("couldn't set SecretCollection Label: %s", error->message);
155 g_error_free (error);
158 g_object_unref (self);
162 collection_take_service (SecretCollection *self,
163 SecretService *service)
168 g_return_if_fail (self->pv->service == NULL);
170 self->pv->service = service;
171 g_object_add_weak_pointer (G_OBJECT (self->pv->service),
172 (gpointer *)&self->pv->service);
174 /* Yes, we expect that the service will stay around */
175 g_object_unref (service);
179 secret_collection_set_property (GObject *obj,
184 SecretCollection *self = SECRET_COLLECTION (obj);
188 collection_take_service (self, g_value_dup_object (value));
191 self->pv->init_flags = g_value_get_flags (value);
194 secret_collection_set_label (self, g_value_get_string (value),
195 self->pv->cancellable, on_set_label,
196 g_object_ref (self));
199 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
205 secret_collection_get_property (GObject *obj,
210 SecretCollection *self = SECRET_COLLECTION (obj);
214 g_value_set_object (value, self->pv->service);
217 g_value_set_flags (value, secret_collection_get_flags (self));
220 g_value_take_boxed (value, secret_collection_get_items (self));
223 g_value_take_string (value, secret_collection_get_label (self));
226 g_value_set_boolean (value, secret_collection_get_locked (self));
229 g_value_set_uint64 (value, secret_collection_get_created (self));
232 g_value_set_uint64 (value, secret_collection_get_modified (self));
235 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
241 secret_collection_dispose (GObject *obj)
243 SecretCollection *self = SECRET_COLLECTION (obj);
245 g_cancellable_cancel (self->pv->cancellable);
247 G_OBJECT_CLASS (secret_collection_parent_class)->dispose (obj);
251 secret_collection_finalize (GObject *obj)
253 SecretCollection *self = SECRET_COLLECTION (obj);
255 if (self->pv->service)
256 g_object_remove_weak_pointer (G_OBJECT (self->pv->service),
257 (gpointer *)&self->pv->service);
259 g_mutex_clear (&self->pv->mutex);
261 g_hash_table_destroy (self->pv->items);
262 g_object_unref (self->pv->cancellable);
264 G_OBJECT_CLASS (secret_collection_parent_class)->finalize (obj);
268 collection_update_items (SecretCollection *self,
271 GHashTable *previous;
273 g_hash_table_ref (items);
275 g_mutex_lock (&self->pv->mutex);
276 previous = self->pv->items;
277 self->pv->items = items;
278 g_mutex_unlock (&self->pv->mutex);
280 if (previous != NULL)
281 g_hash_table_unref (previous);
283 g_object_notify (G_OBJECT (self), "items");
287 handle_property_changed (SecretCollection *self,
288 const gchar *property_name,
293 if (g_str_equal (property_name, "Label")) {
294 g_object_notify (G_OBJECT (self), "label");
296 } else if (g_str_equal (property_name, "Locked")) {
297 g_object_notify (G_OBJECT (self), "locked");
299 } else if (g_str_equal (property_name, "Created")) {
300 g_object_notify (G_OBJECT (self), "created");
302 } else if (g_str_equal (property_name, "Modified")) {
303 g_object_notify (G_OBJECT (self), "modified");
305 } else if (g_str_equal (property_name, "Items") && !self->pv->constructing) {
306 g_mutex_lock (&self->pv->mutex);
307 perform = self->pv->items != NULL;
308 g_mutex_unlock (&self->pv->mutex);
311 secret_collection_load_items (self, self->pv->cancellable, NULL, NULL);
316 secret_collection_properties_changed (GDBusProxy *proxy,
317 GVariant *changed_properties,
318 const gchar* const *invalidated_properties)
320 SecretCollection *self = SECRET_COLLECTION (proxy);
321 gchar *property_name;
325 g_object_freeze_notify (G_OBJECT (self));
327 g_variant_iter_init (&iter, changed_properties);
328 while (g_variant_iter_loop (&iter, "{sv}", &property_name, &value))
329 handle_property_changed (self, property_name, value);
331 g_object_thaw_notify (G_OBJECT (self));
335 secret_collection_signal (GDBusProxy *proxy,
336 const gchar *sender_name,
337 const gchar *signal_name,
338 GVariant *parameters)
340 SecretCollection *self = SECRET_COLLECTION (proxy);
342 const gchar *item_path;
343 GVariantBuilder builder;
344 gboolean found = FALSE;
351 * Remember that these signals come from a time before PropertiesChanged.
352 * We support them because they're in the spec, and ksecretservice uses them.
355 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
357 /* A new collection was added, add it to the Collections property */
358 if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CREATED)) {
359 g_variant_get (parameters, "(@o)", &value);
360 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
361 g_variant_iter_init (&iter, paths);
362 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
363 if (g_variant_equal (path, value)) {
367 g_variant_builder_add_value (&builder, path);
368 g_variant_unref (path);
371 g_variant_builder_add_value (&builder, value);
372 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
374 g_variant_builder_clear (&builder);
375 g_variant_unref (value);
377 /* A collection was deleted, remove it from the Collections property */
378 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_DELETED)) {
379 g_variant_get (parameters, "(@o)", &value);
380 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
381 g_variant_iter_init (&iter, paths);
382 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
383 if (g_variant_equal (path, value))
386 g_variant_builder_add_value (&builder, path);
387 g_variant_unref (path);
390 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
391 g_variant_unref (value);
393 /* The collection changed, update it */
394 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CHANGED)) {
395 g_variant_get (parameters, "(&o)", &item_path);
397 g_mutex_lock (&self->pv->mutex);
400 item = g_hash_table_lookup (self->pv->items, item_path);
406 g_mutex_unlock (&self->pv->mutex);
409 secret_item_refresh (item);
410 g_object_unref (item);
414 g_variant_unref (paths);
418 secret_collection_class_init (SecretCollectionClass *klass)
420 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
421 GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass);
423 gobject_class->get_property = secret_collection_get_property;
424 gobject_class->set_property = secret_collection_set_property;
425 gobject_class->dispose = secret_collection_dispose;
426 gobject_class->finalize = secret_collection_finalize;
428 proxy_class->g_properties_changed = secret_collection_properties_changed;
429 proxy_class->g_signal = secret_collection_signal;
432 * SecretCollection:service:
434 * The #SecretService object that this collection is associated with and
435 * uses to interact with the actual D-Bus Secret Service.
437 g_object_class_install_property (gobject_class, PROP_SERVICE,
438 g_param_spec_object ("service", "Service", "Secret Service",
439 SECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
442 * SecretCollection:flags:
444 * A set of flags describing which parts of the secret collection have
447 g_object_class_install_property (gobject_class, PROP_FLAGS,
448 g_param_spec_flags ("flags", "Flags", "Collection flags",
449 secret_collection_flags_get_type (), SECRET_COLLECTION_NONE,
450 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
453 * SecretCollection:items:
455 * A list of #SecretItem objects representing the items that are in
456 * this collection. This list will be empty if the collection is locked.
458 g_object_class_install_property (gobject_class, PROP_ITEMS,
459 g_param_spec_boxed ("items", "Items", "Items in collection",
460 _secret_list_get_type (), G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
463 * SecretCollection:label:
465 * The human readable label for the collection.
467 * Setting this property will result in the label of the collection being
468 * set asynchronously. To properly track the changing of the label use the
469 * secret_collection_set_label() function.
471 g_object_class_install_property (gobject_class, PROP_LABEL,
472 g_param_spec_string ("label", "Label", "Item label",
473 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
476 * SecretCollection:locked:
478 * Whether the collection is locked or not.
480 * To lock or unlock a collection use the secret_service_lock() or
481 * secret_service_unlock() functions.
483 g_object_class_install_property (gobject_class, PROP_LOCKED,
484 g_param_spec_boolean ("locked", "Locked", "Item locked",
485 TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
488 * SecretCollection:created:
490 * The date and time (in seconds since the UNIX epoch) that this
491 * collection was created.
493 g_object_class_install_property (gobject_class, PROP_CREATED,
494 g_param_spec_uint64 ("created", "Created", "Item creation date",
495 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
498 * SecretCollection:modified:
500 * The date and time (in seconds since the UNIX epoch) that this
501 * collection was last modified.
503 g_object_class_install_property (gobject_class, PROP_MODIFIED,
504 g_param_spec_uint64 ("modified", "Modified", "Item modified date",
505 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
507 g_type_class_add_private (gobject_class, sizeof (SecretCollectionPrivate));
511 collection_ensure_for_flags_sync (SecretCollection *self,
512 SecretCollectionFlags flags,
513 GCancellable *cancellable,
516 SecretCollectionFlags want_flags;
518 want_flags = flags & ~secret_collection_get_flags (self);
520 if (want_flags & SECRET_COLLECTION_LOAD_ITEMS) {
521 if (!secret_collection_load_items_sync (self, cancellable, error))
529 secret_collection_initable_init (GInitable *initable,
530 GCancellable *cancellable,
533 SecretCollection *self;
534 SecretService *service;
537 if (!secret_collection_initable_parent_iface->init (initable, cancellable, error))
540 proxy = G_DBUS_PROXY (initable);
542 if (!_secret_util_have_cached_properties (proxy)) {
543 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
544 "No such secret collection at path: %s",
545 g_dbus_proxy_get_object_path (proxy));
549 self = SECRET_COLLECTION (initable);
551 if (self->pv->service == NULL) {
552 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
556 collection_take_service (self, service);
559 if (!collection_ensure_for_flags_sync (self, self->pv->init_flags, cancellable, error))
562 self->pv->constructing = FALSE;
567 secret_collection_initable_iface (GInitableIface *iface)
569 secret_collection_initable_parent_iface = g_type_interface_peek_parent (iface);
571 iface->init = secret_collection_initable_init;
575 GCancellable *cancellable;
579 init_closure_free (gpointer data)
581 InitClosure *closure = data;
582 g_clear_object (&closure->cancellable);
583 g_slice_free (InitClosure, closure);
587 on_ensure_items (GObject *source,
588 GAsyncResult *result,
591 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
592 SecretCollection *self = SECRET_COLLECTION (source);
593 GError *error = NULL;
595 if (!secret_collection_load_items_finish (self, result, &error))
596 g_simple_async_result_take_error (res, error);
598 g_simple_async_result_complete (res);
599 g_object_unref (res);
603 collection_ensure_for_flags_async (SecretCollection *self,
604 SecretCollectionFlags flags,
605 GCancellable *cancellable,
606 GSimpleAsyncResult *async)
608 SecretCollectionFlags want_flags;
610 want_flags = flags & ~secret_collection_get_flags (self);
612 if (want_flags & SECRET_COLLECTION_LOAD_ITEMS) {
613 secret_collection_load_items (self, cancellable,
614 on_ensure_items, g_object_ref (async));
617 g_simple_async_result_complete (async);
622 on_init_service (GObject *source,
623 GAsyncResult *result,
626 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
627 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
628 InitClosure *init = g_simple_async_result_get_op_res_gpointer (async);
629 SecretService *service;
630 GError *error = NULL;
632 service = secret_service_get_finish (result, &error);
634 collection_take_service (self, service);
635 collection_ensure_for_flags_async (self, self->pv->init_flags,
636 init->cancellable, async);
639 g_simple_async_result_take_error (async, error);
640 g_simple_async_result_complete (async);
643 g_object_unref (self);
644 g_object_unref (async);
648 on_init_base (GObject *source,
649 GAsyncResult *result,
652 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
653 SecretCollection *self = SECRET_COLLECTION (source);
654 InitClosure *init = g_simple_async_result_get_op_res_gpointer (res);
655 GDBusProxy *proxy = G_DBUS_PROXY (self);
656 GError *error = NULL;
658 if (!secret_collection_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
660 g_simple_async_result_take_error (res, error);
661 g_simple_async_result_complete (res);
663 } else if (!_secret_util_have_cached_properties (proxy)) {
664 g_simple_async_result_set_error (res, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
665 "No such secret collection at path: %s",
666 g_dbus_proxy_get_object_path (proxy));
667 g_simple_async_result_complete (res);
669 } else if (self->pv->service == NULL) {
670 secret_service_get (SECRET_SERVICE_NONE, init->cancellable,
671 on_init_service, g_object_ref (res));
674 collection_ensure_for_flags_async (self, self->pv->init_flags,
675 init->cancellable, res);
678 g_object_unref (res);
682 secret_collection_async_initable_init_async (GAsyncInitable *initable,
684 GCancellable *cancellable,
685 GAsyncReadyCallback callback,
688 GSimpleAsyncResult *res;
689 InitClosure *closure;
691 res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data,
692 secret_collection_async_initable_init_async);
693 closure = g_slice_new0 (InitClosure);
694 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
695 g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free);
697 secret_collection_async_initable_parent_iface->init_async (initable, io_priority,
702 g_object_unref (res);
706 secret_collection_async_initable_init_finish (GAsyncInitable *initable,
707 GAsyncResult *result,
710 SecretCollection *self = SECRET_COLLECTION (initable);
712 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable),
713 secret_collection_async_initable_init_async), FALSE);
715 if (_secret_util_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
718 self->pv->constructing = FALSE;
723 secret_collection_async_initable_iface (GAsyncInitableIface *iface)
725 secret_collection_async_initable_parent_iface = g_type_interface_peek_parent (iface);
727 iface->init_async = secret_collection_async_initable_init_async;
728 iface->init_finish = secret_collection_async_initable_init_finish;
732 GCancellable *cancellable;
738 items_closure_free (gpointer data)
740 ItemsClosure *closure = data;
741 g_clear_object (&closure->cancellable);
742 g_hash_table_unref (closure->items);
743 g_slice_free (ItemsClosure, closure);
747 on_load_item (GObject *source,
748 GAsyncResult *result,
751 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
752 ItemsClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
753 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
755 GError *error = NULL;
758 closure->items_loading--;
760 item = secret_item_new_for_dbus_path_finish (result, &error);
763 g_simple_async_result_take_error (res, error);
766 path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
767 g_hash_table_insert (closure->items, g_strdup (path), item);
770 if (closure->items_loading == 0) {
771 collection_update_items (self, closure->items);
772 g_simple_async_result_complete_in_idle (res);
775 g_object_unref (self);
776 g_object_unref (res);
780 * secret_collection_load_items:
781 * @self: the secret collection
782 * @cancellable: optional cancellation object
783 * @callback: called when the operation completes
784 * @user_data: data to be passed to the callback
786 * Ensure that the #SecretCollection proxy has loaded all the items present
787 * in the Secret Service. This affects the result of
788 * secret_collection_get_items().
790 * For collections returned from secret_service_get_collections() the items
791 * will have already been loaded.
793 * This method will return immediately and complete asynchronously.
796 secret_collection_load_items (SecretCollection *self,
797 GCancellable *cancellable,
798 GAsyncReadyCallback callback,
801 ItemsClosure *closure;
803 GSimpleAsyncResult *res;
808 g_return_if_fail (SECRET_IS_COLLECTION (self));
809 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
811 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
812 g_return_if_fail (paths != NULL);
814 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
815 secret_collection_load_items);
816 closure = g_slice_new0 (ItemsClosure);
817 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
818 closure->items = items_table_new ();
819 g_simple_async_result_set_op_res_gpointer (res, closure, items_closure_free);
821 g_variant_iter_init (&iter, paths);
822 while (g_variant_iter_loop (&iter, "&o", &path)) {
823 item = _secret_collection_find_item_instance (self, path);
825 /* No such collection yet create a new one */
827 secret_item_new_for_dbus_path (self->pv->service, path, SECRET_ITEM_NONE,
828 cancellable, on_load_item, g_object_ref (res));
829 closure->items_loading++;
832 g_hash_table_insert (closure->items, g_strdup (path), item);
836 if (closure->items_loading == 0) {
837 collection_update_items (self, closure->items);
838 g_simple_async_result_complete_in_idle (res);
841 g_variant_unref (paths);
842 g_object_unref (res);
846 * secret_collection_load_items_finish:
847 * @self: the secret collection
848 * @result: the asynchronous result passed to the callback
849 * @error: location to place an error on failure
851 * Complete an asynchronous operation to ensure that the #SecretCollection proxy
852 * has loaded all the items present in the Secret Service.
854 * Returns: whether the load was successful or not
857 secret_collection_load_items_finish (SecretCollection *self,
858 GAsyncResult *result,
861 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
862 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
863 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
864 secret_collection_load_items), FALSE);
866 if (_secret_util_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
873 * secret_collection_load_items_sync:
874 * @self: the secret collection
875 * @cancellable: optional cancellation object
876 * @error: location to place an error on failure
878 * Ensure that the #SecretCollection proxy has loaded all the items present
879 * in the Secret Service. This affects the result of
880 * secret_collection_get_items().
882 * For collections returned from secret_service_get_collections() the items
883 * will have already been loaded.
885 * This method may block indefinitely and should not be used in user interface
888 * Returns: whether the load was successful or not
891 secret_collection_load_items_sync (SecretCollection *self,
892 GCancellable *cancellable,
902 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
903 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
904 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
906 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
907 g_return_val_if_fail (paths != NULL, FALSE);
909 items = items_table_new ();
911 g_variant_iter_init (&iter, paths);
912 while (g_variant_iter_next (&iter, "&o", &path)) {
913 item = _secret_collection_find_item_instance (self, path);
915 /* No such collection yet create a new one */
917 item = secret_item_new_for_dbus_path_sync (self->pv->service, path,
926 g_hash_table_insert (items, g_strdup (path), item);
930 collection_update_items (self, items);
932 g_hash_table_unref (items);
933 g_variant_unref (paths);
938 * secret_collection_refresh:
939 * @self: the collection
941 * Refresh the properties on this collection. This fires off a request to
942 * refresh, and the properties will be updated later.
944 * Calling this method is not normally necessary, as the secret service
945 * will notify the client when properties change.
948 secret_collection_refresh (SecretCollection *self)
950 g_return_if_fail (SECRET_IS_COLLECTION (self));
952 _secret_util_get_properties (G_DBUS_PROXY (self),
953 secret_collection_refresh,
954 self->pv->cancellable, NULL, NULL);
958 GCancellable *cancellable;
959 SecretCollection *collection;
960 GHashTable *properties;
962 SecretCollectionCreateFlags flags;
966 create_closure_free (gpointer data)
968 CreateClosure *closure = data;
969 g_clear_object (&closure->cancellable);
970 g_clear_object (&closure->collection);
971 g_hash_table_unref (closure->properties);
972 g_free (closure->alias);
973 g_slice_free (CreateClosure, closure);
977 on_create_collection (GObject *source,
978 GAsyncResult *result,
981 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
982 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
983 GError *error = NULL;
985 closure->collection = secret_collection_new_for_dbus_path_finish (result, &error);
987 g_simple_async_result_take_error (res, error);
989 g_simple_async_result_complete (res);
990 g_object_unref (res);
994 on_create_path (GObject *source,
995 GAsyncResult *result,
998 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
999 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1000 SecretService *service = SECRET_SERVICE (source);
1001 GError *error = NULL;
1004 path = secret_service_create_collection_dbus_path_finish (service, result, &error);
1005 if (error == NULL) {
1006 secret_collection_new_for_dbus_path (service, path, SECRET_COLLECTION_LOAD_ITEMS,
1007 closure->cancellable,
1008 on_create_collection, g_object_ref (res));
1010 g_simple_async_result_take_error (res, error);
1011 g_simple_async_result_complete (res);
1014 g_object_unref (res);
1018 on_create_service (GObject *source,
1019 GAsyncResult *result,
1022 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1023 CreateClosure *create = g_simple_async_result_get_op_res_gpointer (async);
1024 GError *error = NULL;
1025 SecretService *service;
1027 service = secret_service_get_finish (result, &error);
1028 if (error == NULL) {
1029 secret_service_create_collection_dbus_path (service, create->properties,
1030 create->alias, create->flags,
1031 create->cancellable,
1032 on_create_path, g_object_ref (async));
1033 g_object_unref (service);
1036 g_simple_async_result_take_error (async, error);
1037 g_simple_async_result_complete (async);
1040 g_object_unref (async);
1044 _secret_collection_properties_new (const gchar *label)
1046 GHashTable *properties;
1049 properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
1050 (GDestroyNotify)g_variant_unref);
1051 value = g_variant_new_string (label);
1052 g_hash_table_insert (properties,
1053 SECRET_COLLECTION_INTERFACE ".Label",
1054 g_variant_ref_sink (value));
1060 * secret_collection_create:
1061 * @service: (allow-none): a secret service object
1062 * @label: label for the new collection
1063 * @alias: (allow-none): alias to assign to the collection
1064 * @flags: currently unused
1065 * @cancellable: optional cancellation object
1066 * @callback: called when the operation completes
1067 * @user_data: data to pass to the callback
1069 * Create a new collection in the secret service.
1071 * This method returns immediately and completes asynchronously. The secret
1072 * service may prompt the user. secret_service_prompt() will be used to handle
1073 * any prompts that are required.
1075 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1076 * default collection to store items in). This allows other applications to
1077 * easily identify and share a collection. If you specify an @alias, and a
1078 * collection with that alias already exists, then a new collection will not
1079 * be created. The previous one will be returned instead.
1081 * If @service is NULL, then secret_service_get() will be called to get
1082 * the default #SecretService proxy.
1086 secret_collection_create (SecretService *service,
1089 SecretCollectionCreateFlags flags,
1090 GCancellable *cancellable,
1091 GAsyncReadyCallback callback,
1094 GSimpleAsyncResult *res;
1095 CreateClosure *closure;
1097 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
1098 g_return_if_fail (label != NULL);
1099 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1101 res = g_simple_async_result_new (NULL, callback, user_data,
1102 secret_collection_create);
1103 closure = g_slice_new0 (CreateClosure);
1104 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1105 closure->properties = _secret_collection_properties_new (label);
1106 closure->alias = g_strdup (alias);
1107 closure->flags = flags;
1108 g_simple_async_result_set_op_res_gpointer (res, closure, create_closure_free);
1110 if (service == NULL) {
1111 secret_service_get (SECRET_SERVICE_NONE, cancellable,
1112 on_create_service, g_object_ref (res));
1115 secret_service_create_collection_dbus_path (service, closure->properties,
1116 closure->alias, closure->flags,
1117 closure->cancellable,
1118 on_create_path, g_object_ref (res));
1121 g_object_unref (res);
1125 * secret_collection_create_finish:
1126 * @result: the asynchronous result passed to the callback
1127 * @error: location to place an error on failure
1129 * Finish operation to create a new collection in the secret service.
1131 * Returns: (transfer full): the new collection, which should be unreferenced
1132 * with g_object_unref()
1135 secret_collection_create_finish (GAsyncResult *result,
1138 GSimpleAsyncResult *res;
1139 CreateClosure *closure;
1141 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
1142 secret_collection_create), NULL);
1143 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1145 res = G_SIMPLE_ASYNC_RESULT (result);
1147 if (_secret_util_propagate_error (res, error))
1150 closure = g_simple_async_result_get_op_res_gpointer (res);
1151 if (closure->collection == NULL)
1154 return g_object_ref (closure->collection);
1158 * secret_collection_create_sync:
1159 * @service: (allow-none): a secret service object
1160 * @label: label for the new collection
1161 * @alias: (allow-none): alias to assign to the collection
1162 * @flags: currently unused
1163 * @cancellable: optional cancellation object
1164 * @error: location to place an error on failure
1166 * Create a new collection in the secret service.
1168 * This method may block indefinitely and should not be used in user interface
1169 * threads. The secret service may prompt the user. secret_service_prompt()
1170 * will be used to handle any prompts that are required.
1172 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1173 * default collection to store items in). This allows other applications to
1174 * easily identify and share a collection. If you specify an @alias, and a
1175 * collection with that alias already exists, then a new collection will not
1176 * be created. The previous one will be returned instead.
1178 * If @service is NULL, then secret_service_get_sync() will be called to get
1179 * the default #SecretService proxy.
1181 * Returns: (transfer full): the new collection, which should be unreferenced
1182 * with g_object_unref()
1185 secret_collection_create_sync (SecretService *service,
1188 SecretCollectionCreateFlags flags,
1189 GCancellable *cancellable,
1192 SecretCollection *collection;
1193 GHashTable *properties;
1196 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
1197 g_return_val_if_fail (label != NULL, NULL);
1198 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1199 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1201 if (service == NULL) {
1202 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
1203 if (service == NULL)
1206 g_object_ref (service);
1209 properties = _secret_collection_properties_new (label);
1211 path = secret_service_create_collection_dbus_path_sync (service, properties, alias,
1212 flags, cancellable, error);
1214 g_hash_table_unref (properties);
1217 g_object_unref (service);
1221 collection = secret_collection_new_for_dbus_path_sync (service, path,
1222 SECRET_COLLECTION_LOAD_ITEMS,
1223 cancellable, error);
1225 g_object_unref (service);
1232 SecretCollection *collection;
1233 GCancellable *cancellable;
1237 SecretSearchFlags flags;
1241 search_closure_free (gpointer data)
1243 SearchClosure *closure = data;
1244 g_object_unref (closure->collection);
1245 g_clear_object (&closure->cancellable);
1246 g_hash_table_unref (closure->items);
1247 g_strfreev (closure->paths);
1248 g_slice_free (SearchClosure, closure);
1252 search_closure_take_item (SearchClosure *closure,
1255 const gchar *path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
1256 g_hash_table_insert (closure->items, (gpointer)path, item);
1260 on_search_secrets (GObject *source,
1261 GAsyncResult *result,
1264 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1266 /* Note that we ignore any unlock failure */
1267 secret_item_load_secrets_finish (result, NULL);
1269 g_simple_async_result_complete (async);
1270 g_object_unref (async);
1274 on_search_unlocked (GObject *source,
1275 GAsyncResult *result,
1278 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1279 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1282 /* Note that we ignore any unlock failure */
1283 secret_service_unlock_finish (SECRET_SERVICE (source), result, NULL, NULL);
1285 /* If loading secrets ... locked items automatically ignored */
1286 if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1287 items = g_hash_table_get_values (search->items);
1288 secret_item_load_secrets (items, search->cancellable,
1289 on_search_secrets, g_object_ref (async));
1290 g_list_free (items);
1292 /* No additional options, just complete */
1294 g_simple_async_result_complete (async);
1297 g_object_unref (async);
1301 secret_search_unlock_load_or_complete (GSimpleAsyncResult *async,
1302 SearchClosure *search)
1306 /* If unlocking then unlock all the locked items */
1307 if (search->flags & SECRET_SEARCH_UNLOCK) {
1308 items = g_hash_table_get_values (search->items);
1309 secret_service_unlock (secret_collection_get_service (search->collection),
1310 items, search->cancellable,
1311 on_search_unlocked, g_object_ref (async));
1312 g_list_free (items);
1314 /* If loading secrets ... locked items automatically ignored */
1315 } else if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1316 items = g_hash_table_get_values (search->items);
1317 secret_item_load_secrets (items, search->cancellable,
1318 on_search_secrets, g_object_ref (async));
1319 g_list_free (items);
1321 /* No additional options, just complete */
1323 g_simple_async_result_complete (async);
1328 on_search_loaded (GObject *source,
1329 GAsyncResult *result,
1332 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1333 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1334 GError *error = NULL;
1339 item = secret_item_new_for_dbus_path_finish (result, &error);
1341 g_simple_async_result_take_error (async, error);
1344 search_closure_take_item (search, item);
1346 /* We're done loading, lets go to the next step */
1347 if (search->loading == 0)
1348 secret_search_unlock_load_or_complete (async, search);
1350 g_object_unref (async);
1354 on_search_paths (GObject *source,
1355 GAsyncResult *result,
1358 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1359 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1360 SecretCollection *self = search->collection;
1361 SecretService *service = secret_collection_get_service (self);
1362 GError *error = NULL;
1367 search->paths = secret_collection_search_for_dbus_paths_finish (self, result, &error);
1368 if (error == NULL) {
1370 if (search->flags & SECRET_SEARCH_ALL)
1373 for (i = 0; i < want && search->paths[i] != NULL; i++) {
1374 item = _secret_collection_find_item_instance (self, search->paths[i]);
1376 secret_item_new_for_dbus_path (service, search->paths[i], SECRET_ITEM_NONE,
1377 search->cancellable, on_search_loaded,
1378 g_object_ref (async));
1381 search_closure_take_item (search, item);
1386 /* No items loading, complete operation now */
1387 if (search->loading == 0)
1388 secret_search_unlock_load_or_complete (async, search);
1391 g_simple_async_result_take_error (async, error);
1392 g_simple_async_result_complete (async);
1395 g_object_unref (async);
1399 * secret_collection_search:
1400 * @self: a secret collection
1401 * @schema: (allow-none): the schema for the attributes
1402 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1403 * @flags: search option flags
1404 * @cancellable: optional cancellation object
1405 * @callback: called when the operation completes
1406 * @user_data: data to pass to the callback
1408 * Search for items matching the @attributes in the @collection.
1409 * The @attributes should be a table of string keys and string values.
1411 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1412 * search will be returned. Otherwise only the first item will be returned.
1413 * This is almost always the unlocked item that was most recently stored.
1415 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1416 * if necessary. In either case, locked and unlocked items will match the
1417 * search and be returned. If the unlock fails, the search does not fail.
1419 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1420 * their secret values loaded and available via secret_item_get_secret().
1422 * This function returns immediately and completes asynchronously.
1425 secret_collection_search (SecretCollection *self,
1426 const SecretSchema *schema,
1427 GHashTable *attributes,
1428 SecretSearchFlags flags,
1429 GCancellable *cancellable,
1430 GAsyncReadyCallback callback,
1433 GSimpleAsyncResult *async;
1434 SearchClosure *search;
1436 g_return_if_fail (SECRET_IS_COLLECTION (self));
1437 g_return_if_fail (attributes != NULL);
1438 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1440 /* Warnings raised already */
1441 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1444 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1445 secret_collection_search);
1446 search = g_slice_new0 (SearchClosure);
1447 search->collection = g_object_ref (self);
1448 search->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1449 search->items = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
1450 search->flags = flags;
1451 g_simple_async_result_set_op_res_gpointer (async, search, search_closure_free);
1453 secret_collection_search_for_dbus_paths (self, schema, attributes,
1454 cancellable, on_search_paths,
1455 g_object_ref (async));
1457 g_object_unref (async);
1461 * secret_collection_search_finish:
1462 * @self: the secret collection
1463 * @result: asynchronous result passed to callback
1464 * @error: location to place error on failure
1466 * Complete asynchronous operation to search for items in a collection.
1468 * Returns: (transfer full) (element-type Secret.Item):
1469 * a list of items that matched the search
1472 secret_collection_search_finish (SecretCollection *self,
1473 GAsyncResult *result,
1476 GSimpleAsyncResult *async;
1477 SearchClosure *search;
1478 GList *items = NULL;
1482 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1483 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1484 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1485 secret_collection_search), NULL);
1487 async = G_SIMPLE_ASYNC_RESULT (result);
1488 if (_secret_util_propagate_error (async, error))
1491 search = g_simple_async_result_get_op_res_gpointer (async);
1493 for (i = 0; search->paths[i]; i++) {
1494 item = g_hash_table_lookup (search->items, search->paths[i]);
1496 items = g_list_prepend (items, g_object_ref (item));
1499 return g_list_reverse (items);
1503 collection_load_items_sync (SecretCollection *self,
1504 GCancellable *cancellable,
1510 SecretService *service = secret_collection_get_service (self);
1515 for (i = 0; have < want && paths[i] != NULL; i++) {
1516 item = _secret_collection_find_item_instance (self, paths[i]);
1518 item = secret_item_new_for_dbus_path_sync (service, paths[i], SECRET_ITEM_NONE,
1519 cancellable, error);
1524 *items = g_list_prepend (*items, item);
1533 * secret_collection_search_sync:
1534 * @self: a secret collection
1535 * @schema: (allow-none): the schema for the attributes
1536 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1537 * @flags: search option flags
1538 * @cancellable: optional cancellation object
1539 * @error: location to place error on failure
1541 * Search for items matching the @attributes in the @collection.
1542 * The @attributes should be a table of string keys and string values.
1544 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1545 * search will be returned. Otherwise only the first item will be returned.
1546 * This is almost always the unlocked item that was most recently stored.
1548 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1549 * if necessary. In either case, locked and unlocked items will match the
1550 * search and be returned. If the unlock fails, the search does not fail.
1552 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1553 * their secret values loaded and available via secret_item_get_secret().
1555 * This function may block indefinetely. Use the asynchronous version
1556 * in user interface threads.
1558 * Returns: (transfer full) (element-type Secret.Item):
1559 * a list of items that matched the search
1562 secret_collection_search_sync (SecretCollection *self,
1563 const SecretSchema *schema,
1564 GHashTable *attributes,
1565 SecretSearchFlags flags,
1566 GCancellable *cancellable,
1569 gchar **paths = NULL;
1570 GList *items = NULL;
1574 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1575 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1576 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1578 /* Warnings raised already */
1579 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1582 paths = secret_collection_search_for_dbus_paths_sync (self, schema, attributes,
1583 cancellable, error);
1590 if (flags & SECRET_SEARCH_ALL)
1593 ret = collection_load_items_sync (self, cancellable, paths,
1594 &items, want, error);
1601 if (flags & SECRET_SEARCH_UNLOCK) {
1602 secret_service_unlock_sync (secret_collection_get_service (self),
1603 items, cancellable, NULL, NULL);
1606 if (flags & SECRET_SEARCH_LOAD_SECRETS)
1607 secret_item_load_secrets_sync (items, NULL, NULL);
1613 on_service_delete_path (GObject *source,
1614 GAsyncResult *result,
1617 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1618 GError *error = NULL;
1620 _secret_service_delete_path_finish (SECRET_SERVICE (source), result, &error);
1622 g_simple_async_result_take_error (async, error);
1623 g_simple_async_result_complete (async);
1624 g_object_unref (async);
1627 * secret_collection_delete:
1628 * @self: a collection
1629 * @cancellable: optional cancellation object
1630 * @callback: called when the operation completes
1631 * @user_data: data to pass to the callback
1633 * Delete this collection.
1635 * This method returns immediately and completes asynchronously. The secret
1636 * service may prompt the user. secret_service_prompt() will be used to handle
1637 * any prompts that show up.
1640 secret_collection_delete (SecretCollection *self,
1641 GCancellable *cancellable,
1642 GAsyncReadyCallback callback,
1645 GSimpleAsyncResult *async;
1646 const gchar *object_path;
1648 g_return_if_fail (SECRET_IS_COLLECTION (self));
1649 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1651 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1652 secret_collection_delete);
1654 object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
1655 _secret_service_delete_path (self->pv->service, object_path, FALSE,
1656 cancellable, on_service_delete_path,
1657 g_object_ref (async));
1659 g_object_unref (async);
1663 * secret_collection_delete_finish:
1664 * @self: a collection
1665 * @result: asynchronous result passed to the callback
1666 * @error: location to place an error on failure
1668 * Complete operation to delete this collection.
1670 * Returns: whether the collection was successfully deleted or not
1673 secret_collection_delete_finish (SecretCollection *self,
1674 GAsyncResult *result,
1677 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1678 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1679 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1680 secret_collection_delete), FALSE);
1682 if (_secret_util_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
1689 * secret_collection_delete_sync:
1690 * @self: a collection
1691 * @cancellable: optional cancellation object
1692 * @error: location to place an error on failure
1694 * Delete this collection.
1696 * This method may block indefinitely and should not be used in user
1697 * interface threads. The secret service may prompt the user.
1698 * secret_service_prompt() will be used to handle any prompts that show up.
1700 * Returns: whether the collection was successfully deleted or not
1703 secret_collection_delete_sync (SecretCollection *self,
1704 GCancellable *cancellable,
1710 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1711 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1712 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1714 sync = _secret_sync_new ();
1715 g_main_context_push_thread_default (sync->context);
1717 secret_collection_delete (self, cancellable, _secret_sync_on_result, sync);
1719 g_main_loop_run (sync->loop);
1721 ret = secret_collection_delete_finish (self, sync->result, error);
1723 g_main_context_pop_thread_default (sync->context);
1724 _secret_sync_free (sync);
1730 * secret_collection_get_service:
1731 * @self: a collection
1733 * Get the Secret Service object that this collection was created with.
1735 * Returns: (transfer none): the Secret Service object
1738 secret_collection_get_service (SecretCollection *self)
1740 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1741 return self->pv->service;
1745 * secret_collection_get_flags:
1746 * @self: the secret collection proxy
1748 * Get the flags representing what features of the #SecretCollection proxy
1749 * have been initialized.
1751 * Use secret_collection_load_items() to initialize further features
1752 * and change the flags.
1754 * Returns: the flags for features initialized
1756 SecretCollectionFlags
1757 secret_collection_get_flags (SecretCollection *self)
1759 SecretCollectionFlags flags = 0;
1761 g_return_val_if_fail (SECRET_IS_COLLECTION (self), SECRET_COLLECTION_NONE);
1763 g_mutex_lock (&self->pv->mutex);
1765 if (self->pv->items)
1766 flags |= SECRET_COLLECTION_LOAD_ITEMS;
1768 g_mutex_unlock (&self->pv->mutex);
1774 * secret_collection_get_items:
1775 * @self: a collection
1777 * Get the list of items in this collection.
1779 * Returns: (transfer full) (element-type Secret.Item): a list of items,
1780 * when done, the list should be freed with g_list_free, and each item should
1781 * be released with g_object_unref()
1784 secret_collection_get_items (SecretCollection *self)
1786 GList *l, *items = NULL;
1788 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1790 g_mutex_lock (&self->pv->mutex);
1791 if (self->pv->items)
1792 items = g_hash_table_get_values (self->pv->items);
1793 for (l = items; l != NULL; l = g_list_next (l))
1794 g_object_ref (l->data);
1795 g_mutex_unlock (&self->pv->mutex);
1801 _secret_collection_find_item_instance (SecretCollection *self,
1802 const gchar *item_path)
1804 SecretItem *item = NULL;
1806 g_mutex_lock (&self->pv->mutex);
1807 if (self->pv->items)
1808 item = g_hash_table_lookup (self->pv->items, item_path);
1810 g_object_ref (item);
1811 g_mutex_unlock (&self->pv->mutex);
1817 * secret_collection_get_label:
1818 * @self: a collection
1820 * Get the label of this collection.
1822 * Returns: (transfer full): the label, which should be freed with g_free()
1825 secret_collection_get_label (SecretCollection *self)
1830 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1832 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Label");
1833 g_return_val_if_fail (variant != NULL, NULL);
1835 label = g_variant_dup_string (variant, NULL);
1836 g_variant_unref (variant);
1842 * secret_collection_set_label:
1843 * @self: a collection
1844 * @label: a new label
1845 * @cancellable: optional cancellation object
1846 * @callback: called when the operation completes
1847 * @user_data: data to pass to the callback
1849 * Set the label of this collection.
1851 * This function returns immediately and completes asynchronously.
1854 secret_collection_set_label (SecretCollection *self,
1856 GCancellable *cancellable,
1857 GAsyncReadyCallback callback,
1860 g_return_if_fail (SECRET_IS_COLLECTION (self));
1861 g_return_if_fail (label != NULL);
1863 _secret_util_set_property (G_DBUS_PROXY (self), "Label",
1864 g_variant_new_string (label),
1865 secret_collection_set_label,
1866 cancellable, callback, user_data);
1870 * secret_collection_set_label_finish:
1871 * @self: a collection
1872 * @result: asynchronous result passed to callback
1873 * @error: location to place error on failure
1875 * Complete asynchronous operation to set the label of this collection.
1877 * Returns: whether the change was successful or not
1880 secret_collection_set_label_finish (SecretCollection *self,
1881 GAsyncResult *result,
1884 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1886 return _secret_util_set_property_finish (G_DBUS_PROXY (self),
1887 secret_collection_set_label,
1892 * secret_collection_set_label_sync:
1893 * @self: a collection
1894 * @label: a new label
1895 * @cancellable: optional cancellation object
1896 * @error: location to place error on failure
1898 * Set the label of this collection.
1900 * This function may block indefinetely. Use the asynchronous version
1901 * in user interface threads.
1903 * Returns: whether the change was successful or not
1906 secret_collection_set_label_sync (SecretCollection *self,
1908 GCancellable *cancellable,
1911 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1912 g_return_val_if_fail (label != NULL, FALSE);
1914 return _secret_util_set_property_sync (G_DBUS_PROXY (self), "Label",
1915 g_variant_new_string (label),
1916 cancellable, error);
1920 * secret_collection_get_locked:
1921 * @self: a collection
1923 * Get whether the collection is locked or not.
1925 * Use secret_service_lock() or secret_service_unlock() to lock or unlock the
1928 * Returns: whether the collection is locked or not
1931 secret_collection_get_locked (SecretCollection *self)
1936 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1938 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Locked");
1939 g_return_val_if_fail (variant != NULL, TRUE);
1941 locked = g_variant_get_boolean (variant);
1942 g_variant_unref (variant);
1948 * secret_collection_get_created:
1949 * @self: a collection
1951 * Get the created date and time of the collection. The return value is
1952 * the number of seconds since the unix epoch, January 1st 1970.
1954 * Returns: the created date and time
1957 secret_collection_get_created (SecretCollection *self)
1962 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1964 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Created");
1965 g_return_val_if_fail (variant != NULL, 0);
1967 created = g_variant_get_uint64 (variant);
1968 g_variant_unref (variant);
1974 * secret_collection_get_modified:
1975 * @self: a collection
1977 * Get the modified date and time of the collection. The return value is
1978 * the number of seconds since the unix epoch, January 1st 1970.
1980 * Returns: the modified date and time
1983 secret_collection_get_modified (SecretCollection *self)
1988 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1990 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Modified");
1991 g_return_val_if_fail (variant != NULL, 0);
1993 modified = g_variant_get_uint64 (variant);
1994 g_variant_unref (variant);
2001 GCancellable *cancellable;
2003 SecretCollectionFlags flags;
2004 SecretCollection *collection;
2008 read_closure_free (gpointer data)
2010 ReadClosure *read = data;
2011 g_free (read->alias);
2012 if (read->collection)
2013 g_object_unref (read->collection);
2014 if (read->cancellable)
2015 g_object_unref (read->cancellable);
2016 g_slice_free (ReadClosure, read);
2020 on_read_alias_collection (GObject *source,
2021 GAsyncResult *result,
2024 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2025 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2026 GError *error = NULL;
2028 read->collection = secret_collection_new_for_dbus_path_finish (result, &error);
2030 g_simple_async_result_take_error (async, error);
2032 g_simple_async_result_complete (async);
2033 g_object_unref (async);
2037 on_read_alias_path (GObject *source,
2038 GAsyncResult *result,
2041 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2042 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2043 SecretService *self = SECRET_SERVICE (source);
2044 GError *error = NULL;
2045 gchar *collection_path;
2047 collection_path = secret_service_read_alias_dbus_path_finish (self, result, &error);
2048 if (error == NULL) {
2050 /* No collection for this alias */
2051 if (collection_path == NULL) {
2052 g_simple_async_result_complete (async);
2055 read->collection = _secret_service_find_collection_instance (self,
2057 if (read->collection != NULL) {
2059 /* Make sure collection has necessary flags */
2060 collection_ensure_for_flags_async (read->collection, read->flags,
2061 read->cancellable, async);
2063 /* No collection loaded, but valid path, load */
2065 secret_collection_new_for_dbus_path (self, collection_path,
2068 on_read_alias_collection,
2069 g_object_ref (async));
2074 g_simple_async_result_take_error (async, error);
2075 g_simple_async_result_complete (async);
2078 g_free (collection_path);
2079 g_object_unref (async);
2083 on_read_alias_service (GObject *source,
2084 GAsyncResult *result,
2087 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2088 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2089 SecretService *service;
2090 GError *error = NULL;
2092 service = secret_service_get_finish (result, &error);
2093 if (error == NULL) {
2094 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2095 on_read_alias_path, g_object_ref (async));
2096 g_object_unref (service);
2099 g_simple_async_result_take_error (async, error);
2100 g_simple_async_result_complete (async);
2103 g_object_unref (async);
2107 * secret_collection_for_alias:
2108 * @service: (allow-none): a secret service object
2109 * @alias: the alias to lookup
2110 * @flags: options for the collection initialization
2111 * @cancellable: (allow-none): optional cancellation object
2112 * @callback: called when the operation completes
2113 * @user_data: data to pass to the callback
2115 * Lookup which collection is assigned to this alias. Aliases help determine
2116 * well known collections, such as 'default'.
2118 * If @service is NULL, then secret_service_get() will be called to get
2119 * the default #SecretService proxy.
2121 * This method will return immediately and complete asynchronously.
2124 secret_collection_for_alias (SecretService *service,
2126 SecretCollectionFlags flags,
2127 GCancellable *cancellable,
2128 GAsyncReadyCallback callback,
2131 GSimpleAsyncResult *async;
2134 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
2135 g_return_if_fail (alias != NULL);
2136 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2138 async = g_simple_async_result_new (NULL, callback, user_data,
2139 secret_collection_for_alias);
2140 read = g_slice_new0 (ReadClosure);
2141 read->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
2142 read->alias = g_strdup (alias);
2143 read->flags = flags;
2144 g_simple_async_result_set_op_res_gpointer (async, read, read_closure_free);
2146 if (service == NULL) {
2147 secret_service_get (SECRET_SERVICE_NONE, cancellable,
2148 on_read_alias_service, g_object_ref (async));
2150 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2151 on_read_alias_path, g_object_ref (async));
2154 g_object_unref (async);
2158 * secret_collection_for_alias_finish:
2159 * @result: asynchronous result passed to callback
2160 * @error: location to place error on failure
2162 * Finish an asynchronous operation to lookup which collection is assigned
2165 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2168 secret_collection_for_alias_finish (GAsyncResult *result,
2171 GSimpleAsyncResult *async;
2174 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
2175 secret_collection_for_alias), NULL);
2176 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2178 async = G_SIMPLE_ASYNC_RESULT (result);
2179 if (_secret_util_propagate_error (async, error))
2181 read = g_simple_async_result_get_op_res_gpointer (async);
2182 if (read->collection)
2183 g_object_ref (read->collection);
2184 return read->collection;
2188 * secret_collection_for_alias_sync:
2189 * @service: (allow-none): a secret service object
2190 * @alias: the alias to lookup
2191 * @flags: options for the collection initialization
2192 * @cancellable: (allow-none): optional cancellation object
2193 * @error: location to place error on failure
2195 * Lookup which collection is assigned to this alias. Aliases help determine
2196 * well known collections, such as 'default'.
2198 * If @service is NULL, then secret_service_get_sync() will be called to get
2199 * the default #SecretService proxy.
2201 * This method may block and should not be used in user interface threads.
2203 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2206 secret_collection_for_alias_sync (SecretService *service,
2208 SecretCollectionFlags flags,
2209 GCancellable *cancellable,
2212 SecretCollection *collection;
2213 gchar *collection_path;
2215 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
2216 g_return_val_if_fail (alias != NULL, NULL);
2217 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2218 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2220 collection_path = secret_service_read_alias_dbus_path_sync (service, alias,
2221 cancellable, error);
2222 if (collection_path == NULL)
2225 /* No collection for this alias */
2226 if (collection_path == NULL) {
2230 collection = _secret_service_find_collection_instance (service,
2233 if (collection != NULL) {
2235 /* Have a collection with all necessary flags */
2236 if (!collection_ensure_for_flags_sync (collection, flags,
2237 cancellable, error)) {
2238 g_object_unref (collection);
2242 /* No collection loaded, but valid path, load */
2244 collection = secret_collection_new_for_dbus_path_sync (service, collection_path,
2245 flags, cancellable, error);
2249 g_free (collection_path);