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->constructing = TRUE;
147 on_set_label (GObject *source,
148 GAsyncResult *result,
151 SecretCollection *self = SECRET_COLLECTION (user_data);
152 GError *error = NULL;
154 secret_collection_set_label_finish (self, result, &error);
156 g_warning ("couldn't set SecretCollection Label: %s", error->message);
157 g_error_free (error);
160 g_object_unref (self);
164 collection_take_service (SecretCollection *self,
165 SecretService *service)
170 g_return_if_fail (self->pv->service == NULL);
172 self->pv->service = service;
173 g_object_add_weak_pointer (G_OBJECT (self->pv->service),
174 (gpointer *)&self->pv->service);
176 /* Yes, we expect that the service will stay around */
177 g_object_unref (service);
181 secret_collection_set_property (GObject *obj,
186 SecretCollection *self = SECRET_COLLECTION (obj);
190 collection_take_service (self, g_value_dup_object (value));
193 self->pv->init_flags = g_value_get_flags (value);
196 secret_collection_set_label (self, g_value_get_string (value),
197 self->pv->cancellable, on_set_label,
198 g_object_ref (self));
201 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
207 secret_collection_get_property (GObject *obj,
212 SecretCollection *self = SECRET_COLLECTION (obj);
216 g_value_set_object (value, self->pv->service);
219 g_value_set_flags (value, secret_collection_get_flags (self));
222 g_value_take_boxed (value, secret_collection_get_items (self));
225 g_value_take_string (value, secret_collection_get_label (self));
228 g_value_set_boolean (value, secret_collection_get_locked (self));
231 g_value_set_uint64 (value, secret_collection_get_created (self));
234 g_value_set_uint64 (value, secret_collection_get_modified (self));
237 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
243 secret_collection_dispose (GObject *obj)
245 SecretCollection *self = SECRET_COLLECTION (obj);
247 g_cancellable_cancel (self->pv->cancellable);
249 G_OBJECT_CLASS (secret_collection_parent_class)->dispose (obj);
253 secret_collection_finalize (GObject *obj)
255 SecretCollection *self = SECRET_COLLECTION (obj);
257 if (self->pv->service)
258 g_object_remove_weak_pointer (G_OBJECT (self->pv->service),
259 (gpointer *)&self->pv->service);
261 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_update_items (SecretCollection *self,
273 GHashTable *previous;
275 g_hash_table_ref (items);
277 g_mutex_lock (&self->pv->mutex);
278 previous = self->pv->items;
279 self->pv->items = items;
280 g_mutex_unlock (&self->pv->mutex);
282 if (previous != NULL)
283 g_hash_table_unref (previous);
285 g_object_notify (G_OBJECT (self), "items");
289 handle_property_changed (SecretCollection *self,
290 const gchar *property_name,
295 if (g_str_equal (property_name, "Label")) {
296 g_object_notify (G_OBJECT (self), "label");
298 } else if (g_str_equal (property_name, "Locked")) {
299 g_object_notify (G_OBJECT (self), "locked");
301 } else if (g_str_equal (property_name, "Created")) {
302 g_object_notify (G_OBJECT (self), "created");
304 } else if (g_str_equal (property_name, "Modified")) {
305 g_object_notify (G_OBJECT (self), "modified");
307 } else if (g_str_equal (property_name, "Items") && !self->pv->constructing) {
308 g_mutex_lock (&self->pv->mutex);
309 perform = self->pv->items != NULL;
310 g_mutex_unlock (&self->pv->mutex);
313 secret_collection_load_items (self, self->pv->cancellable, NULL, NULL);
318 secret_collection_properties_changed (GDBusProxy *proxy,
319 GVariant *changed_properties,
320 const gchar* const *invalidated_properties)
322 SecretCollection *self = SECRET_COLLECTION (proxy);
323 gchar *property_name;
327 g_object_freeze_notify (G_OBJECT (self));
329 g_variant_iter_init (&iter, changed_properties);
330 while (g_variant_iter_loop (&iter, "{sv}", &property_name, &value))
331 handle_property_changed (self, property_name, value);
333 g_object_thaw_notify (G_OBJECT (self));
337 secret_collection_signal (GDBusProxy *proxy,
338 const gchar *sender_name,
339 const gchar *signal_name,
340 GVariant *parameters)
342 SecretCollection *self = SECRET_COLLECTION (proxy);
344 const gchar *item_path;
345 GVariantBuilder builder;
346 gboolean found = FALSE;
353 * Remember that these signals come from a time before PropertiesChanged.
354 * We support them because they're in the spec, and ksecretservice uses them.
357 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
359 /* A new collection was added, add it to the Collections property */
360 if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CREATED)) {
361 g_variant_get (parameters, "(@o)", &value);
362 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
363 g_variant_iter_init (&iter, paths);
364 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
365 if (g_variant_equal (path, value)) {
369 g_variant_builder_add_value (&builder, path);
370 g_variant_unref (path);
373 g_variant_builder_add_value (&builder, value);
374 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
376 g_variant_builder_clear (&builder);
377 g_variant_unref (value);
379 /* A collection was deleted, remove it from the Collections property */
380 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_DELETED)) {
381 g_variant_get (parameters, "(@o)", &value);
382 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
383 g_variant_iter_init (&iter, paths);
384 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
385 if (g_variant_equal (path, value))
388 g_variant_builder_add_value (&builder, path);
389 g_variant_unref (path);
392 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
393 g_variant_unref (value);
395 /* The collection changed, update it */
396 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CHANGED)) {
397 g_variant_get (parameters, "(&o)", &item_path);
399 g_mutex_lock (&self->pv->mutex);
402 item = g_hash_table_lookup (self->pv->items, item_path);
408 g_mutex_unlock (&self->pv->mutex);
411 secret_item_refresh (item);
412 g_object_unref (item);
416 g_variant_unref (paths);
420 secret_collection_class_init (SecretCollectionClass *klass)
422 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
423 GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass);
425 gobject_class->get_property = secret_collection_get_property;
426 gobject_class->set_property = secret_collection_set_property;
427 gobject_class->dispose = secret_collection_dispose;
428 gobject_class->finalize = secret_collection_finalize;
430 proxy_class->g_properties_changed = secret_collection_properties_changed;
431 proxy_class->g_signal = secret_collection_signal;
434 * SecretCollection:service:
436 * The #SecretService object that this collection is associated with and
437 * uses to interact with the actual D-Bus Secret Service.
439 g_object_class_install_property (gobject_class, PROP_SERVICE,
440 g_param_spec_object ("service", "Service", "Secret Service",
441 SECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
444 * SecretCollection:flags:
446 * A set of flags describing which parts of the secret collection have
449 g_object_class_install_property (gobject_class, PROP_FLAGS,
450 g_param_spec_flags ("flags", "Flags", "Collection flags",
451 secret_collection_flags_get_type (), SECRET_COLLECTION_NONE,
452 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
455 * SecretCollection:items:
457 * A list of #SecretItem objects representing the items that are in
458 * this collection. This list will be empty if the collection is locked.
460 g_object_class_install_property (gobject_class, PROP_ITEMS,
461 g_param_spec_boxed ("items", "Items", "Items in collection",
462 _secret_list_get_type (), G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
465 * SecretCollection:label:
467 * The human readable label for the collection.
469 * Setting this property will result in the label of the collection being
470 * set asynchronously. To properly track the changing of the label use the
471 * secret_collection_set_label() function.
473 g_object_class_install_property (gobject_class, PROP_LABEL,
474 g_param_spec_string ("label", "Label", "Item label",
475 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
478 * SecretCollection:locked:
480 * Whether the collection is locked or not.
482 * To lock or unlock a collection use the secret_service_lock() or
483 * secret_service_unlock() functions.
485 g_object_class_install_property (gobject_class, PROP_LOCKED,
486 g_param_spec_boolean ("locked", "Locked", "Item locked",
487 TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
490 * SecretCollection:created:
492 * The date and time (in seconds since the UNIX epoch) that this
493 * collection was created.
495 g_object_class_install_property (gobject_class, PROP_CREATED,
496 g_param_spec_uint64 ("created", "Created", "Item creation date",
497 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
500 * SecretCollection:modified:
502 * The date and time (in seconds since the UNIX epoch) that this
503 * collection was last modified.
505 g_object_class_install_property (gobject_class, PROP_MODIFIED,
506 g_param_spec_uint64 ("modified", "Modified", "Item modified date",
507 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
509 g_type_class_add_private (gobject_class, sizeof (SecretCollectionPrivate));
513 collection_ensure_for_flags_sync (SecretCollection *self,
514 SecretCollectionFlags flags,
515 GCancellable *cancellable,
518 SecretCollectionFlags want_flags;
520 want_flags = flags & ~secret_collection_get_flags (self);
522 if (want_flags & SECRET_COLLECTION_LOAD_ITEMS) {
523 if (!secret_collection_load_items_sync (self, cancellable, error))
531 secret_collection_initable_init (GInitable *initable,
532 GCancellable *cancellable,
535 SecretCollection *self;
536 SecretService *service;
539 if (!secret_collection_initable_parent_iface->init (initable, cancellable, error))
542 proxy = G_DBUS_PROXY (initable);
544 if (!_secret_util_have_cached_properties (proxy)) {
545 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
546 "No such secret collection at path: %s",
547 g_dbus_proxy_get_object_path (proxy));
551 self = SECRET_COLLECTION (initable);
553 if (self->pv->service == NULL) {
554 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
558 collection_take_service (self, service);
561 if (!collection_ensure_for_flags_sync (self, self->pv->init_flags, cancellable, error))
564 self->pv->constructing = FALSE;
569 secret_collection_initable_iface (GInitableIface *iface)
571 secret_collection_initable_parent_iface = g_type_interface_peek_parent (iface);
573 iface->init = secret_collection_initable_init;
577 GCancellable *cancellable;
581 init_closure_free (gpointer data)
583 InitClosure *closure = data;
584 g_clear_object (&closure->cancellable);
585 g_slice_free (InitClosure, closure);
589 on_ensure_items (GObject *source,
590 GAsyncResult *result,
593 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
594 SecretCollection *self = SECRET_COLLECTION (source);
595 GError *error = NULL;
597 if (!secret_collection_load_items_finish (self, result, &error))
598 g_simple_async_result_take_error (res, error);
600 g_simple_async_result_complete (res);
601 g_object_unref (res);
605 collection_ensure_for_flags_async (SecretCollection *self,
606 SecretCollectionFlags flags,
607 GCancellable *cancellable,
608 GSimpleAsyncResult *async)
610 SecretCollectionFlags want_flags;
612 want_flags = flags & ~secret_collection_get_flags (self);
614 if (want_flags & SECRET_COLLECTION_LOAD_ITEMS) {
615 secret_collection_load_items (self, cancellable,
616 on_ensure_items, g_object_ref (async));
619 g_simple_async_result_complete (async);
624 on_init_service (GObject *source,
625 GAsyncResult *result,
628 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
629 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
630 InitClosure *init = g_simple_async_result_get_op_res_gpointer (async);
631 SecretService *service;
632 GError *error = NULL;
634 service = secret_service_get_finish (result, &error);
636 collection_take_service (self, service);
637 collection_ensure_for_flags_async (self, self->pv->init_flags,
638 init->cancellable, async);
641 g_simple_async_result_take_error (async, error);
642 g_simple_async_result_complete (async);
645 g_object_unref (self);
646 g_object_unref (async);
650 on_init_base (GObject *source,
651 GAsyncResult *result,
654 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
655 SecretCollection *self = SECRET_COLLECTION (source);
656 InitClosure *init = g_simple_async_result_get_op_res_gpointer (res);
657 GDBusProxy *proxy = G_DBUS_PROXY (self);
658 GError *error = NULL;
660 if (!secret_collection_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
662 g_simple_async_result_take_error (res, error);
663 g_simple_async_result_complete (res);
665 } else if (!_secret_util_have_cached_properties (proxy)) {
666 g_simple_async_result_set_error (res, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
667 "No such secret collection at path: %s",
668 g_dbus_proxy_get_object_path (proxy));
669 g_simple_async_result_complete (res);
671 } else if (self->pv->service == NULL) {
672 secret_service_get (SECRET_SERVICE_NONE, init->cancellable,
673 on_init_service, g_object_ref (res));
676 collection_ensure_for_flags_async (self, self->pv->init_flags,
677 init->cancellable, res);
680 g_object_unref (res);
684 secret_collection_async_initable_init_async (GAsyncInitable *initable,
686 GCancellable *cancellable,
687 GAsyncReadyCallback callback,
690 GSimpleAsyncResult *res;
691 InitClosure *closure;
693 res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data,
694 secret_collection_async_initable_init_async);
695 closure = g_slice_new0 (InitClosure);
696 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
697 g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free);
699 secret_collection_async_initable_parent_iface->init_async (initable, io_priority,
704 g_object_unref (res);
708 secret_collection_async_initable_init_finish (GAsyncInitable *initable,
709 GAsyncResult *result,
712 SecretCollection *self = SECRET_COLLECTION (initable);
714 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable),
715 secret_collection_async_initable_init_async), FALSE);
717 if (_secret_util_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
720 self->pv->constructing = FALSE;
725 secret_collection_async_initable_iface (GAsyncInitableIface *iface)
727 secret_collection_async_initable_parent_iface = g_type_interface_peek_parent (iface);
729 iface->init_async = secret_collection_async_initable_init_async;
730 iface->init_finish = secret_collection_async_initable_init_finish;
734 GCancellable *cancellable;
740 items_closure_free (gpointer data)
742 ItemsClosure *closure = data;
743 g_clear_object (&closure->cancellable);
744 g_hash_table_unref (closure->items);
745 g_slice_free (ItemsClosure, closure);
749 on_load_item (GObject *source,
750 GAsyncResult *result,
753 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
754 ItemsClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
755 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
757 GError *error = NULL;
760 closure->items_loading--;
762 item = secret_item_new_for_dbus_path_finish (result, &error);
765 g_simple_async_result_take_error (res, error);
768 path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
769 g_hash_table_insert (closure->items, g_strdup (path), item);
772 if (closure->items_loading == 0) {
773 collection_update_items (self, closure->items);
774 g_simple_async_result_complete_in_idle (res);
777 g_object_unref (self);
778 g_object_unref (res);
782 * secret_collection_load_items:
783 * @self: the secret collection
784 * @cancellable: optional cancellation object
785 * @callback: called when the operation completes
786 * @user_data: data to be passed to the callback
788 * Ensure that the #SecretCollection proxy has loaded all the items present
789 * in the Secret Service. This affects the result of
790 * secret_collection_get_items().
792 * For collections returned from secret_service_get_collections() the items
793 * will have already been loaded.
795 * This method will return immediately and complete asynchronously.
798 secret_collection_load_items (SecretCollection *self,
799 GCancellable *cancellable,
800 GAsyncReadyCallback callback,
803 ItemsClosure *closure;
805 GSimpleAsyncResult *res;
810 g_return_if_fail (SECRET_IS_COLLECTION (self));
811 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
813 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
814 g_return_if_fail (paths != NULL);
816 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
817 secret_collection_load_items);
818 closure = g_slice_new0 (ItemsClosure);
819 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
820 closure->items = items_table_new ();
821 g_simple_async_result_set_op_res_gpointer (res, closure, items_closure_free);
823 g_variant_iter_init (&iter, paths);
824 while (g_variant_iter_loop (&iter, "&o", &path)) {
825 item = _secret_collection_find_item_instance (self, path);
827 /* No such collection yet create a new one */
829 secret_item_new_for_dbus_path (self->pv->service, path, SECRET_ITEM_NONE,
830 cancellable, on_load_item, g_object_ref (res));
831 closure->items_loading++;
834 g_hash_table_insert (closure->items, g_strdup (path), item);
838 if (closure->items_loading == 0) {
839 collection_update_items (self, closure->items);
840 g_simple_async_result_complete_in_idle (res);
843 g_variant_unref (paths);
844 g_object_unref (res);
848 * secret_collection_load_items_finish:
849 * @self: the secret collection
850 * @result: the asynchronous result passed to the callback
851 * @error: location to place an error on failure
853 * Complete an asynchronous operation to ensure that the #SecretCollection proxy
854 * has loaded all the items present in the Secret Service.
856 * Returns: whether the load was successful or not
859 secret_collection_load_items_finish (SecretCollection *self,
860 GAsyncResult *result,
863 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
864 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
865 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
866 secret_collection_load_items), FALSE);
868 if (_secret_util_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
875 * secret_collection_load_items_sync:
876 * @self: the secret collection
877 * @cancellable: optional cancellation object
878 * @error: location to place an error on failure
880 * Ensure that the #SecretCollection proxy has loaded all the items present
881 * in the Secret Service. This affects the result of
882 * secret_collection_get_items().
884 * For collections returned from secret_service_get_collections() the items
885 * will have already been loaded.
887 * This method may block indefinitely and should not be used in user interface
890 * Returns: whether the load was successful or not
893 secret_collection_load_items_sync (SecretCollection *self,
894 GCancellable *cancellable,
904 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
905 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
906 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
908 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
909 g_return_val_if_fail (paths != NULL, FALSE);
911 items = items_table_new ();
913 g_variant_iter_init (&iter, paths);
914 while (g_variant_iter_next (&iter, "&o", &path)) {
915 item = _secret_collection_find_item_instance (self, path);
917 /* No such collection yet create a new one */
919 item = secret_item_new_for_dbus_path_sync (self->pv->service, path,
928 g_hash_table_insert (items, g_strdup (path), item);
932 collection_update_items (self, items);
934 g_hash_table_unref (items);
935 g_variant_unref (paths);
940 * secret_collection_refresh:
941 * @self: the collection
943 * Refresh the properties on this collection. This fires off a request to
944 * refresh, and the properties will be updated later.
946 * Calling this method is not normally necessary, as the secret service
947 * will notify the client when properties change.
950 secret_collection_refresh (SecretCollection *self)
952 g_return_if_fail (SECRET_IS_COLLECTION (self));
954 _secret_util_get_properties (G_DBUS_PROXY (self),
955 secret_collection_refresh,
956 self->pv->cancellable, NULL, NULL);
960 GCancellable *cancellable;
961 SecretCollection *collection;
962 GHashTable *properties;
964 SecretCollectionCreateFlags flags;
968 create_closure_free (gpointer data)
970 CreateClosure *closure = data;
971 g_clear_object (&closure->cancellable);
972 g_clear_object (&closure->collection);
973 g_hash_table_unref (closure->properties);
974 g_free (closure->alias);
975 g_slice_free (CreateClosure, closure);
979 on_create_collection (GObject *source,
980 GAsyncResult *result,
983 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
984 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
985 GError *error = NULL;
987 closure->collection = secret_collection_new_for_dbus_path_finish (result, &error);
989 g_simple_async_result_take_error (res, error);
991 g_simple_async_result_complete (res);
992 g_object_unref (res);
996 on_create_path (GObject *source,
997 GAsyncResult *result,
1000 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
1001 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
1002 SecretService *service = SECRET_SERVICE (source);
1003 GError *error = NULL;
1006 path = secret_service_create_collection_dbus_path_finish (service, result, &error);
1007 if (error == NULL) {
1008 secret_collection_new_for_dbus_path (service, path, SECRET_COLLECTION_LOAD_ITEMS,
1009 closure->cancellable,
1010 on_create_collection, g_object_ref (res));
1012 g_simple_async_result_take_error (res, error);
1013 g_simple_async_result_complete (res);
1016 g_object_unref (res);
1020 on_create_service (GObject *source,
1021 GAsyncResult *result,
1024 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1025 CreateClosure *create = g_simple_async_result_get_op_res_gpointer (async);
1026 GError *error = NULL;
1027 SecretService *service;
1029 service = secret_service_get_finish (result, &error);
1030 if (error == NULL) {
1031 secret_service_create_collection_dbus_path (service, create->properties,
1032 create->alias, create->flags,
1033 create->cancellable,
1034 on_create_path, g_object_ref (async));
1035 g_object_unref (service);
1038 g_simple_async_result_take_error (async, error);
1039 g_simple_async_result_complete (async);
1042 g_object_unref (async);
1046 _secret_collection_properties_new (const gchar *label)
1048 GHashTable *properties;
1051 properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
1052 (GDestroyNotify)g_variant_unref);
1053 value = g_variant_new_string (label);
1054 g_hash_table_insert (properties,
1055 SECRET_COLLECTION_INTERFACE ".Label",
1056 g_variant_ref_sink (value));
1062 * secret_collection_create:
1063 * @service: (allow-none): a secret service object
1064 * @label: label for the new collection
1065 * @alias: (allow-none): alias to assign to the collection
1066 * @flags: currently unused
1067 * @cancellable: optional cancellation object
1068 * @callback: called when the operation completes
1069 * @user_data: data to pass to the callback
1071 * Create a new collection in the secret service.
1073 * This method returns immediately and completes asynchronously. The secret
1074 * service may prompt the user. secret_service_prompt() will be used to handle
1075 * any prompts that are required.
1077 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1078 * default collection to store items in). This allows other applications to
1079 * easily identify and share a collection. If you specify an @alias, and a
1080 * collection with that alias already exists, then a new collection will not
1081 * be created. The previous one will be returned instead.
1083 * If @service is NULL, then secret_service_get() will be called to get
1084 * the default #SecretService proxy.
1088 secret_collection_create (SecretService *service,
1091 SecretCollectionCreateFlags flags,
1092 GCancellable *cancellable,
1093 GAsyncReadyCallback callback,
1096 GSimpleAsyncResult *res;
1097 CreateClosure *closure;
1099 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
1100 g_return_if_fail (label != NULL);
1101 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1103 res = g_simple_async_result_new (NULL, callback, user_data,
1104 secret_collection_create);
1105 closure = g_slice_new0 (CreateClosure);
1106 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1107 closure->properties = _secret_collection_properties_new (label);
1108 closure->alias = g_strdup (alias);
1109 closure->flags = flags;
1110 g_simple_async_result_set_op_res_gpointer (res, closure, create_closure_free);
1112 if (service == NULL) {
1113 secret_service_get (SECRET_SERVICE_NONE, cancellable,
1114 on_create_service, g_object_ref (res));
1117 secret_service_create_collection_dbus_path (service, closure->properties,
1118 closure->alias, closure->flags,
1119 closure->cancellable,
1120 on_create_path, g_object_ref (res));
1123 g_object_unref (res);
1127 * secret_collection_create_finish:
1128 * @result: the asynchronous result passed to the callback
1129 * @error: location to place an error on failure
1131 * Finish operation to create a new collection in the secret service.
1133 * Returns: (transfer full): the new collection, which should be unreferenced
1134 * with g_object_unref()
1137 secret_collection_create_finish (GAsyncResult *result,
1140 GSimpleAsyncResult *res;
1141 CreateClosure *closure;
1143 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
1144 secret_collection_create), NULL);
1145 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1147 res = G_SIMPLE_ASYNC_RESULT (result);
1149 if (_secret_util_propagate_error (res, error))
1152 closure = g_simple_async_result_get_op_res_gpointer (res);
1153 if (closure->collection == NULL)
1156 return g_object_ref (closure->collection);
1160 * secret_collection_create_sync:
1161 * @service: (allow-none): a secret service object
1162 * @label: label for the new collection
1163 * @alias: (allow-none): alias to assign to the collection
1164 * @flags: currently unused
1165 * @cancellable: optional cancellation object
1166 * @error: location to place an error on failure
1168 * Create a new collection in the secret service.
1170 * This method may block indefinitely and should not be used in user interface
1171 * threads. The secret service may prompt the user. secret_service_prompt()
1172 * will be used to handle any prompts that are required.
1174 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1175 * default collection to store items in). This allows other applications to
1176 * easily identify and share a collection. If you specify an @alias, and a
1177 * collection with that alias already exists, then a new collection will not
1178 * be created. The previous one will be returned instead.
1180 * If @service is NULL, then secret_service_get_sync() will be called to get
1181 * the default #SecretService proxy.
1183 * Returns: (transfer full): the new collection, which should be unreferenced
1184 * with g_object_unref()
1187 secret_collection_create_sync (SecretService *service,
1190 SecretCollectionCreateFlags flags,
1191 GCancellable *cancellable,
1194 SecretCollection *collection;
1195 GHashTable *properties;
1198 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
1199 g_return_val_if_fail (label != NULL, NULL);
1200 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1201 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1203 if (service == NULL) {
1204 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
1205 if (service == NULL)
1208 g_object_ref (service);
1211 properties = _secret_collection_properties_new (label);
1213 path = secret_service_create_collection_dbus_path_sync (service, properties, alias,
1214 flags, cancellable, error);
1216 g_hash_table_unref (properties);
1219 g_object_unref (service);
1223 collection = secret_collection_new_for_dbus_path_sync (service, path,
1224 SECRET_COLLECTION_LOAD_ITEMS,
1225 cancellable, error);
1227 g_object_unref (service);
1234 SecretCollection *collection;
1235 GCancellable *cancellable;
1239 SecretSearchFlags flags;
1243 search_closure_free (gpointer data)
1245 SearchClosure *closure = data;
1246 g_object_unref (closure->collection);
1247 g_clear_object (&closure->cancellable);
1248 g_hash_table_unref (closure->items);
1249 g_strfreev (closure->paths);
1250 g_slice_free (SearchClosure, closure);
1254 search_closure_take_item (SearchClosure *closure,
1257 const gchar *path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
1258 g_hash_table_insert (closure->items, (gpointer)path, item);
1262 on_search_secrets (GObject *source,
1263 GAsyncResult *result,
1266 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1268 /* Note that we ignore any unlock failure */
1269 secret_item_load_secrets_finish (result, NULL);
1271 g_simple_async_result_complete (async);
1272 g_object_unref (async);
1276 on_search_unlocked (GObject *source,
1277 GAsyncResult *result,
1280 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1281 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1284 /* Note that we ignore any unlock failure */
1285 secret_service_unlock_finish (SECRET_SERVICE (source), result, NULL, NULL);
1287 /* If loading secrets ... locked items automatically ignored */
1288 if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1289 items = g_hash_table_get_values (search->items);
1290 secret_item_load_secrets (items, search->cancellable,
1291 on_search_secrets, g_object_ref (async));
1292 g_list_free (items);
1294 /* No additional options, just complete */
1296 g_simple_async_result_complete (async);
1299 g_object_unref (async);
1303 secret_search_unlock_load_or_complete (GSimpleAsyncResult *async,
1304 SearchClosure *search)
1308 /* If unlocking then unlock all the locked items */
1309 if (search->flags & SECRET_SEARCH_UNLOCK) {
1310 items = g_hash_table_get_values (search->items);
1311 secret_service_unlock (secret_collection_get_service (search->collection),
1312 items, search->cancellable,
1313 on_search_unlocked, g_object_ref (async));
1314 g_list_free (items);
1316 /* If loading secrets ... locked items automatically ignored */
1317 } else if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1318 items = g_hash_table_get_values (search->items);
1319 secret_item_load_secrets (items, search->cancellable,
1320 on_search_secrets, g_object_ref (async));
1321 g_list_free (items);
1323 /* No additional options, just complete */
1325 g_simple_async_result_complete (async);
1330 on_search_loaded (GObject *source,
1331 GAsyncResult *result,
1334 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1335 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1336 GError *error = NULL;
1341 item = secret_item_new_for_dbus_path_finish (result, &error);
1343 g_simple_async_result_take_error (async, error);
1346 search_closure_take_item (search, item);
1348 /* We're done loading, lets go to the next step */
1349 if (search->loading == 0)
1350 secret_search_unlock_load_or_complete (async, search);
1352 g_object_unref (async);
1356 on_search_paths (GObject *source,
1357 GAsyncResult *result,
1360 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1361 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1362 SecretCollection *self = search->collection;
1363 SecretService *service = secret_collection_get_service (self);
1364 GError *error = NULL;
1369 search->paths = secret_collection_search_for_dbus_paths_finish (self, result, &error);
1370 if (error == NULL) {
1372 if (search->flags & SECRET_SEARCH_ALL)
1375 for (i = 0; i < want && search->paths[i] != NULL; i++) {
1376 item = _secret_collection_find_item_instance (self, search->paths[i]);
1378 secret_item_new_for_dbus_path (service, search->paths[i], SECRET_ITEM_NONE,
1379 search->cancellable, on_search_loaded,
1380 g_object_ref (async));
1383 search_closure_take_item (search, item);
1388 /* No items loading, complete operation now */
1389 if (search->loading == 0)
1390 secret_search_unlock_load_or_complete (async, search);
1393 g_simple_async_result_take_error (async, error);
1394 g_simple_async_result_complete (async);
1397 g_object_unref (async);
1401 * secret_collection_search:
1402 * @self: a secret collection
1403 * @schema: (allow-none): the schema for the attributes
1404 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1405 * @flags: search option flags
1406 * @cancellable: optional cancellation object
1407 * @callback: called when the operation completes
1408 * @user_data: data to pass to the callback
1410 * Search for items matching the @attributes in the @collection.
1411 * The @attributes should be a table of string keys and string values.
1413 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1414 * search will be returned. Otherwise only the first item will be returned.
1415 * This is almost always the unlocked item that was most recently stored.
1417 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1418 * if necessary. In either case, locked and unlocked items will match the
1419 * search and be returned. If the unlock fails, the search does not fail.
1421 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1422 * their secret values loaded and available via secret_item_get_secret().
1424 * This function returns immediately and completes asynchronously.
1427 secret_collection_search (SecretCollection *self,
1428 const SecretSchema *schema,
1429 GHashTable *attributes,
1430 SecretSearchFlags flags,
1431 GCancellable *cancellable,
1432 GAsyncReadyCallback callback,
1435 GSimpleAsyncResult *async;
1436 SearchClosure *search;
1438 g_return_if_fail (SECRET_IS_COLLECTION (self));
1439 g_return_if_fail (attributes != NULL);
1440 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1442 /* Warnings raised already */
1443 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1446 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1447 secret_collection_search);
1448 search = g_slice_new0 (SearchClosure);
1449 search->collection = g_object_ref (self);
1450 search->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1451 search->items = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
1452 search->flags = flags;
1453 g_simple_async_result_set_op_res_gpointer (async, search, search_closure_free);
1455 secret_collection_search_for_dbus_paths (self, schema, attributes,
1456 cancellable, on_search_paths,
1457 g_object_ref (async));
1459 g_object_unref (async);
1463 * secret_collection_search_finish:
1464 * @self: the secret collection
1465 * @result: asynchronous result passed to callback
1466 * @error: location to place error on failure
1468 * Complete asynchronous operation to search for items in a collection.
1470 * Returns: (transfer full) (element-type SecretUnstable.Item):
1471 * a list of items that matched the search
1474 secret_collection_search_finish (SecretCollection *self,
1475 GAsyncResult *result,
1478 GSimpleAsyncResult *async;
1479 SearchClosure *search;
1480 GList *items = NULL;
1484 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1485 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1486 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1487 secret_collection_search), NULL);
1489 async = G_SIMPLE_ASYNC_RESULT (result);
1490 if (_secret_util_propagate_error (async, error))
1493 search = g_simple_async_result_get_op_res_gpointer (async);
1495 for (i = 0; search->paths[i]; i++) {
1496 item = g_hash_table_lookup (search->items, search->paths[i]);
1498 items = g_list_prepend (items, g_object_ref (item));
1501 return g_list_reverse (items);
1505 collection_load_items_sync (SecretCollection *self,
1506 GCancellable *cancellable,
1512 SecretService *service = secret_collection_get_service (self);
1517 for (i = 0; have < want && paths[i] != NULL; i++) {
1518 item = _secret_collection_find_item_instance (self, paths[i]);
1520 item = secret_item_new_for_dbus_path_sync (service, paths[i], SECRET_ITEM_NONE,
1521 cancellable, error);
1526 *items = g_list_prepend (*items, item);
1535 * secret_collection_search_sync:
1536 * @self: a secret collection
1537 * @schema: (allow-none): the schema for the attributes
1538 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1539 * @flags: search option flags
1540 * @cancellable: optional cancellation object
1541 * @error: location to place error on failure
1543 * Search for items matching the @attributes in the @collection.
1544 * The @attributes should be a table of string keys and string values.
1546 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1547 * search will be returned. Otherwise only the first item will be returned.
1548 * This is almost always the unlocked item that was most recently stored.
1550 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1551 * if necessary. In either case, locked and unlocked items will match the
1552 * search and be returned. If the unlock fails, the search does not fail.
1554 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1555 * their secret values loaded and available via secret_item_get_secret().
1557 * This function may block indefinetely. Use the asynchronous version
1558 * in user interface threads.
1560 * Returns: (transfer full) (element-type SecretUnstable.Item):
1561 * a list of items that matched the search
1564 secret_collection_search_sync (SecretCollection *self,
1565 const SecretSchema *schema,
1566 GHashTable *attributes,
1567 SecretSearchFlags flags,
1568 GCancellable *cancellable,
1571 gchar **paths = NULL;
1572 GList *items = NULL;
1576 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1577 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1578 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1580 /* Warnings raised already */
1581 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1584 paths = secret_collection_search_for_dbus_paths_sync (self, schema, attributes,
1585 cancellable, error);
1592 if (flags & SECRET_SEARCH_ALL)
1595 ret = collection_load_items_sync (self, cancellable, paths,
1596 &items, want, error);
1603 if (flags & SECRET_SEARCH_UNLOCK) {
1604 secret_service_unlock_sync (secret_collection_get_service (self),
1605 items, cancellable, NULL, NULL);
1608 if (flags & SECRET_SEARCH_LOAD_SECRETS)
1609 secret_item_load_secrets_sync (items, NULL, NULL);
1615 on_service_delete_path (GObject *source,
1616 GAsyncResult *result,
1619 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1620 GError *error = NULL;
1622 _secret_service_delete_path_finish (SECRET_SERVICE (source), result, &error);
1624 g_simple_async_result_take_error (async, error);
1625 g_simple_async_result_complete (async);
1626 g_object_unref (async);
1629 * secret_collection_delete:
1630 * @self: a collection
1631 * @cancellable: optional cancellation object
1632 * @callback: called when the operation completes
1633 * @user_data: data to pass to the callback
1635 * Delete this collection.
1637 * This method returns immediately and completes asynchronously. The secret
1638 * service may prompt the user. secret_service_prompt() will be used to handle
1639 * any prompts that show up.
1642 secret_collection_delete (SecretCollection *self,
1643 GCancellable *cancellable,
1644 GAsyncReadyCallback callback,
1647 GSimpleAsyncResult *async;
1648 const gchar *object_path;
1650 g_return_if_fail (SECRET_IS_COLLECTION (self));
1651 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1653 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1654 secret_collection_delete);
1656 object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
1657 _secret_service_delete_path (self->pv->service, object_path, FALSE,
1658 cancellable, on_service_delete_path,
1659 g_object_ref (async));
1661 g_object_unref (async);
1665 * secret_collection_delete_finish:
1666 * @self: a collection
1667 * @result: asynchronous result passed to the callback
1668 * @error: location to place an error on failure
1670 * Complete operation to delete this collection.
1672 * Returns: whether the collection was successfully deleted or not
1675 secret_collection_delete_finish (SecretCollection *self,
1676 GAsyncResult *result,
1679 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1680 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1681 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1682 secret_collection_delete), FALSE);
1684 if (_secret_util_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
1691 * secret_collection_delete_sync:
1692 * @self: a collection
1693 * @cancellable: optional cancellation object
1694 * @error: location to place an error on failure
1696 * Delete this collection.
1698 * This method may block indefinitely and should not be used in user
1699 * interface threads. The secret service may prompt the user.
1700 * secret_service_prompt() will be used to handle any prompts that show up.
1702 * Returns: whether the collection was successfully deleted or not
1705 secret_collection_delete_sync (SecretCollection *self,
1706 GCancellable *cancellable,
1712 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1713 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1714 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1716 sync = _secret_sync_new ();
1717 g_main_context_push_thread_default (sync->context);
1719 secret_collection_delete (self, cancellable, _secret_sync_on_result, sync);
1721 g_main_loop_run (sync->loop);
1723 ret = secret_collection_delete_finish (self, sync->result, error);
1725 g_main_context_pop_thread_default (sync->context);
1726 _secret_sync_free (sync);
1732 * secret_collection_get_service:
1733 * @self: a collection
1735 * Get the Secret Service object that this collection was created with.
1737 * Returns: (transfer none): the Secret Service object
1740 secret_collection_get_service (SecretCollection *self)
1742 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1743 return self->pv->service;
1747 * secret_collection_get_flags:
1748 * @self: the secret collection proxy
1750 * Get the flags representing what features of the #SecretCollection proxy
1751 * have been initialized.
1753 * Use secret_collection_load_items() to initialize further features
1754 * and change the flags.
1756 * Returns: the flags for features initialized
1758 SecretCollectionFlags
1759 secret_collection_get_flags (SecretCollection *self)
1761 SecretCollectionFlags flags = 0;
1763 g_return_val_if_fail (SECRET_IS_COLLECTION (self), SECRET_COLLECTION_NONE);
1765 g_mutex_lock (&self->pv->mutex);
1767 if (self->pv->items)
1768 flags |= SECRET_COLLECTION_LOAD_ITEMS;
1770 g_mutex_unlock (&self->pv->mutex);
1776 * secret_collection_get_items:
1777 * @self: a collection
1779 * Get the list of items in this collection.
1781 * Returns: (transfer full) (element-type SecretUnstable.Item): a list of items,
1782 * when done, the list should be freed with g_list_free, and each item should
1783 * be released with g_object_unref()
1786 secret_collection_get_items (SecretCollection *self)
1788 GList *l, *items = NULL;
1790 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1792 g_mutex_lock (&self->pv->mutex);
1793 if (self->pv->items)
1794 items = g_hash_table_get_values (self->pv->items);
1795 for (l = items; l != NULL; l = g_list_next (l))
1796 g_object_ref (l->data);
1797 g_mutex_unlock (&self->pv->mutex);
1803 _secret_collection_find_item_instance (SecretCollection *self,
1804 const gchar *item_path)
1806 SecretItem *item = NULL;
1808 g_mutex_lock (&self->pv->mutex);
1809 if (self->pv->items)
1810 item = g_hash_table_lookup (self->pv->items, item_path);
1812 g_object_ref (item);
1813 g_mutex_unlock (&self->pv->mutex);
1819 * secret_collection_get_label:
1820 * @self: a collection
1822 * Get the label of this collection.
1824 * Returns: (transfer full): the label, which should be freed with g_free()
1827 secret_collection_get_label (SecretCollection *self)
1832 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1834 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Label");
1835 g_return_val_if_fail (variant != NULL, NULL);
1837 label = g_variant_dup_string (variant, NULL);
1838 g_variant_unref (variant);
1844 * secret_collection_set_label:
1845 * @self: a collection
1846 * @label: a new label
1847 * @cancellable: optional cancellation object
1848 * @callback: called when the operation completes
1849 * @user_data: data to pass to the callback
1851 * Set the label of this collection.
1853 * This function returns immediately and completes asynchronously.
1856 secret_collection_set_label (SecretCollection *self,
1858 GCancellable *cancellable,
1859 GAsyncReadyCallback callback,
1862 g_return_if_fail (SECRET_IS_COLLECTION (self));
1863 g_return_if_fail (label != NULL);
1865 _secret_util_set_property (G_DBUS_PROXY (self), "Label",
1866 g_variant_new_string (label),
1867 secret_collection_set_label,
1868 cancellable, callback, user_data);
1872 * secret_collection_set_label_finish:
1873 * @self: a collection
1874 * @result: asynchronous result passed to callback
1875 * @error: location to place error on failure
1877 * Complete asynchronous operation to set the label of this collection.
1879 * Returns: whether the change was successful or not
1882 secret_collection_set_label_finish (SecretCollection *self,
1883 GAsyncResult *result,
1886 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1888 return _secret_util_set_property_finish (G_DBUS_PROXY (self),
1889 secret_collection_set_label,
1894 * secret_collection_set_label_sync:
1895 * @self: a collection
1896 * @label: a new label
1897 * @cancellable: optional cancellation object
1898 * @error: location to place error on failure
1900 * Set the label of this collection.
1902 * This function may block indefinetely. Use the asynchronous version
1903 * in user interface threads.
1905 * Returns: whether the change was successful or not
1908 secret_collection_set_label_sync (SecretCollection *self,
1910 GCancellable *cancellable,
1913 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1914 g_return_val_if_fail (label != NULL, FALSE);
1916 return _secret_util_set_property_sync (G_DBUS_PROXY (self), "Label",
1917 g_variant_new_string (label),
1918 cancellable, error);
1922 * secret_collection_get_locked:
1923 * @self: a collection
1925 * Get whether the collection is locked or not.
1927 * Use secret_service_lock() or secret_service_unlock() to lock or unlock the
1930 * Returns: whether the collection is locked or not
1933 secret_collection_get_locked (SecretCollection *self)
1938 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1940 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Locked");
1941 g_return_val_if_fail (variant != NULL, TRUE);
1943 locked = g_variant_get_boolean (variant);
1944 g_variant_unref (variant);
1950 * secret_collection_get_created:
1951 * @self: a collection
1953 * Get the created date and time of the collection. The return value is
1954 * the number of seconds since the unix epoch, January 1st 1970.
1956 * Returns: the created date and time
1959 secret_collection_get_created (SecretCollection *self)
1964 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1966 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Created");
1967 g_return_val_if_fail (variant != NULL, 0);
1969 created = g_variant_get_uint64 (variant);
1970 g_variant_unref (variant);
1976 * secret_collection_get_modified:
1977 * @self: a collection
1979 * Get the modified date and time of the collection. The return value is
1980 * the number of seconds since the unix epoch, January 1st 1970.
1982 * Returns: the modified date and time
1985 secret_collection_get_modified (SecretCollection *self)
1990 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1992 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Modified");
1993 g_return_val_if_fail (variant != NULL, 0);
1995 modified = g_variant_get_uint64 (variant);
1996 g_variant_unref (variant);
2003 GCancellable *cancellable;
2005 SecretCollectionFlags flags;
2006 SecretCollection *collection;
2010 read_closure_free (gpointer data)
2012 ReadClosure *read = data;
2013 g_free (read->alias);
2014 if (read->collection)
2015 g_object_unref (read->collection);
2016 if (read->cancellable)
2017 g_object_unref (read->cancellable);
2018 g_slice_free (ReadClosure, read);
2022 on_read_alias_collection (GObject *source,
2023 GAsyncResult *result,
2026 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2027 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2028 GError *error = NULL;
2030 read->collection = secret_collection_new_for_dbus_path_finish (result, &error);
2032 g_simple_async_result_take_error (async, error);
2034 g_simple_async_result_complete (async);
2035 g_object_unref (async);
2039 on_read_alias_path (GObject *source,
2040 GAsyncResult *result,
2043 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2044 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2045 SecretService *self = SECRET_SERVICE (source);
2046 GError *error = NULL;
2047 gchar *collection_path;
2049 collection_path = secret_service_read_alias_dbus_path_finish (self, result, &error);
2050 if (error == NULL) {
2052 /* No collection for this alias */
2053 if (collection_path == NULL) {
2054 g_simple_async_result_complete (async);
2057 read->collection = _secret_service_find_collection_instance (self,
2059 if (read->collection != NULL) {
2061 /* Make sure collection has necessary flags */
2062 collection_ensure_for_flags_async (read->collection, read->flags,
2063 read->cancellable, async);
2065 /* No collection loaded, but valid path, load */
2067 secret_collection_new_for_dbus_path (self, collection_path,
2070 on_read_alias_collection,
2071 g_object_ref (async));
2076 g_simple_async_result_take_error (async, error);
2077 g_simple_async_result_complete (async);
2080 g_free (collection_path);
2081 g_object_unref (async);
2085 on_read_alias_service (GObject *source,
2086 GAsyncResult *result,
2089 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2090 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2091 SecretService *service;
2092 GError *error = NULL;
2094 service = secret_service_get_finish (result, &error);
2095 if (error == NULL) {
2096 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2097 on_read_alias_path, g_object_ref (async));
2098 g_object_unref (service);
2101 g_simple_async_result_take_error (async, error);
2102 g_simple_async_result_complete (async);
2105 g_object_unref (async);
2109 * secret_collection_for_alias:
2110 * @service: (allow-none): a secret service object
2111 * @alias: the alias to lookup
2112 * @flags: options for the collection initialization
2113 * @cancellable: (allow-none): optional cancellation object
2114 * @callback: called when the operation completes
2115 * @user_data: data to pass to the callback
2117 * Lookup which collection is assigned to this alias. Aliases help determine
2118 * well known collections, such as 'default'.
2120 * If @service is NULL, then secret_service_get() will be called to get
2121 * the default #SecretService proxy.
2123 * This method will return immediately and complete asynchronously.
2126 secret_collection_for_alias (SecretService *service,
2128 SecretCollectionFlags flags,
2129 GCancellable *cancellable,
2130 GAsyncReadyCallback callback,
2133 GSimpleAsyncResult *async;
2136 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
2137 g_return_if_fail (alias != NULL);
2138 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2140 async = g_simple_async_result_new (NULL, callback, user_data,
2141 secret_collection_for_alias);
2142 read = g_slice_new0 (ReadClosure);
2143 read->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
2144 read->alias = g_strdup (alias);
2145 read->flags = flags;
2146 g_simple_async_result_set_op_res_gpointer (async, read, read_closure_free);
2148 if (service == NULL) {
2149 secret_service_get (SECRET_SERVICE_NONE, cancellable,
2150 on_read_alias_service, g_object_ref (async));
2152 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2153 on_read_alias_path, g_object_ref (async));
2156 g_object_unref (async);
2160 * secret_collection_for_alias_finish:
2161 * @result: asynchronous result passed to callback
2162 * @error: location to place error on failure
2164 * Finish an asynchronous operation to lookup which collection is assigned
2167 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2170 secret_collection_for_alias_finish (GAsyncResult *result,
2173 GSimpleAsyncResult *async;
2176 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
2177 secret_collection_for_alias), NULL);
2178 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2180 async = G_SIMPLE_ASYNC_RESULT (result);
2181 if (_secret_util_propagate_error (async, error))
2183 read = g_simple_async_result_get_op_res_gpointer (async);
2184 if (read->collection)
2185 g_object_ref (read->collection);
2186 return read->collection;
2190 * secret_collection_for_alias_sync:
2191 * @service: (allow-none): a secret service object
2192 * @alias: the alias to lookup
2193 * @flags: options for the collection initialization
2194 * @cancellable: (allow-none): optional cancellation object
2195 * @error: location to place error on failure
2197 * Lookup which collection is assigned to this alias. Aliases help determine
2198 * well known collections, such as 'default'.
2200 * If @service is NULL, then secret_service_get_sync() will be called to get
2201 * the default #SecretService proxy.
2203 * This method may block and should not be used in user interface threads.
2205 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2208 secret_collection_for_alias_sync (SecretService *service,
2210 SecretCollectionFlags flags,
2211 GCancellable *cancellable,
2214 SecretCollection *collection;
2215 gchar *collection_path;
2217 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
2218 g_return_val_if_fail (alias != NULL, NULL);
2219 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2220 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2222 collection_path = secret_service_read_alias_dbus_path_sync (service, alias,
2223 cancellable, error);
2224 if (collection_path == NULL)
2227 /* No collection for this alias */
2228 if (collection_path == NULL) {
2232 collection = _secret_service_find_collection_instance (service,
2235 if (collection != NULL) {
2237 /* Have a collection with all necessary flags */
2238 if (!collection_ensure_for_flags_sync (collection, flags,
2239 cancellable, error)) {
2240 g_object_unref (collection);
2244 /* No collection loaded, but valid path, load */
2246 collection = secret_collection_new_for_dbus_path_sync (service, collection_path,
2247 flags, cancellable, error);
2251 g_free (collection_path);