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.
49 * A proxy object representing a collection of secrets in the Secret Service.
53 * SecretCollectionClass:
54 * @parent_class: the parent class
56 * The class for #SecretCollection.
60 * SecretCollectionFlags:
61 * @SECRET_COLLECTION_NONE: no flags
62 * @SECRET_COLLECTION_LOAD_ITEMS: items have or should be loaded
64 * Flags which determine which parts of the #SecretCollection proxy are initialized.
68 * SecretCollectionCreateFlags:
69 * @SECRET_COLLECTION_CREATE_NONE: no flags
71 * Flags for secret_collection_create().
75 * SECRET_COLLECTION_DEFAULT:
77 * An alias to the default collection. This can be passed to secret_password_store()
78 * secret_collection_for_alias().
82 * SECRET_COLLECTION_SESSION:
84 * An alias to the session collection, which will be cleared when the user ends
85 * the session. This can be passed to secret_password_store(),
86 * secret_collection_for_alias() or similar functions.
100 struct _SecretCollectionPrivate {
101 /* Doesn't change between construct and finalize */
102 SecretService *service;
103 GCancellable *cancellable;
104 gboolean constructing;
105 SecretCollectionFlags init_flags;
107 /* Protected by mutex */
112 static GInitableIface *secret_collection_initable_parent_iface = NULL;
114 static GAsyncInitableIface *secret_collection_async_initable_parent_iface = NULL;
116 static void secret_collection_initable_iface (GInitableIface *iface);
118 static void secret_collection_async_initable_iface (GAsyncInitableIface *iface);
120 G_DEFINE_TYPE_WITH_CODE (SecretCollection, secret_collection, G_TYPE_DBUS_PROXY,
121 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, secret_collection_initable_iface);
122 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, secret_collection_async_initable_iface);
126 items_table_new (void)
128 return g_hash_table_new_full (g_str_hash, g_str_equal,
129 g_free, g_object_unref);
133 secret_collection_init (SecretCollection *self)
135 self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SECRET_TYPE_COLLECTION,
136 SecretCollectionPrivate);
138 g_mutex_init (&self->pv->mutex);
139 self->pv->cancellable = g_cancellable_new ();
140 self->pv->items = items_table_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);
260 g_hash_table_destroy (self->pv->items);
261 g_object_unref (self->pv->cancellable);
263 G_OBJECT_CLASS (secret_collection_parent_class)->finalize (obj);
267 collection_lookup_item (SecretCollection *self,
270 SecretItem *item = NULL;
272 g_mutex_lock (&self->pv->mutex);
274 item = g_hash_table_lookup (self->pv->items, path);
278 g_mutex_unlock (&self->pv->mutex);
284 collection_update_items (SecretCollection *self,
287 GHashTable *previous;
289 g_hash_table_ref (items);
291 g_mutex_lock (&self->pv->mutex);
292 previous = self->pv->items;
293 self->pv->items = items;
294 g_mutex_unlock (&self->pv->mutex);
296 g_hash_table_unref (previous);
297 g_object_notify (G_OBJECT (self), "items");
301 handle_property_changed (SecretCollection *self,
302 const gchar *property_name,
307 if (g_str_equal (property_name, "Label")) {
308 g_object_notify (G_OBJECT (self), "label");
310 } else if (g_str_equal (property_name, "Locked")) {
311 g_object_notify (G_OBJECT (self), "locked");
313 } else if (g_str_equal (property_name, "Created")) {
314 g_object_notify (G_OBJECT (self), "created");
316 } else if (g_str_equal (property_name, "Modified")) {
317 g_object_notify (G_OBJECT (self), "modified");
319 } else if (g_str_equal (property_name, "Items") && !self->pv->constructing) {
320 g_mutex_lock (&self->pv->mutex);
321 perform = self->pv->items != NULL;
322 g_mutex_unlock (&self->pv->mutex);
325 secret_collection_load_items (self, self->pv->cancellable, NULL, NULL);
330 secret_collection_properties_changed (GDBusProxy *proxy,
331 GVariant *changed_properties,
332 const gchar* const *invalidated_properties)
334 SecretCollection *self = SECRET_COLLECTION (proxy);
335 gchar *property_name;
339 g_object_freeze_notify (G_OBJECT (self));
341 g_variant_iter_init (&iter, changed_properties);
342 while (g_variant_iter_loop (&iter, "{sv}", &property_name, &value))
343 handle_property_changed (self, property_name, value);
345 g_object_thaw_notify (G_OBJECT (self));
349 secret_collection_signal (GDBusProxy *proxy,
350 const gchar *sender_name,
351 const gchar *signal_name,
352 GVariant *parameters)
354 SecretCollection *self = SECRET_COLLECTION (proxy);
356 const gchar *item_path;
357 GVariantBuilder builder;
358 gboolean found = FALSE;
365 * Remember that these signals come from a time before PropertiesChanged.
366 * We support them because they're in the spec, and ksecretservice uses them.
369 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
371 /* A new collection was added, add it to the Collections property */
372 if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CREATED)) {
373 g_variant_get (parameters, "(@o)", &value);
374 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
375 g_variant_iter_init (&iter, paths);
376 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
377 if (g_variant_equal (path, value)) {
381 g_variant_builder_add_value (&builder, path);
382 g_variant_unref (path);
385 g_variant_builder_add_value (&builder, value);
386 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
388 g_variant_builder_clear (&builder);
389 g_variant_unref (value);
391 /* A collection was deleted, remove it from the Collections property */
392 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_DELETED)) {
393 g_variant_get (parameters, "(@o)", &value);
394 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
395 g_variant_iter_init (&iter, paths);
396 while ((path = g_variant_iter_next_value (&iter)) != NULL) {
397 if (g_variant_equal (path, value))
400 g_variant_builder_add_value (&builder, path);
401 g_variant_unref (path);
404 handle_property_changed (self, "Items", g_variant_builder_end (&builder));
405 g_variant_unref (value);
407 /* The collection changed, update it */
408 } else if (g_str_equal (signal_name, SECRET_SIGNAL_ITEM_CHANGED)) {
409 g_variant_get (parameters, "(&o)", &item_path);
411 g_mutex_lock (&self->pv->mutex);
414 item = g_hash_table_lookup (self->pv->items, item_path);
420 g_mutex_unlock (&self->pv->mutex);
423 secret_item_refresh (item);
424 g_object_unref (item);
428 g_variant_unref (paths);
432 secret_collection_class_init (SecretCollectionClass *klass)
434 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
435 GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass);
437 gobject_class->get_property = secret_collection_get_property;
438 gobject_class->set_property = secret_collection_set_property;
439 gobject_class->dispose = secret_collection_dispose;
440 gobject_class->finalize = secret_collection_finalize;
442 proxy_class->g_properties_changed = secret_collection_properties_changed;
443 proxy_class->g_signal = secret_collection_signal;
446 * SecretCollection:service:
448 * The #SecretService object that this collection is associated with and
449 * uses to interact with the actual D-Bus Secret Service.
451 g_object_class_install_property (gobject_class, PROP_SERVICE,
452 g_param_spec_object ("service", "Service", "Secret Service",
453 SECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
456 * SecretCollection:flags:
458 * A set of flags describing which parts of the secret collection have
461 g_object_class_install_property (gobject_class, PROP_FLAGS,
462 g_param_spec_flags ("flags", "Flags", "Collection flags",
463 secret_collection_flags_get_type (), SECRET_COLLECTION_NONE,
464 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
467 * SecretCollection:items:
469 * A list of #SecretItem objects representing the items that are in
470 * this collection. This list will be empty if the collection is locked.
472 g_object_class_install_property (gobject_class, PROP_ITEMS,
473 g_param_spec_boxed ("items", "Items", "Items in collection",
474 _secret_list_get_type (), G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
477 * SecretCollection:label:
479 * The human readable label for the collection.
481 * Setting this property will result in the label of the collection being
482 * set asynchronously. To properly track the changing of the label use the
483 * secret_collection_set_label() function.
485 g_object_class_install_property (gobject_class, PROP_LABEL,
486 g_param_spec_string ("label", "Label", "Item label",
487 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
490 * SecretCollection:locked:
492 * Whether the collection is locked or not.
494 * To lock or unlock a collection use the secret_service_lock() or
495 * secret_service_unlock() functions.
497 g_object_class_install_property (gobject_class, PROP_LOCKED,
498 g_param_spec_boolean ("locked", "Locked", "Item locked",
499 TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
502 * SecretCollection:created:
504 * The date and time (in seconds since the UNIX epoch) that this
505 * collection was created.
507 g_object_class_install_property (gobject_class, PROP_CREATED,
508 g_param_spec_uint64 ("created", "Created", "Item creation date",
509 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
512 * SecretCollection:modified:
514 * The date and time (in seconds since the UNIX epoch) that this
515 * collection was last modified.
517 g_object_class_install_property (gobject_class, PROP_MODIFIED,
518 g_param_spec_uint64 ("modified", "Modified", "Item modified date",
519 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
521 g_type_class_add_private (gobject_class, sizeof (SecretCollectionPrivate));
525 secret_collection_initable_init (GInitable *initable,
526 GCancellable *cancellable,
529 SecretCollection *self;
530 SecretService *service;
533 if (!secret_collection_initable_parent_iface->init (initable, cancellable, error))
536 proxy = G_DBUS_PROXY (initable);
538 if (!_secret_util_have_cached_properties (proxy)) {
539 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
540 "No such secret collection at path: %s",
541 g_dbus_proxy_get_object_path (proxy));
545 self = SECRET_COLLECTION (initable);
547 if (self->pv->service == NULL) {
548 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
552 collection_take_service (self, service);
555 if (self->pv->init_flags & SECRET_COLLECTION_LOAD_ITEMS) {
556 if (!secret_collection_load_items_sync (self, cancellable, error))
560 self->pv->constructing = FALSE;
565 secret_collection_initable_iface (GInitableIface *iface)
567 secret_collection_initable_parent_iface = g_type_interface_peek_parent (iface);
569 iface->init = secret_collection_initable_init;
573 GCancellable *cancellable;
577 init_closure_free (gpointer data)
579 InitClosure *closure = data;
580 g_clear_object (&closure->cancellable);
581 g_slice_free (InitClosure, closure);
585 on_init_items (GObject *source,
586 GAsyncResult *result,
589 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
590 SecretCollection *self = SECRET_COLLECTION (source);
591 GError *error = NULL;
593 if (!secret_collection_load_items_finish (self, result, &error))
594 g_simple_async_result_take_error (res, error);
596 g_simple_async_result_complete (res);
597 g_object_unref (res);
601 collection_ensure_for_flags_async (SecretCollection *self,
602 SecretCollectionFlags flags,
603 GSimpleAsyncResult *async)
605 InitClosure *init = g_simple_async_result_get_op_res_gpointer (async);
607 if (flags & SECRET_COLLECTION_LOAD_ITEMS)
608 secret_collection_load_items (self, init->cancellable,
609 on_init_items, g_object_ref (async));
612 g_simple_async_result_complete (async);
616 on_init_service (GObject *source,
617 GAsyncResult *result,
620 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
621 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
622 SecretService *service;
623 GError *error = NULL;
625 service = secret_service_get_finish (result, &error);
627 collection_take_service (self, service);
628 collection_ensure_for_flags_async (self, self->pv->init_flags, async);
631 g_simple_async_result_take_error (async, error);
632 g_simple_async_result_complete (async);
635 g_object_unref (self);
636 g_object_unref (async);
640 on_init_base (GObject *source,
641 GAsyncResult *result,
644 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
645 SecretCollection *self = SECRET_COLLECTION (source);
646 InitClosure *init = g_simple_async_result_get_op_res_gpointer (res);
647 GDBusProxy *proxy = G_DBUS_PROXY (self);
648 GError *error = NULL;
650 if (!secret_collection_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
652 g_simple_async_result_take_error (res, error);
653 g_simple_async_result_complete (res);
655 } else if (!_secret_util_have_cached_properties (proxy)) {
656 g_simple_async_result_set_error (res, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
657 "No such secret collection at path: %s",
658 g_dbus_proxy_get_object_path (proxy));
659 g_simple_async_result_complete (res);
661 } else if (self->pv->service == NULL) {
662 secret_service_get (SECRET_SERVICE_NONE, init->cancellable,
663 on_init_service, g_object_ref (res));
666 collection_ensure_for_flags_async (self, self->pv->init_flags, res);
669 g_object_unref (res);
673 secret_collection_async_initable_init_async (GAsyncInitable *initable,
675 GCancellable *cancellable,
676 GAsyncReadyCallback callback,
679 GSimpleAsyncResult *res;
680 InitClosure *closure;
682 res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data,
683 secret_collection_async_initable_init_async);
684 closure = g_slice_new0 (InitClosure);
685 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
686 g_simple_async_result_set_op_res_gpointer (res, closure, init_closure_free);
688 secret_collection_async_initable_parent_iface->init_async (initable, io_priority,
693 g_object_unref (res);
697 secret_collection_async_initable_init_finish (GAsyncInitable *initable,
698 GAsyncResult *result,
701 SecretCollection *self = SECRET_COLLECTION (initable);
703 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable),
704 secret_collection_async_initable_init_async), FALSE);
706 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
709 self->pv->constructing = FALSE;
714 secret_collection_async_initable_iface (GAsyncInitableIface *iface)
716 secret_collection_async_initable_parent_iface = g_type_interface_peek_parent (iface);
718 iface->init_async = secret_collection_async_initable_init_async;
719 iface->init_finish = secret_collection_async_initable_init_finish;
723 GCancellable *cancellable;
729 items_closure_free (gpointer data)
731 ItemsClosure *closure = data;
732 g_clear_object (&closure->cancellable);
733 g_hash_table_unref (closure->items);
734 g_slice_free (ItemsClosure, closure);
738 on_load_item (GObject *source,
739 GAsyncResult *result,
742 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
743 ItemsClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
744 SecretCollection *self = SECRET_COLLECTION (g_async_result_get_source_object (user_data));
746 GError *error = NULL;
749 closure->items_loading--;
751 item = secret_item_new_for_dbus_path_finish (result, &error);
754 g_simple_async_result_take_error (res, error);
757 path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
758 g_hash_table_insert (closure->items, g_strdup (path), item);
761 if (closure->items_loading == 0) {
762 collection_update_items (self, closure->items);
763 g_simple_async_result_complete_in_idle (res);
766 g_object_unref (self);
767 g_object_unref (res);
771 * secret_collection_load_items:
772 * @self: the secret collection
773 * @cancellable: optional cancellation object
774 * @callback: called when the operation completes
775 * @user_data: data to be passed to the callback
777 * Ensure that the #SecretCollection proxy has loaded all the items present
778 * in the Secret Service. This affects the result of
779 * secret_collection_get_items().
781 * For collections returned from secret_service_get_collections() the items
782 * will have already been loaded.
784 * This method will return immediately and complete asynchronously.
787 secret_collection_load_items (SecretCollection *self,
788 GCancellable *cancellable,
789 GAsyncReadyCallback callback,
792 ItemsClosure *closure;
794 GSimpleAsyncResult *res;
799 g_return_if_fail (SECRET_IS_COLLECTION (self));
800 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
802 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
803 g_return_if_fail (paths != NULL);
805 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
806 secret_collection_load_items);
807 closure = g_slice_new0 (ItemsClosure);
808 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
809 closure->items = items_table_new ();
810 g_simple_async_result_set_op_res_gpointer (res, closure, items_closure_free);
812 g_variant_iter_init (&iter, paths);
813 while (g_variant_iter_loop (&iter, "&o", &path)) {
814 item = collection_lookup_item (self, path);
816 /* No such collection yet create a new one */
818 secret_item_new_for_dbus_path (self->pv->service, path, SECRET_ITEM_NONE,
819 cancellable, on_load_item, g_object_ref (res));
820 closure->items_loading++;
823 g_hash_table_insert (closure->items, g_strdup (path), item);
827 if (closure->items_loading == 0) {
828 collection_update_items (self, closure->items);
829 g_simple_async_result_complete_in_idle (res);
832 g_variant_unref (paths);
833 g_object_unref (res);
837 * secret_collection_load_items_finish:
838 * @self: the secret collection
839 * @result: the asynchronous result passed to the callback
840 * @error: location to place an error on failure
842 * Complete an asynchronous operation to ensure that the #SecretCollection proxy
843 * has loaded all the items present in the Secret Service.
845 * Returns: whether the load was successful or not
848 secret_collection_load_items_finish (SecretCollection *self,
849 GAsyncResult *result,
852 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
853 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
854 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
855 secret_collection_load_items), FALSE);
857 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
864 * secret_collection_load_items_sync:
865 * @self: the secret collection
866 * @cancellable: optional cancellation object
867 * @error: location to place an error on failure
869 * Ensure that the #SecretCollection proxy has loaded all the items present
870 * in the Secret Service. This affects the result of
871 * secret_collection_get_items().
873 * For collections returned from secret_service_get_collections() the items
874 * will have already been loaded.
876 * This method may block indefinitely and should not be used in user interface
879 * Returns: whether the load was successful or not
882 secret_collection_load_items_sync (SecretCollection *self,
883 GCancellable *cancellable,
893 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
894 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
895 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
897 paths = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Items");
898 g_return_val_if_fail (paths != NULL, FALSE);
900 items = items_table_new ();
902 g_variant_iter_init (&iter, paths);
903 while (g_variant_iter_next (&iter, "&o", &path)) {
904 item = collection_lookup_item (self, path);
906 /* No such collection yet create a new one */
908 item = secret_item_new_for_dbus_path_sync (self->pv->service, path,
917 g_hash_table_insert (items, g_strdup (path), item);
921 collection_update_items (self, items);
923 g_hash_table_unref (items);
924 g_variant_unref (paths);
929 * secret_collection_refresh:
930 * @self: the collection
932 * Refresh the properties on this collection. This fires off a request to
933 * refresh, and the properties will be updated later.
935 * Calling this method is not normally necessary, as the secret service
936 * will notify the client when properties change.
939 secret_collection_refresh (SecretCollection *self)
941 g_return_if_fail (SECRET_IS_COLLECTION (self));
943 _secret_util_get_properties (G_DBUS_PROXY (self),
944 secret_collection_refresh,
945 self->pv->cancellable, NULL, NULL);
949 GCancellable *cancellable;
950 SecretCollection *collection;
951 GHashTable *properties;
953 SecretCollectionCreateFlags flags;
957 create_closure_free (gpointer data)
959 CreateClosure *closure = data;
960 g_clear_object (&closure->cancellable);
961 g_clear_object (&closure->collection);
962 g_hash_table_unref (closure->properties);
963 g_free (closure->alias);
964 g_slice_free (CreateClosure, closure);
968 on_create_collection (GObject *source,
969 GAsyncResult *result,
972 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
973 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
974 GError *error = NULL;
976 closure->collection = secret_collection_new_for_dbus_path_finish (result, &error);
978 g_simple_async_result_take_error (res, error);
980 g_simple_async_result_complete (res);
981 g_object_unref (res);
985 on_create_path (GObject *source,
986 GAsyncResult *result,
989 GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
990 CreateClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
991 SecretService *service = SECRET_SERVICE (source);
992 GError *error = NULL;
995 path = secret_service_create_collection_dbus_path_finish (service, result, &error);
997 secret_collection_new_for_dbus_path (service, path, SECRET_COLLECTION_LOAD_ITEMS,
998 closure->cancellable,
999 on_create_collection, g_object_ref (res));
1001 g_simple_async_result_take_error (res, error);
1002 g_simple_async_result_complete (res);
1005 g_object_unref (res);
1009 on_create_service (GObject *source,
1010 GAsyncResult *result,
1013 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1014 CreateClosure *create = g_simple_async_result_get_op_res_gpointer (async);
1015 GError *error = NULL;
1016 SecretService *service;
1018 service = secret_service_get_finish (result, &error);
1019 if (error == NULL) {
1020 secret_service_create_collection_dbus_path (service, create->properties,
1021 create->alias, create->flags,
1022 create->cancellable,
1023 on_create_path, g_object_ref (async));
1024 g_object_unref (service);
1027 g_simple_async_result_take_error (async, error);
1028 g_simple_async_result_complete (async);
1031 g_object_unref (async);
1035 collection_properties_new (const gchar *label)
1037 GHashTable *properties;
1040 properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
1041 (GDestroyNotify)g_variant_unref);
1042 value = g_variant_new_string (label);
1043 g_hash_table_insert (properties,
1044 SECRET_COLLECTION_INTERFACE ".Label",
1045 g_variant_ref_sink (value));
1051 * secret_collection_create:
1052 * @service: (allow-none): a secret service object
1053 * @label: label for the new collection
1054 * @alias: (allow-none): alias to assign to the collection
1055 * @flags: currently unused
1056 * @cancellable: optional cancellation object
1057 * @callback: called when the operation completes
1058 * @user_data: data to pass to the callback
1060 * Create a new collection in the secret service.
1062 * This method returns immediately and completes asynchronously. The secret
1063 * service may prompt the user. secret_service_prompt() will be used to handle
1064 * any prompts that are required.
1066 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1067 * default collection to store items in). This allows other applications to
1068 * easily identify and share a collection. If you specify an @alias, and a
1069 * collection with that alias already exists, then a new collection will not
1070 * be created. The previous one will be returned instead.
1072 * If @service is NULL, then secret_service_get() will be called to get
1073 * the default #SecretService proxy.
1077 secret_collection_create (SecretService *service,
1080 SecretCollectionCreateFlags flags,
1081 GCancellable *cancellable,
1082 GAsyncReadyCallback callback,
1085 GSimpleAsyncResult *res;
1086 CreateClosure *closure;
1088 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
1089 g_return_if_fail (label != NULL);
1090 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1092 res = g_simple_async_result_new (NULL, callback, user_data,
1093 secret_collection_create);
1094 closure = g_slice_new0 (CreateClosure);
1095 closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1096 closure->properties = collection_properties_new (label);
1097 closure->alias = g_strdup (alias);
1098 closure->flags = flags;
1099 g_simple_async_result_set_op_res_gpointer (res, closure, create_closure_free);
1101 if (service == NULL) {
1102 secret_service_get (SECRET_SERVICE_NONE, cancellable,
1103 on_create_service, g_object_ref (res));
1106 secret_service_create_collection_dbus_path (service, closure->properties,
1107 closure->alias, closure->flags,
1108 closure->cancellable,
1109 on_create_path, g_object_ref (res));
1112 g_object_unref (res);
1116 * secret_collection_create_finish:
1117 * @result: the asynchronous result passed to the callback
1118 * @error: location to place an error on failure
1120 * Finish operation to create a new collection in the secret service.
1122 * Returns: (transfer full): the new collection, which should be unreferenced
1123 * with g_object_unref()
1126 secret_collection_create_finish (GAsyncResult *result,
1129 GSimpleAsyncResult *res;
1130 CreateClosure *closure;
1132 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
1133 secret_collection_create), NULL);
1134 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1136 res = G_SIMPLE_ASYNC_RESULT (result);
1138 if (g_simple_async_result_propagate_error (res, error))
1141 closure = g_simple_async_result_get_op_res_gpointer (res);
1142 if (closure->collection == NULL)
1145 return g_object_ref (closure->collection);
1149 * secret_collection_create_sync:
1150 * @service: (allow-none): a secret service object
1151 * @label: label for the new collection
1152 * @alias: (allow-none): alias to assign to the collection
1153 * @flags: currently unused
1154 * @cancellable: optional cancellation object
1155 * @error: location to place an error on failure
1157 * Create a new collection in the secret service.
1159 * This method may block indefinitely and should not be used in user interface
1160 * threads. The secret service may prompt the user. secret_service_prompt()
1161 * will be used to handle any prompts that are required.
1163 * An @alias is a well-known tag for a collection, such as 'default' (ie: the
1164 * default collection to store items in). This allows other applications to
1165 * easily identify and share a collection. If you specify an @alias, and a
1166 * collection with that alias already exists, then a new collection will not
1167 * be created. The previous one will be returned instead.
1169 * If @service is NULL, then secret_service_get_sync() will be called to get
1170 * the default #SecretService proxy.
1172 * Returns: (transfer full): the new collection, which should be unreferenced
1173 * with g_object_unref()
1176 secret_collection_create_sync (SecretService *service,
1179 SecretCollectionCreateFlags flags,
1180 GCancellable *cancellable,
1183 SecretCollection *collection;
1184 GHashTable *properties;
1187 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
1188 g_return_val_if_fail (label != NULL, NULL);
1189 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1190 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1192 if (service == NULL) {
1193 service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
1194 if (service == NULL)
1197 g_object_ref (service);
1200 properties = collection_properties_new (label);
1202 path = secret_service_create_collection_dbus_path_sync (service, properties, alias,
1203 flags, cancellable, error);
1205 g_hash_table_unref (properties);
1208 g_object_unref (service);
1212 collection = secret_collection_new_for_dbus_path_sync (service, path,
1213 SECRET_COLLECTION_LOAD_ITEMS,
1214 cancellable, error);
1216 g_object_unref (service);
1223 SecretCollection *collection;
1224 GCancellable *cancellable;
1228 SecretSearchFlags flags;
1232 search_closure_free (gpointer data)
1234 SearchClosure *closure = data;
1235 g_object_unref (closure->collection);
1236 g_clear_object (&closure->cancellable);
1237 g_hash_table_unref (closure->items);
1238 g_strfreev (closure->paths);
1239 g_slice_free (SearchClosure, closure);
1243 search_closure_take_item (SearchClosure *closure,
1246 const gchar *path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
1247 g_hash_table_insert (closure->items, (gpointer)path, item);
1251 on_search_secrets (GObject *source,
1252 GAsyncResult *result,
1255 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1257 /* Note that we ignore any unlock failure */
1258 secret_item_load_secrets_finish (result, NULL);
1260 g_simple_async_result_complete (async);
1261 g_object_unref (async);
1265 on_search_unlocked (GObject *source,
1266 GAsyncResult *result,
1269 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1270 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1273 /* Note that we ignore any unlock failure */
1274 secret_service_unlock_finish (SECRET_SERVICE (source), result, NULL, NULL);
1276 /* If loading secrets ... locked items automatically ignored */
1277 if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1278 items = g_hash_table_get_values (search->items);
1279 secret_item_load_secrets (items, search->cancellable,
1280 on_search_secrets, g_object_ref (async));
1281 g_list_free (items);
1283 /* No additional options, just complete */
1285 g_simple_async_result_complete (async);
1288 g_object_unref (async);
1292 secret_search_unlock_load_or_complete (GSimpleAsyncResult *async,
1293 SearchClosure *search)
1297 /* If unlocking then unlock all the locked items */
1298 if (search->flags & SECRET_SEARCH_UNLOCK) {
1299 items = g_hash_table_get_values (search->items);
1300 secret_service_unlock (secret_collection_get_service (search->collection),
1301 items, search->cancellable,
1302 on_search_unlocked, g_object_ref (async));
1303 g_list_free (items);
1305 /* If loading secrets ... locked items automatically ignored */
1306 } else if (search->flags & SECRET_SEARCH_LOAD_SECRETS) {
1307 items = g_hash_table_get_values (search->items);
1308 secret_item_load_secrets (items, search->cancellable,
1309 on_search_secrets, g_object_ref (async));
1310 g_list_free (items);
1312 /* No additional options, just complete */
1314 g_simple_async_result_complete (async);
1319 on_search_loaded (GObject *source,
1320 GAsyncResult *result,
1323 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1324 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1325 GError *error = NULL;
1330 item = secret_item_new_for_dbus_path_finish (result, &error);
1332 g_simple_async_result_take_error (async, error);
1335 search_closure_take_item (search, item);
1337 /* We're done loading, lets go to the next step */
1338 if (search->loading == 0)
1339 secret_search_unlock_load_or_complete (async, search);
1341 g_object_unref (async);
1345 on_search_paths (GObject *source,
1346 GAsyncResult *result,
1349 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1350 SearchClosure *search = g_simple_async_result_get_op_res_gpointer (async);
1351 SecretCollection *self = search->collection;
1352 SecretService *service = secret_collection_get_service (self);
1353 GError *error = NULL;
1358 search->paths = secret_collection_search_for_dbus_paths_finish (self, result, &error);
1359 if (error == NULL) {
1361 if (search->flags & SECRET_SEARCH_ALL)
1364 for (i = 0; i < want && search->paths[i] != NULL; i++) {
1365 item = _secret_collection_find_item_instance (self, search->paths[i]);
1367 secret_item_new_for_dbus_path (service, search->paths[i], SECRET_ITEM_NONE,
1368 search->cancellable, on_search_loaded,
1369 g_object_ref (async));
1372 search_closure_take_item (search, item);
1377 /* No items loading, complete operation now */
1378 if (search->loading == 0)
1379 secret_search_unlock_load_or_complete (async, search);
1382 g_simple_async_result_take_error (async, error);
1383 g_simple_async_result_complete (async);
1386 g_object_unref (async);
1390 * secret_collection_search:
1391 * @self: a secret collection
1392 * @schema: (allow-none): the schema for the attributes
1393 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1394 * @flags: search option flags
1395 * @cancellable: optional cancellation object
1396 * @callback: called when the operation completes
1397 * @user_data: data to pass to the callback
1399 * Search for items matching the @attributes in the @collection.
1400 * The @attributes should be a table of string keys and string values.
1402 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1403 * search will be returned. Otherwise only the first item will be returned.
1404 * This is almost always the unlocked item that was most recently stored.
1406 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1407 * if necessary. In either case, locked and unlocked items will match the
1408 * search and be returned. If the unlock fails, the search does not fail.
1410 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1411 * their secret values loaded and available via secret_item_get_secret().
1413 * This function returns immediately and completes asynchronously.
1416 secret_collection_search (SecretCollection *self,
1417 const SecretSchema *schema,
1418 GHashTable *attributes,
1419 SecretSearchFlags flags,
1420 GCancellable *cancellable,
1421 GAsyncReadyCallback callback,
1424 GSimpleAsyncResult *async;
1425 SearchClosure *search;
1427 g_return_if_fail (SECRET_IS_COLLECTION (self));
1428 g_return_if_fail (attributes != NULL);
1429 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1431 /* Warnings raised already */
1432 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1435 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1436 secret_collection_search);
1437 search = g_slice_new0 (SearchClosure);
1438 search->collection = g_object_ref (self);
1439 search->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1440 search->items = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
1441 search->flags = flags;
1442 g_simple_async_result_set_op_res_gpointer (async, search, search_closure_free);
1444 secret_collection_search_for_dbus_paths (self, schema, attributes,
1445 cancellable, on_search_paths,
1446 g_object_ref (async));
1448 g_object_unref (async);
1452 * secret_collection_search_finish:
1453 * @self: the secret collection
1454 * @result: asynchronous result passed to callback
1455 * @error: location to place error on failure
1457 * Complete asynchronous operation to search for items in a collection.
1459 * Returns: (transfer full) (element-type Secret.Item):
1460 * a list of items that matched the search
1463 secret_collection_search_finish (SecretCollection *self,
1464 GAsyncResult *result,
1467 GSimpleAsyncResult *async;
1468 SearchClosure *search;
1469 GList *items = NULL;
1473 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1474 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1475 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1476 secret_collection_search), NULL);
1478 async = G_SIMPLE_ASYNC_RESULT (result);
1479 if (g_simple_async_result_propagate_error (async, error))
1482 search = g_simple_async_result_get_op_res_gpointer (async);
1484 for (i = 0; search->paths[i]; i++) {
1485 item = g_hash_table_lookup (search->items, search->paths[i]);
1487 items = g_list_prepend (items, g_object_ref (item));
1490 return g_list_reverse (items);
1494 collection_load_items_sync (SecretCollection *self,
1495 GCancellable *cancellable,
1501 SecretService *service = secret_collection_get_service (self);
1506 for (i = 0; have < want && paths[i] != NULL; i++) {
1507 item = _secret_collection_find_item_instance (self, paths[i]);
1509 item = secret_item_new_for_dbus_path_sync (service, paths[i], SECRET_ITEM_NONE,
1510 cancellable, error);
1515 *items = g_list_prepend (*items, item);
1524 * secret_collection_search_sync:
1525 * @self: a secret collection
1526 * @schema: (allow-none): the schema for the attributes
1527 * @attributes: (element-type utf8 utf8): search for items matching these attributes
1528 * @flags: search option flags
1529 * @cancellable: optional cancellation object
1530 * @error: location to place error on failure
1532 * Search for items matching the @attributes in the @collection.
1533 * The @attributes should be a table of string keys and string values.
1535 * If %SECRET_SEARCH_ALL is set in @flags, then all the items matching the
1536 * search will be returned. Otherwise only the first item will be returned.
1537 * This is almost always the unlocked item that was most recently stored.
1539 * If %SECRET_SEARCH_UNLOCK is set in @flags, then items will be unlocked
1540 * if necessary. In either case, locked and unlocked items will match the
1541 * search and be returned. If the unlock fails, the search does not fail.
1543 * If %SECRET_SEARCH_LOAD_SECRETS is set in @flags, then the items will have
1544 * their secret values loaded and available via secret_item_get_secret().
1546 * This function may block indefinetely. Use the asynchronous version
1547 * in user interface threads.
1549 * Returns: (transfer full) (element-type Secret.Item):
1550 * a list of items that matched the search
1553 secret_collection_search_sync (SecretCollection *self,
1554 const SecretSchema *schema,
1555 GHashTable *attributes,
1556 SecretSearchFlags flags,
1557 GCancellable *cancellable,
1560 gchar **paths = NULL;
1561 GList *items = NULL;
1565 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1566 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
1567 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1569 /* Warnings raised already */
1570 if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
1573 paths = secret_collection_search_for_dbus_paths_sync (self, schema, attributes,
1574 cancellable, error);
1581 if (flags & SECRET_SEARCH_ALL)
1584 ret = collection_load_items_sync (self, cancellable, paths,
1585 &items, want, error);
1592 if (flags & SECRET_SEARCH_UNLOCK) {
1593 secret_service_unlock_sync (secret_collection_get_service (self),
1594 items, cancellable, NULL, NULL);
1597 if (flags & SECRET_SEARCH_LOAD_SECRETS)
1598 secret_item_load_secrets_sync (items, NULL, NULL);
1604 on_service_delete_path (GObject *source,
1605 GAsyncResult *result,
1608 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
1609 GError *error = NULL;
1611 _secret_service_delete_path_finish (SECRET_SERVICE (source), result, &error);
1613 g_simple_async_result_take_error (async, error);
1614 g_simple_async_result_complete (async);
1615 g_object_unref (async);
1618 * secret_collection_delete:
1619 * @self: a collection
1620 * @cancellable: optional cancellation object
1621 * @callback: called when the operation completes
1622 * @user_data: data to pass to the callback
1624 * Delete this collection.
1626 * This method returns immediately and completes asynchronously. The secret
1627 * service may prompt the user. secret_service_prompt() will be used to handle
1628 * any prompts that show up.
1631 secret_collection_delete (SecretCollection *self,
1632 GCancellable *cancellable,
1633 GAsyncReadyCallback callback,
1636 GSimpleAsyncResult *async;
1637 const gchar *object_path;
1639 g_return_if_fail (SECRET_IS_COLLECTION (self));
1640 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1642 async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
1643 secret_collection_delete);
1645 object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
1646 _secret_service_delete_path (self->pv->service, object_path, FALSE,
1647 cancellable, on_service_delete_path,
1648 g_object_ref (async));
1650 g_object_unref (async);
1654 * secret_collection_delete_finish:
1655 * @self: a collection
1656 * @result: asynchronous result passed to the callback
1657 * @error: location to place an error on failure
1659 * Complete operation to delete this collection.
1661 * Returns: whether the collection was successfully deleted or not
1664 secret_collection_delete_finish (SecretCollection *self,
1665 GAsyncResult *result,
1668 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1669 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1670 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
1671 secret_collection_delete), FALSE);
1673 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
1680 * secret_collection_delete_sync:
1681 * @self: a collection
1682 * @cancellable: optional cancellation object
1683 * @error: location to place an error on failure
1685 * Delete this collection.
1687 * This method may block indefinitely and should not be used in user
1688 * interface threads. The secret service may prompt the user.
1689 * secret_service_prompt() will be used to handle any prompts that show up.
1691 * Returns: whether the collection was successfully deleted or not
1694 secret_collection_delete_sync (SecretCollection *self,
1695 GCancellable *cancellable,
1701 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1702 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1703 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1705 sync = _secret_sync_new ();
1706 g_main_context_push_thread_default (sync->context);
1708 secret_collection_delete (self, cancellable, _secret_sync_on_result, sync);
1710 g_main_loop_run (sync->loop);
1712 ret = secret_collection_delete_finish (self, sync->result, error);
1714 g_main_context_pop_thread_default (sync->context);
1715 _secret_sync_free (sync);
1721 * secret_collection_get_service:
1722 * @self: a collection
1724 * Get the Secret Service object that this collection was created with.
1726 * Returns: (transfer none): the Secret Service object
1729 secret_collection_get_service (SecretCollection *self)
1731 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1732 return self->pv->service;
1736 * secret_collection_get_flags:
1737 * @self: the secret collection proxy
1739 * Get the flags representing what features of the #SecretCollection proxy
1740 * have been initialized.
1742 * Use secret_collection_load_items() to initialize further features
1743 * and change the flags.
1745 * Returns: the flags for features initialized
1747 SecretCollectionFlags
1748 secret_collection_get_flags (SecretCollection *self)
1750 SecretCollectionFlags flags = 0;
1752 g_return_val_if_fail (SECRET_IS_COLLECTION (self), SECRET_COLLECTION_NONE);
1754 g_mutex_lock (&self->pv->mutex);
1756 if (self->pv->items)
1757 flags |= SECRET_COLLECTION_LOAD_ITEMS;
1759 g_mutex_unlock (&self->pv->mutex);
1765 * secret_collection_get_items:
1766 * @self: a collection
1768 * Get the list of items in this collection.
1770 * Returns: (transfer full) (element-type Secret.Item): a list of items,
1771 * when done, the list should be freed with g_list_free, and each item should
1772 * be released with g_object_unref()
1775 secret_collection_get_items (SecretCollection *self)
1779 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1781 g_mutex_lock (&self->pv->mutex);
1782 items = g_hash_table_get_values (self->pv->items);
1783 for (l = items; l != NULL; l = g_list_next (l))
1784 g_object_ref (l->data);
1785 g_mutex_unlock (&self->pv->mutex);
1791 _secret_collection_find_item_instance (SecretCollection *self,
1792 const gchar *item_path)
1796 g_mutex_lock (&self->pv->mutex);
1797 item = g_hash_table_lookup (self->pv->items, item_path);
1799 g_object_ref (item);
1800 g_mutex_unlock (&self->pv->mutex);
1806 * secret_collection_get_label:
1807 * @self: a collection
1809 * Get the label of this collection.
1811 * Returns: (transfer full): the label, which should be freed with g_free()
1814 secret_collection_get_label (SecretCollection *self)
1819 g_return_val_if_fail (SECRET_IS_COLLECTION (self), NULL);
1821 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Label");
1822 g_return_val_if_fail (variant != NULL, NULL);
1824 label = g_variant_dup_string (variant, NULL);
1825 g_variant_unref (variant);
1831 * secret_collection_set_label:
1832 * @self: a collection
1833 * @label: a new label
1834 * @cancellable: optional cancellation object
1835 * @callback: called when the operation completes
1836 * @user_data: data to pass to the callback
1838 * Set the label of this collection.
1840 * This function returns immediately and completes asynchronously.
1843 secret_collection_set_label (SecretCollection *self,
1845 GCancellable *cancellable,
1846 GAsyncReadyCallback callback,
1849 g_return_if_fail (SECRET_IS_COLLECTION (self));
1850 g_return_if_fail (label != NULL);
1852 _secret_util_set_property (G_DBUS_PROXY (self), "Label",
1853 g_variant_new_string (label),
1854 secret_collection_set_label,
1855 cancellable, callback, user_data);
1859 * secret_collection_set_label_finish:
1860 * @self: a collection
1861 * @result: asynchronous result passed to callback
1862 * @error: location to place error on failure
1864 * Complete asynchronous operation to set the label of this collection.
1866 * Returns: whether the change was successful or not
1869 secret_collection_set_label_finish (SecretCollection *self,
1870 GAsyncResult *result,
1873 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1875 return _secret_util_set_property_finish (G_DBUS_PROXY (self),
1876 secret_collection_set_label,
1881 * secret_collection_set_label_sync:
1882 * @self: a collection
1883 * @label: a new label
1884 * @cancellable: optional cancellation object
1885 * @error: location to place error on failure
1887 * Set the label of this collection.
1889 * This function may block indefinetely. Use the asynchronous version
1890 * in user interface threads.
1892 * Returns: whether the change was successful or not
1895 secret_collection_set_label_sync (SecretCollection *self,
1897 GCancellable *cancellable,
1900 g_return_val_if_fail (SECRET_IS_COLLECTION (self), FALSE);
1901 g_return_val_if_fail (label != NULL, FALSE);
1903 return _secret_util_set_property_sync (G_DBUS_PROXY (self), "Label",
1904 g_variant_new_string (label),
1905 cancellable, error);
1909 * secret_collection_get_locked:
1910 * @self: a collection
1912 * Get whether the collection is locked or not.
1914 * Use secret_service_lock() or secret_service_unlock() to lock or unlock the
1917 * Returns: whether the collection is locked or not
1920 secret_collection_get_locked (SecretCollection *self)
1925 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1927 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Locked");
1928 g_return_val_if_fail (variant != NULL, TRUE);
1930 locked = g_variant_get_boolean (variant);
1931 g_variant_unref (variant);
1937 * secret_collection_get_created:
1938 * @self: a collection
1940 * Get the created date and time of the collection. The return value is
1941 * the number of seconds since the unix epoch, January 1st 1970.
1943 * Returns: the created date and time
1946 secret_collection_get_created (SecretCollection *self)
1951 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1953 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Created");
1954 g_return_val_if_fail (variant != NULL, 0);
1956 created = g_variant_get_uint64 (variant);
1957 g_variant_unref (variant);
1963 * secret_collection_get_modified:
1964 * @self: a collection
1966 * Get the modified date and time of the collection. The return value is
1967 * the number of seconds since the unix epoch, January 1st 1970.
1969 * Returns: the modified date and time
1972 secret_collection_get_modified (SecretCollection *self)
1977 g_return_val_if_fail (SECRET_IS_COLLECTION (self), TRUE);
1979 variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Modified");
1980 g_return_val_if_fail (variant != NULL, 0);
1982 modified = g_variant_get_uint64 (variant);
1983 g_variant_unref (variant);
1990 GCancellable *cancellable;
1992 SecretCollection *collection;
1996 read_closure_free (gpointer data)
1998 ReadClosure *read = data;
1999 g_free (read->alias);
2000 if (read->collection)
2001 g_object_unref (read->collection);
2002 if (read->cancellable)
2003 g_object_unref (read->cancellable);
2004 g_slice_free (ReadClosure, read);
2008 on_read_alias_collection (GObject *source,
2009 GAsyncResult *result,
2012 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2013 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2014 GError *error = NULL;
2016 read->collection = secret_collection_new_for_dbus_path_finish (result, &error);
2018 g_simple_async_result_take_error (async, error);
2020 g_simple_async_result_complete (async);
2021 g_object_unref (async);
2025 on_read_alias_path (GObject *source,
2026 GAsyncResult *result,
2029 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2030 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2031 SecretService *self = SECRET_SERVICE (source);
2032 GError *error = NULL;
2033 gchar *collection_path;
2035 collection_path = secret_service_read_alias_dbus_path_finish (self, result, &error);
2036 if (error == NULL) {
2038 /* No collection for this alias */
2039 if (collection_path == NULL) {
2040 g_simple_async_result_complete (async);
2043 read->collection = _secret_service_find_collection_instance (self,
2045 if (read->collection != NULL) {
2046 g_simple_async_result_complete (async);
2048 /* No collection loaded, but valid path, load */
2050 secret_collection_new_for_dbus_path (self, collection_path,
2051 SECRET_COLLECTION_NONE,
2053 on_read_alias_collection,
2054 g_object_ref (async));
2059 g_simple_async_result_take_error (async, error);
2060 g_simple_async_result_complete (async);
2063 g_free (collection_path);
2064 g_object_unref (async);
2068 on_read_alias_service (GObject *source,
2069 GAsyncResult *result,
2072 GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
2073 ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
2074 SecretService *service;
2075 GError *error = NULL;
2077 service = secret_service_get_finish (result, &error);
2078 if (error == NULL) {
2079 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2080 on_read_alias_path, g_object_ref (async));
2081 g_object_unref (service);
2084 g_simple_async_result_take_error (async, error);
2085 g_simple_async_result_complete (async);
2088 g_object_unref (async);
2092 * secret_collection_for_alias:
2093 * @service: (allow-none): a secret service object
2094 * @alias: the alias to lookup
2095 * @cancellable: (allow-none): optional cancellation object
2096 * @callback: called when the operation completes
2097 * @user_data: data to pass to the callback
2099 * Lookup which collection is assigned to this alias. Aliases help determine
2100 * well known collections, such as 'default'.
2102 * If @service is NULL, then secret_service_get() will be called to get
2103 * the default #SecretService proxy.
2105 * This method will return immediately and complete asynchronously.
2108 secret_collection_for_alias (SecretService *service,
2110 GCancellable *cancellable,
2111 GAsyncReadyCallback callback,
2114 GSimpleAsyncResult *async;
2117 g_return_if_fail (service == NULL || SECRET_IS_SERVICE (service));
2118 g_return_if_fail (alias != NULL);
2119 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2121 async = g_simple_async_result_new (NULL, callback, user_data,
2122 secret_collection_for_alias);
2123 read = g_slice_new0 (ReadClosure);
2124 read->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
2125 read->alias = g_strdup (alias);
2126 g_simple_async_result_set_op_res_gpointer (async, read, read_closure_free);
2128 if (service == NULL) {
2129 secret_service_get (SECRET_SERVICE_NONE, cancellable,
2130 on_read_alias_service, g_object_ref (async));
2132 secret_service_read_alias_dbus_path (service, read->alias, read->cancellable,
2133 on_read_alias_path, g_object_ref (async));
2136 g_object_unref (async);
2140 * secret_collection_for_alias_finish:
2141 * @result: asynchronous result passed to callback
2142 * @error: location to place error on failure
2144 * Finish an asynchronous operation to lookup which collection is assigned
2147 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2150 secret_collection_for_alias_finish (GAsyncResult *result,
2153 GSimpleAsyncResult *async;
2156 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
2157 secret_collection_for_alias), NULL);
2158 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2160 async = G_SIMPLE_ASYNC_RESULT (result);
2161 if (g_simple_async_result_propagate_error (async, error))
2163 read = g_simple_async_result_get_op_res_gpointer (async);
2164 if (read->collection)
2165 g_object_ref (read->collection);
2166 return read->collection;
2170 * secret_collection_for_alias_sync:
2171 * @service: (allow-none): a secret service object
2172 * @alias: the alias to lookup
2173 * @cancellable: (allow-none): optional cancellation object
2174 * @error: location to place error on failure
2176 * Lookup which collection is assigned to this alias. Aliases help determine
2177 * well known collections, such as 'default'.
2179 * If @service is NULL, then secret_service_get_sync() will be called to get
2180 * the default #SecretService proxy.
2182 * This method may block and should not be used in user interface threads.
2184 * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
2187 secret_collection_for_alias_sync (SecretService *service,
2189 GCancellable *cancellable,
2192 SecretCollection *collection;
2193 gchar *collection_path;
2195 g_return_val_if_fail (service == NULL || SECRET_IS_SERVICE (service), NULL);
2196 g_return_val_if_fail (alias != NULL, NULL);
2197 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2198 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2200 collection_path = secret_service_read_alias_dbus_path_sync (service, alias,
2201 cancellable, error);
2202 if (collection_path == NULL)
2205 /* No collection for this alias */
2206 if (collection_path == NULL) {
2210 collection = _secret_service_find_collection_instance (service,
2213 /* No collection loaded, but valid path, load */
2214 if (collection == NULL) {
2215 collection = secret_collection_new_for_dbus_path_sync (service, collection_path,
2216 SECRET_COLLECTION_LOAD_ITEMS,
2217 cancellable, error);
2221 g_free (collection_path);