From: Stef Walter Date: Wed, 13 Feb 2013 16:32:54 +0000 (+0100) Subject: Try to unlock locked collection when storing an item X-Git-Tag: upstream/0.14~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0e9870bd357814e8183a2ca59248b29359e9a271;p=platform%2Fupstream%2Flibsecret.git 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 --- 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);