[libsecret] Try to unlock locked collection when storing an item



commit 0e9870bd357814e8183a2ca59248b29359e9a271
Author: Stef Walter <stefw gnome org>
Date:   Wed Feb 13 17:32:54 2013 +0100

    Try to unlock locked collection when storing an item
    
    And add tests to verify this behavior.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=693723

 libsecret/secret-methods.c      |   32 +++++++++++++++++++
 libsecret/tests/mock/service.py |    2 +
 libsecret/tests/test-password.c |   66 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 0 deletions(-)
---
diff --git a/libsecret/secret-methods.c b/libsecret/secret-methods.c
index 1e55ce3..23ee9fa 100644
--- a/libsecret/secret-methods.c
+++ b/libsecret/secret-methods.c
@@ -958,6 +958,7 @@ typedef struct {
        SecretValue *value;
        GHashTable *properties;
        gboolean created_collection;
+       gboolean unlocked_collection;
 } StoreClosure;
 
 static void
@@ -1005,6 +1006,31 @@ on_store_keyring (GObject *source,
 }
 
 static void
+on_store_unlock (GObject *source,
+                 GAsyncResult *result,
+                 gpointer user_data)
+{
+       GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
+       StoreClosure *store = g_simple_async_result_get_op_res_gpointer (async);
+       SecretService *service = SECRET_SERVICE (source);
+       GError *error = NULL;
+
+       secret_service_unlock_dbus_paths_finish (service, result, NULL, &error);
+       if (error == NULL) {
+               store->unlocked_collection = TRUE;
+               secret_service_create_item_dbus_path (service, store->collection_path,
+                                                     store->properties, store->value,
+                                                     SECRET_ITEM_CREATE_REPLACE, store->cancellable,
+                                                     on_store_create, g_object_ref (async));
+       } else {
+               g_simple_async_result_take_error (async, error);
+               g_simple_async_result_complete (async);
+       }
+
+       g_object_unref (async);
+}
+
+static void
 on_store_create (GObject *source,
                  GAsyncResult *result,
                  gpointer user_data)
@@ -1033,6 +1059,12 @@ on_store_create (GObject *source,
                g_hash_table_unref (properties);
                g_error_free (error);
 
+       } else if (!store->unlocked_collection &&
+                  g_error_matches (error, SECRET_ERROR, SECRET_ERROR_IS_LOCKED)) {
+               const gchar *paths[2] = { store->collection_path, NULL };
+               secret_service_unlock_dbus_paths (service, paths, store->cancellable,
+                                                 on_store_unlock, g_object_ref (async));
+               g_error_free (error);
        } else {
                if (error != NULL)
                        g_simple_async_result_take_error (async, error);
diff --git a/libsecret/tests/mock/service.py b/libsecret/tests/mock/service.py
index 2d6b580..14661a1 100644
--- a/libsecret/tests/mock/service.py
+++ b/libsecret/tests/mock/service.py
@@ -392,6 +392,8 @@ class SecretCollection(dbus.service.Object):
                session = objects.get(session_path, None)
                if not session or session.sender != sender:
                        raise InvalidArgs("session invalid: %s" % session_path)
+               if self.locked:
+                       raise IsLocked("collection is locked: %s" % self.path)
 
                attributes = properties.get("org.freedesktop.Secret.Item.Attributes", { })
                label = properties.get("org.freedesktop.Secret.Item.Label", None)
diff --git a/libsecret/tests/test-password.c b/libsecret/tests/test-password.c
index 65323a6..e379283 100644
--- a/libsecret/tests/test-password.c
+++ b/libsecret/tests/test-password.c
@@ -225,6 +225,71 @@ test_store_async (Test *test,
 }
 
 static void
+test_store_unlock (Test *test,
+                   gconstpointer unused)
+{
+       const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
+       GAsyncResult *result = NULL;
+       SecretCollection *collection;
+       SecretService *service;
+       GError *error = NULL;
+       gchar *password;
+       gboolean ret;
+       GList *objects;
+       gint count;
+
+       service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
+       g_assert_no_error (error);
+
+       /* Check collection state */
+       collection = secret_collection_new_for_dbus_path_sync (service, collection_path,
+                                                              SECRET_COLLECTION_NONE, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (secret_collection_get_locked (collection) == FALSE);
+
+       /* Lock it, use async, so collection properties update */
+       objects = g_list_append (NULL, collection);
+       secret_service_lock (service, objects, NULL, on_complete_get_result, &result);
+       egg_test_wait ();
+       count = secret_service_lock_finish (service, result, NULL, &error);
+       g_assert_cmpint (count, ==, 1);
+       g_clear_object (&result);
+       g_list_free (objects);
+
+       /* Check collection state */
+       g_assert (secret_collection_get_locked (collection) == TRUE);
+
+       /* Store the password, use async so collection properties update */
+       secret_password_store (&MOCK_SCHEMA, collection_path, "Label here",
+                              "the password", NULL, on_complete_get_result, &result,
+                              "even", TRUE,
+                              "string", "twelve",
+                              "number", 12,
+                              NULL);
+       g_assert (result == NULL);
+       egg_test_wait ();
+       ret = secret_password_store_finish (result, &error);
+       g_assert_no_error (error);
+       g_assert (ret == TRUE);
+       g_clear_object (&result);
+
+       /* Check collection state */
+       g_assert (secret_collection_get_locked (collection) == FALSE);
+
+
+       password = secret_password_lookup_nonpageable_sync (&MOCK_SCHEMA, NULL, &error,
+                                                           "string", "twelve",
+                                                           NULL);
+
+       g_assert_no_error (error);
+       g_assert_cmpstr (password, ==, "the password");
+
+       secret_password_free (password);
+       g_object_unref (collection);
+       g_object_unref (service);
+}
+
+static void
 test_delete_sync (Test *test,
                   gconstpointer used)
 {
@@ -320,6 +385,7 @@ main (int argc, char **argv)
 
        g_test_add ("/password/store-sync", Test, "mock-service-normal.py", setup, test_store_sync, teardown);
        g_test_add ("/password/store-async", Test, "mock-service-normal.py", setup, test_store_async, 
teardown);
+       g_test_add ("/password/store-unlock", Test, "mock-service-normal.py", setup, test_store_unlock, 
teardown);
 
        g_test_add ("/password/delete-sync", Test, "mock-service-delete.py", setup, test_delete_sync, 
teardown);
        g_test_add ("/password/delete-async", Test, "mock-service-delete.py", setup, test_delete_async, 
teardown);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]