[libsecret] Separate path based functionality



commit f962662b09ffe9654ab22ce4d2133b3771c552ac
Author: Stef Walter <stefw gnome org>
Date:   Thu Jul 5 16:41:28 2012 +0200

    Separate path based functionality
    
     * Move the dbus object path based functionality into its
       own file and own section of the documentation.

 docs/reference/libsecret/libsecret-docs.sgml    |    1 +
 docs/reference/libsecret/libsecret-sections.txt |   69 +-
 library/Makefile.am                             |    2 +
 library/secret-collection.c                     |    1 +
 library/secret-item.c                           |    1 +
 library/secret-methods.c                        | 2159 +++--------------------
 library/secret-paths.c                          | 2054 +++++++++++++++++++++
 library/secret-paths.h                          |  219 +++
 library/secret-private.h                        |    6 +
 library/secret-service.c                        |   87 +-
 library/secret-service.h                        |  185 --
 library/secret-unstable.h                       |    1 +
 library/tests/Makefile.am                       |    1 +
 library/tests/test-methods.c                    |  614 +-------
 library/tests/test-paths.c                      |  743 ++++++++
 15 files changed, 3295 insertions(+), 2848 deletions(-)
---
diff --git a/docs/reference/libsecret/libsecret-docs.sgml b/docs/reference/libsecret/libsecret-docs.sgml
index 3ec04c1..c7b168a 100644
--- a/docs/reference/libsecret/libsecret-docs.sgml
+++ b/docs/reference/libsecret/libsecret-docs.sgml
@@ -30,6 +30,7 @@
 		<xi:include href="xml/secret-attributes.xml"/>
 		<xi:include href="xml/secret-prompt.xml"/>
 		<xi:include href="xml/secret-error.xml"/>
+		<xi:include href="xml/secret-paths.xml"/>
 	</part>
 
 	<xi:include href="xml/annotation-glossary.xml">
diff --git a/docs/reference/libsecret/libsecret-sections.txt b/docs/reference/libsecret/libsecret-sections.txt
index 1168fea..1a53da5 100644
--- a/docs/reference/libsecret/libsecret-sections.txt
+++ b/docs/reference/libsecret/libsecret-sections.txt
@@ -186,30 +186,15 @@ secret_service_ensure_collections_sync
 secret_service_search
 secret_service_search_finish
 secret_service_search_sync
-secret_service_search_for_paths
-secret_service_search_for_paths_finish
-secret_service_search_for_paths_sync
 secret_service_get_secrets
 secret_service_get_secrets_finish
 secret_service_get_secrets_sync
-secret_service_get_secrets_for_paths
-secret_service_get_secrets_for_paths_finish
-secret_service_get_secrets_for_paths_sync
-secret_service_get_secret_for_path
-secret_service_get_secret_for_path_finish
-secret_service_get_secret_for_path_sync
 secret_service_lock
 secret_service_lock_finish
 secret_service_lock_sync
-secret_service_lock_paths
-secret_service_lock_paths_finish
-secret_service_lock_paths_sync
 secret_service_unlock
 secret_service_unlock_finish
 secret_service_unlock_sync
-secret_service_unlock_paths
-secret_service_unlock_paths_finish
-secret_service_unlock_paths_sync
 secret_service_store
 secret_service_store_finish
 secret_service_store_sync
@@ -222,6 +207,43 @@ secret_service_remove_sync
 secret_service_prompt
 secret_service_prompt_finish
 secret_service_prompt_sync
+secret_service_read_alias
+secret_service_read_alias_finish
+secret_service_read_alias_sync
+secret_service_set_alias
+secret_service_set_alias_finish
+secret_service_set_alias_sync
+<SUBSECTION Standard>
+SECRET_IS_SERVICE
+SECRET_IS_SERVICE_CLASS
+SECRET_SERVICE
+SECRET_SERVICE_CLASS
+SECRET_SERVICE_GET_CLASS
+SECRET_TYPE_SERVICE
+SECRET_TYPE_SERVICE_FLAGS
+SecretServicePrivate
+secret_service_flags_get_type
+secret_service_get_type
+</SECTION>
+
+<SECTION>
+<FILE>secret-paths</FILE>
+<INCLUDE>secret/secret-unstable.h</INCLUDE>
+secret_service_search_for_paths
+secret_service_search_for_paths_finish
+secret_service_search_for_paths_sync
+secret_service_get_secrets_for_paths
+secret_service_get_secrets_for_paths_finish
+secret_service_get_secrets_for_paths_sync
+secret_service_get_secret_for_path
+secret_service_get_secret_for_path_finish
+secret_service_get_secret_for_path_sync
+secret_service_lock_paths
+secret_service_lock_paths_finish
+secret_service_lock_paths_sync
+secret_service_unlock_paths
+secret_service_unlock_paths_finish
+secret_service_unlock_paths_sync
 secret_service_prompt_path
 secret_service_prompt_path_finish
 secret_service_prompt_path_sync
@@ -234,29 +256,12 @@ secret_service_create_item_path_sync
 secret_service_delete_path
 secret_service_delete_path_finish
 secret_service_delete_path_sync
-secret_service_read_alias
-secret_service_read_alias_finish
-secret_service_read_alias_sync
 secret_service_read_alias_path
 secret_service_read_alias_path_finish
 secret_service_read_alias_path_sync
-secret_service_set_alias
-secret_service_set_alias_finish
-secret_service_set_alias_sync
 secret_service_set_alias_path
 secret_service_set_alias_path_finish
 secret_service_set_alias_path_sync
-<SUBSECTION Standard>
-SECRET_IS_SERVICE
-SECRET_IS_SERVICE_CLASS
-SECRET_SERVICE
-SECRET_SERVICE_CLASS
-SECRET_SERVICE_GET_CLASS
-SECRET_TYPE_SERVICE
-SECRET_TYPE_SERVICE_FLAGS
-SecretServicePrivate
-secret_service_flags_get_type
-secret_service_get_type
 </SECTION>
 
 <SECTION>
diff --git a/library/Makefile.am b/library/Makefile.am
index 752dd01..c45c10f 100644
--- a/library/Makefile.am
+++ b/library/Makefile.am
@@ -26,6 +26,7 @@ HEADER_FILES = \
 	secret-collection.h \
 	secret-item.h \
 	secret-password.h \
+	secret-paths.h \
 	secret-prompt.h \
 	secret-schema.h \
 	secret-schemas.h \
@@ -51,6 +52,7 @@ PUBLIC_FILES = \
 	secret-item.h secret-item.c \
 	secret-methods.c \
 	secret-password.h secret-password.c \
+	secret-paths.h secret-paths.c \
 	secret-prompt.h secret-prompt.c \
 	secret-schema.h secret-schema.c \
 	secret-schemas.h secret-schemas.c \
diff --git a/library/secret-collection.c b/library/secret-collection.c
index 56992b5..95e8b22 100644
--- a/library/secret-collection.c
+++ b/library/secret-collection.c
@@ -17,6 +17,7 @@
 #include "secret-collection.h"
 #include "secret-dbus-generated.h"
 #include "secret-item.h"
+#include "secret-paths.h"
 #include "secret-private.h"
 #include "secret-service.h"
 #include "secret-types.h"
diff --git a/library/secret-item.c b/library/secret-item.c
index ce53955..81f5a2e 100644
--- a/library/secret-item.c
+++ b/library/secret-item.c
@@ -18,6 +18,7 @@
 #include "secret-dbus-generated.h"
 #include "secret-enum-types.h"
 #include "secret-item.h"
+#include "secret-paths.h"
 #include "secret-private.h"
 #include "secret-service.h"
 #include "secret-types.h"
diff --git a/library/secret-methods.c b/library/secret-methods.c
index 6842384..91405c4 100644
--- a/library/secret-methods.c
+++ b/library/secret-methods.c
@@ -18,213 +18,12 @@
 #include "secret-collection.h"
 #include "secret-dbus-generated.h"
 #include "secret-item.h"
+#include "secret-paths.h"
 #include "secret-private.h"
 #include "secret-service.h"
 #include "secret-types.h"
 #include "secret-value.h"
 
-static void
-on_search_items_complete (GObject *source,
-                          GAsyncResult *result,
-                          gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	GError *error = NULL;
-	GVariant *response;
-
-	response = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
-	if (error != NULL)
-		g_simple_async_result_take_error (res, error);
-	else
-		g_simple_async_result_set_op_res_gpointer (res, response,
-		                                           (GDestroyNotify)g_variant_unref);
-
-	g_simple_async_result_complete (res);
-	g_object_unref (res);
-}
-
-/**
- * secret_service_search_for_paths:
- * @self: the secret service
- * @attributes: (element-type utf8 utf8): search for items matching these attributes
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Search for items matching the @attributes, and return their D-Bus object paths.
- * All collections are searched. The @attributes should be a table of string keys
- * and string values.
- *
- * This function returns immediately and completes asynchronously.
- *
- * When your callback is called use secret_service_search_for_paths_finish()
- * to get the results of this function. Only the D-Bus object paths of the
- * items will be returned. If you would like #SecretItem objects to be returned
- * instead, then use the secret_service_search() function.
- */
-void
-secret_service_search_for_paths (SecretService *self,
-                                 GHashTable *attributes,
-                                 GCancellable *cancellable,
-                                 GAsyncReadyCallback callback,
-                                 gpointer user_data)
-{
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (attributes != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	_secret_service_search_for_paths_variant (self, _secret_attributes_to_variant (attributes, NULL),
-	                                          cancellable, callback, user_data);
-}
-
-void
-_secret_service_search_for_paths_variant (SecretService *self,
-                                          GVariant *attributes,
-                                          GCancellable *cancellable,
-                                          GAsyncReadyCallback callback,
-                                          gpointer user_data)
-{
-	GSimpleAsyncResult *res;
-
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (attributes != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 secret_service_search_for_paths);
-
-	g_dbus_proxy_call (G_DBUS_PROXY (self), "SearchItems",
-	                   g_variant_new ("(@a{ss})", attributes),
-	                   G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
-	                   on_search_items_complete, g_object_ref (res));
-
-	g_object_unref (res);
-}
-
-/**
- * secret_service_search_for_paths_finish:
- * @self: the secret service
- * @result: asynchronous result passed to callback
- * @unlocked: (out) (transfer full) (array zero-terminated=1) (allow-none):
- *            location to place an array of D-Bus object paths for matching
- *            items which were locked.
- * @locked: (out) (transfer full) (array zero-terminated=1) (allow-none):
- *          location to place an array of D-Bus object paths for matching
- *          items which were locked.
- * @error: location to place error on failure
- *
- * Complete asynchronous operation to search for items, and return their
- * D-Bus object paths.
- *
- * Matching items that are locked or unlocked, have their D-Bus paths placed
- * in the @locked or @unlocked arrays respectively.
- *
- * D-Bus object paths of the items will be returned in the @unlocked or
- * @locked arrays. If you would to have #SecretItem objects to be returned
- * instead, then us the secret_service_search() and
- * secret_service_search_finish() functions.
- *
- * Returns: whether the search was successful or not
- */
-gboolean
-secret_service_search_for_paths_finish (SecretService *self,
-                                        GAsyncResult *result,
-                                        gchar ***unlocked,
-                                        gchar ***locked,
-                                        GError **error)
-{
-	GVariant *response;
-	GSimpleAsyncResult *res;
-	gchar **dummy = NULL;
-
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      secret_service_search_for_paths), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-	if (g_simple_async_result_propagate_error (res, error))
-		return FALSE;
-
-	if (unlocked || locked) {
-		if (!unlocked)
-			unlocked = &dummy;
-		else if (!locked)
-			locked = &dummy;
-		response = g_simple_async_result_get_op_res_gpointer (res);
-		g_variant_get (response, "(^ao^ao)", unlocked, locked);
-	}
-
-	g_strfreev (dummy);
-	return TRUE;
-}
-
-/**
- * secret_service_search_for_paths_sync:
- * @self: the secret service
- * @attributes: (element-type utf8 utf8): search for items matching these attributes
- * @cancellable: optional cancellation object
- * @unlocked: (out) (transfer full) (array zero-terminated=1) (allow-none):
- *            location to place an array of D-Bus object paths for matching
- *            items which were locked.
- * @locked: (out) (transfer full) (array zero-terminated=1) (allow-none):
- *          location to place an array of D-Bus object paths for matching
- *          items which were locked.
- * @error: location to place error on failure
- *
- * Search for items matching the @attributes, and return their D-Bus object
- * paths. All collections are searched. The @attributes should be a table of
- * string keys and string values.
- *
- * This function may block indefinetely. Use the asynchronous version
- * in user interface threads.
- *
- * Matching items that are locked or unlocked, have their D-Bus paths placed
- * in the @locked or @unlocked arrays respectively.
- *
- * D-Bus object paths of the items will be returned in the @unlocked or
- * @locked arrays. If you would to have #SecretItem objects to be returned
- * instead, then use the secret_service_search_sync() function.
- *
- * Returns: whether the search was successful or not
- */
-gboolean
-secret_service_search_for_paths_sync (SecretService *self,
-                                      GHashTable *attributes,
-                                      GCancellable *cancellable,
-                                      gchar ***unlocked,
-                                      gchar ***locked,
-                                      GError **error)
-{
-	gchar **dummy = NULL;
-	GVariant *response;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (attributes != NULL, FALSE);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	response = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "SearchItems",
-	                                   g_variant_new ("(@a{ss})",
-	                                                  _secret_attributes_to_variant (attributes, NULL)),
-	                                   G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error);
-
-	if (response != NULL) {
-		if (unlocked || locked) {
-			if (!unlocked)
-				unlocked = &dummy;
-			else if (!locked)
-				locked = &dummy;
-			g_variant_get (response, "(^ao^ao)", unlocked, locked);
-		}
-
-		g_variant_unref (response);
-	}
-
-	g_strfreev (dummy);
-
-	return response != NULL;
-}
-
 typedef struct {
 	GCancellable *cancellable;
 	GHashTable *items;
@@ -584,54 +383,10 @@ on_get_secrets_session (GObject *source,
 	g_object_unref (res);
 }
 
-/**
- * secret_service_get_secret_for_path:
- * @self: the secret service
- * @item_path: the D-Bus path to item to retrieve secret for
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Get the secret value for an secret item stored in the service.
- *
- * The item is represented by its D-Bus object path. If you already have a
- * #SecretItem proxy object, use use secret_item_get_secret() to more simply
- * get its secret value.
- *
- * This function returns immediately and completes asynchronously.
- */
-void
-secret_service_get_secret_for_path (SecretService *self,
-                                    const gchar *item_path,
-                                    GCancellable *cancellable,
-                                    GAsyncReadyCallback callback,
-                                    gpointer user_data)
-{
-	GSimpleAsyncResult *res;
-	GetClosure *closure;
-
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (item_path != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 secret_service_get_secret_for_path);
-
-	closure = g_slice_new0 (GetClosure);
-	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	closure->in = g_variant_ref_sink (g_variant_new_objv (&item_path, 1));
-	g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
-
-	secret_service_ensure_session (self, cancellable,
-	                               on_get_secrets_session,
-	                               g_object_ref (res));
-
-	g_object_unref (res);
-}
 
-static SecretValue *
-service_decode_get_secrets_first (SecretService *self,
-                                  GVariant *out)
+SecretValue *
+_secret_service_decode_get_secrets_first (SecretService *self,
+                                          GVariant *out)
 {
 	SecretSession *session;
 	SecretValue *value = NULL;
@@ -650,9 +405,9 @@ service_decode_get_secrets_first (SecretService *self,
 	return value;
 }
 
-static GHashTable *
-service_decode_get_secrets_all (SecretService *self,
-                                GVariant *out)
+GHashTable *
+_secret_service_decode_get_secrets_all (SecretService *self,
+                                        GVariant *out)
 {
 	SecretSession *session;
 	GVariantIter *iter;
@@ -675,138 +430,66 @@ service_decode_get_secrets_all (SecretService *self,
 }
 
 /**
- * secret_service_get_secret_for_path_finish:
- * @self: the secret service
- * @result: asynchronous result passed to callback
- * @error: location to place an error on failure
- *
- * Complete asynchronous operation to get the secret value for an
- * secret item stored in the service.
- *
- * Will return %NULL if the item is locked.
- *
- * Returns: (transfer full) (allow-none): the newly allocated secret value
- *          for the item, which should be released with secret_value_unref()
- */
-SecretValue *
-secret_service_get_secret_for_path_finish (SecretService *self,
-                                           GAsyncResult *result,
-                                           GError **error)
-{
-	GSimpleAsyncResult *res;
-	GetClosure *closure;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      secret_service_get_secret_for_path), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-	if (g_simple_async_result_propagate_error (res, error))
-		return NULL;
-
-	closure = g_simple_async_result_get_op_res_gpointer (res);
-	return service_decode_get_secrets_first (self, closure->out);
-}
-
-/**
- * secret_service_get_secret_for_path_sync:
- * @self: the secret service
- * @item_path: the D-Bus path to item to retrieve secret for
- * @cancellable: optional cancellation object
- * @error: location to place an error on failure
- *
- * Get the secret value for an secret item stored in the service.
- *
- * The item is represented by its D-Bus object path. If you already have a
- * #SecretItem proxy object, use use secret_item_get_secret_sync() to more simply
- * get its secret value.
- *
- * This method may block indefinitely and should not be used in user interface
- * threads.
- *
- * Will return %NULL if the item is locked.
- *
- * Returns: (transfer full) (allow-none): the newly allocated secret value
- *          for the item, which should be released with secret_value_unref()
- */
-SecretValue *
-secret_service_get_secret_for_path_sync (SecretService *self,
-                                         const gchar *item_path,
-                                         GCancellable *cancellable,
-                                         GError **error)
-{
-	SecretSync *sync;
-	SecretValue *value;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (item_path != NULL, NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_get_secret_for_path (self, item_path, cancellable,
-	                                    _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	value = secret_service_get_secret_for_path_finish (self, sync->result, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return value;
-}
-
-/**
- * secret_service_get_secrets_for_paths:
+ * secret_service_get_secrets:
  * @self: the secret service
- * @item_paths: the D-Bus paths to items to retrieve secrets for
+ * @items: (element-type Secret.Item): the items to retrieve secrets for
  * @cancellable: optional cancellation object
  * @callback: called when the operation completes
  * @user_data: data to pass to the callback
  *
  * Get the secret values for an secret items stored in the service.
  *
- * The items are represented by their D-Bus object paths. If you already have
- * #SecretItem proxy objects, use use secret_service_get_secrets() to more simply
- * get their secret values.
+ * This method takes a list of #SecretItem proxy objects. If you only have the
+ * D-Bus object paths of the items, use secret_service_get_secrets_for_paths()
+ * instead.
  *
  * This function returns immediately and completes asynchronously.
  */
 void
-secret_service_get_secrets_for_paths (SecretService *self,
-                                      const gchar **item_paths,
-                                      GCancellable *cancellable,
-                                      GAsyncReadyCallback callback,
-                                      gpointer user_data)
+secret_service_get_secrets (SecretService *self,
+                            GList *items,
+                            GCancellable *cancellable,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data)
 {
 	GSimpleAsyncResult *res;
 	GetClosure *closure;
+	GPtrArray *paths;
+	const gchar *path;
+	GList *l;
 
 	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (item_paths != NULL);
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 secret_service_get_secret_for_path);
-
+	                                 secret_service_get_secrets);
 	closure = g_slice_new0 (GetClosure);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	closure->in = g_variant_ref_sink (g_variant_new_objv (item_paths, -1));
+	closure->items = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                                        g_free, g_object_unref);
+
+	paths = g_ptr_array_new ();
+	for (l = items; l != NULL; l = g_list_next (l)) {
+		path = g_dbus_proxy_get_object_path (l->data);
+		g_hash_table_insert (closure->items, g_strdup (path), g_object_ref (l->data));
+		g_ptr_array_add (paths, (gpointer)path);
+	}
+
+	closure->in = g_variant_new_objv ((const gchar * const *)paths->pdata, paths->len);
+	g_variant_ref_sink (closure->in);
+
+	g_ptr_array_free (paths, TRUE);
 	g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
 
 	secret_service_ensure_session (self, cancellable,
-	                               on_get_secrets_session,
-	                               g_object_ref (res));
+	                                on_get_secrets_session,
+	                                g_object_ref (res));
 
 	g_object_unref (res);
 }
 
 /**
- * secret_service_get_secrets_for_paths_finish:
+ * secret_service_get_secrets_finish:
  * @self: the secret service
  * @result: asynchronous result passed to callback
  * @error: location to place an error on failure
@@ -816,20 +499,26 @@ secret_service_get_secrets_for_paths (SecretService *self,
  *
  * Items that are locked will not be included the results.
  *
- * Returns: (transfer full): a newly allocated hash table of item_path keys to
- *          #SecretValue values.
+ * Returns: (transfer full): a newly allocated hash table of #SecretItem keys
+ *          to #SecretValue values.
  */
 GHashTable *
-secret_service_get_secrets_for_paths_finish (SecretService *self,
-                                             GAsyncResult *result,
-                                             GError **error)
+secret_service_get_secrets_finish (SecretService *self,
+                                   GAsyncResult *result,
+                                   GError **error)
 {
 	GSimpleAsyncResult *res;
 	GetClosure *closure;
+	GHashTable *with_paths;
+	GHashTable *with_items;
+	GHashTableIter iter;
+	const gchar *path;
+	SecretValue *value;
+	SecretItem *item;
 
 	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      secret_service_get_secret_for_path), NULL);
+	                      secret_service_get_secrets), NULL);
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	res = G_SIMPLE_ASYNC_RESULT (result);
@@ -837,187 +526,36 @@ secret_service_get_secrets_for_paths_finish (SecretService *self,
 		return NULL;
 
 	closure = g_simple_async_result_get_op_res_gpointer (res);
-	return service_decode_get_secrets_all (self, closure->out);
+	with_paths = _secret_service_decode_get_secrets_all (self, closure->out);
+	g_return_val_if_fail (with_paths != NULL, NULL);
+
+	with_items = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+	                                    g_object_unref, secret_value_unref);
+
+	g_hash_table_iter_init (&iter, with_paths);
+	while (g_hash_table_iter_next (&iter, (gpointer *)&path, (gpointer *)&value)) {
+		item = g_hash_table_lookup (closure->items, path);
+		if (item != NULL)
+			g_hash_table_insert (with_items, g_object_ref (item),
+			                     secret_value_ref (value));
+	}
+
+	g_hash_table_unref (with_paths);
+	return with_items;
 }
 
 /**
- * secret_service_get_secrets_for_paths_sync:
+ * secret_service_get_secrets_sync:
  * @self: the secret service
- * @item_paths: the D-Bus paths to items to retrieve secrets for
+ * @items: (element-type Secret.Item): the items to retrieve secrets for
  * @cancellable: optional cancellation object
  * @error: location to place an error on failure
  *
  * Get the secret values for an secret items stored in the service.
  *
- * The items are represented by their D-Bus object paths. If you already have
- * #SecretItem proxy objects, use use secret_service_get_secrets_sync() to more
- * simply get their secret values.
- *
- * This method may block indefinitely and should not be used in user interface
- * threads.
- *
- * Items that are locked will not be included the results.
- *
- * Returns: (transfer full): a newly allocated hash table of item_path keys to
- *          #SecretValue values.
- */
-GHashTable *
-secret_service_get_secrets_for_paths_sync (SecretService *self,
-                                           const gchar **item_paths,
-                                           GCancellable *cancellable,
-                                           GError **error)
-{
-	SecretSync *sync;
-	GHashTable *secrets;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (item_paths != NULL, NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_get_secrets_for_paths (self, item_paths, cancellable,
-	                                      _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	secrets = secret_service_get_secrets_for_paths_finish (self, sync->result, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return secrets;
-}
-
-/**
- * secret_service_get_secrets:
- * @self: the secret service
- * @items: (element-type Secret.Item): the items to retrieve secrets for
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Get the secret values for an secret items stored in the service.
- *
- * This method takes a list of #SecretItem proxy objects. If you only have the
- * D-Bus object paths of the items, use secret_service_get_secrets_for_paths()
- * instead.
- *
- * This function returns immediately and completes asynchronously.
- */
-void
-secret_service_get_secrets (SecretService *self,
-                            GList *items,
-                            GCancellable *cancellable,
-                            GAsyncReadyCallback callback,
-                            gpointer user_data)
-{
-	GSimpleAsyncResult *res;
-	GetClosure *closure;
-	GPtrArray *paths;
-	const gchar *path;
-	GList *l;
-
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 secret_service_get_secrets);
-	closure = g_slice_new0 (GetClosure);
-	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	closure->items = g_hash_table_new_full (g_str_hash, g_str_equal,
-	                                        g_free, g_object_unref);
-
-	paths = g_ptr_array_new ();
-	for (l = items; l != NULL; l = g_list_next (l)) {
-		path = g_dbus_proxy_get_object_path (l->data);
-		g_hash_table_insert (closure->items, g_strdup (path), g_object_ref (l->data));
-		g_ptr_array_add (paths, (gpointer)path);
-	}
-
-	closure->in = g_variant_new_objv ((const gchar * const *)paths->pdata, paths->len);
-	g_variant_ref_sink (closure->in);
-
-	g_ptr_array_free (paths, TRUE);
-	g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
-
-	secret_service_ensure_session (self, cancellable,
-	                                on_get_secrets_session,
-	                                g_object_ref (res));
-
-	g_object_unref (res);
-}
-
-/**
- * secret_service_get_secrets_finish:
- * @self: the secret service
- * @result: asynchronous result passed to callback
- * @error: location to place an error on failure
- *
- * Complete asynchronous operation to get the secret values for an
- * secret items stored in the service.
- *
- * Items that are locked will not be included the results.
- *
- * Returns: (transfer full): a newly allocated hash table of #SecretItem keys
- *          to #SecretValue values.
- */
-GHashTable *
-secret_service_get_secrets_finish (SecretService *self,
-                                   GAsyncResult *result,
-                                   GError **error)
-{
-	GSimpleAsyncResult *res;
-	GetClosure *closure;
-	GHashTable *with_paths;
-	GHashTable *with_items;
-	GHashTableIter iter;
-	const gchar *path;
-	SecretValue *value;
-	SecretItem *item;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      secret_service_get_secrets), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-	if (g_simple_async_result_propagate_error (res, error))
-		return NULL;
-
-	closure = g_simple_async_result_get_op_res_gpointer (res);
-	with_paths = service_decode_get_secrets_all (self, closure->out);
-	g_return_val_if_fail (with_paths != NULL, NULL);
-
-	with_items = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-	                                    g_object_unref, secret_value_unref);
-
-	g_hash_table_iter_init (&iter, with_paths);
-	while (g_hash_table_iter_next (&iter, (gpointer *)&path, (gpointer *)&value)) {
-		item = g_hash_table_lookup (closure->items, path);
-		if (item != NULL)
-			g_hash_table_insert (with_items, g_object_ref (item),
-			                     secret_value_ref (value));
-	}
-
-	g_hash_table_unref (with_paths);
-	return with_items;
-}
-
-/**
- * secret_service_get_secrets_sync:
- * @self: the secret service
- * @items: (element-type Secret.Item): the items to retrieve secrets for
- * @cancellable: optional cancellation object
- * @error: location to place an error on failure
- *
- * Get the secret values for an secret items stored in the service.
- *
- * This method takes a list of #SecretItem proxy objects. If you only have the
- * D-Bus object paths of the items, use secret_service_get_secrets_for_paths_sync()
- * instead.
+ * This method takes a list of #SecretItem proxy objects. If you only have the
+ * D-Bus object paths of the items, use secret_service_get_secrets_for_paths_sync()
+ * instead.
  *
  * This method may block indefinitely and should not be used in user interface
  * threads.
@@ -1382,339 +920,83 @@ secret_service_lock_sync (SecretService *self,
 }
 
 /**
- * secret_service_lock_paths_sync:
+ * secret_service_unlock:
  * @self: the secret service
- * @paths: the D-Bus object paths of the items or collections to lock
+ * @objects: (element-type GLib.DBusProxy): the items or collections to unlock
  * @cancellable: optional cancellation object
- * @locked: (out) (array zero-terminated=1) (transfer full) (allow-none):
- *          location to place array of D-Bus paths of items or collections
- *          that were locked
- * @error: location to place an error on failure
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
  *
- * Lock items or collections in the secret service.
+ * Unlock items or collections in the secret service.
  *
- * The items or collections are represented by their D-Bus object paths. If you
- * already have #SecretItem and #SecretCollection proxy objects, use use
- * secret_service_lock_sync() instead.
+ * This method takes a list of #SecretItem or #SecretCollection proxy objects.
+ * If you only have the D-Bus object paths of the items or collections, use
+ * secret_service_unlock_paths() instead.
  *
- * The secret service may not be able to lock items individually, and may
- * lock an entire collection instead.
+ * The secret service may not be able to unlock items individually, and may
+ * unlock an entire collection instead.
  *
  * This method may block indefinitely and should not be used in user
  * interface threads. The secret service may prompt the user.
  * secret_service_prompt() will be used to handle any prompts that show up.
- *
- * Returns: the number of items or collections that were locked
- */
-gint
-secret_service_lock_paths_sync (SecretService *self,
-                                const gchar **paths,
-                                GCancellable *cancellable,
-                                gchar ***locked,
-                                GError **error)
-{
-	SecretSync *sync;
-	gint count;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
-	g_return_val_if_fail (paths != NULL, -1);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
-	g_return_val_if_fail (error == NULL || *error == NULL, -1);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_lock_paths (self, paths, cancellable,
-	                            _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	count = secret_service_lock_paths_finish (self, sync->result,
-	                                           locked, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return count;
-}
-
-/**
- * secret_service_lock_paths:
- * @self: the secret service
- * @paths: the D-Bus paths for items or collections to lock
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Lock items or collections in the secret service.
- *
- * The items or collections are represented by their D-Bus object paths. If you
- * already have #SecretItem and #SecretCollection proxy objects, use use
- * secret_service_lock() instead.
- *
- * The secret service may not be able to lock items individually, and may
- * lock an entire collection instead.
- *
- * This method returns immediately and completes asynchronously. The secret
- * service may prompt the user. secret_service_prompt() will be used to handle
- * any prompts that show up.
  */
 void
-secret_service_lock_paths (SecretService *self,
-                           const gchar **paths,
-                           GCancellable *cancellable,
-                           GAsyncReadyCallback callback,
-                           gpointer user_data)
+secret_service_unlock (SecretService *self,
+                       GList *objects,
+                       GCancellable *cancellable,
+                       GAsyncReadyCallback callback,
+                       gpointer user_data)
 {
-	GSimpleAsyncResult *res;
-
 	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (paths != NULL);
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
-	res = service_xlock_paths_async (self, "Lock", paths, cancellable,
-	                                 callback, user_data);
-
-	g_object_unref (res);
+	service_xlock_async (self, "Unlock", objects, cancellable, callback, user_data);
 }
 
 /**
- * secret_service_lock_paths_finish:
+ * secret_service_unlock_finish:
  * @self: the secret service
  * @result: asynchronous result passed to the callback
- * @locked: (out) (array zero-terminated=1) (transfer full) (allow-none):
- *          location to place array of D-Bus paths of items or collections
- *          that were locked
+ * @unlocked: (out) (element-type GLib.DBusProxy) (transfer full) (allow-none):
+ *            location to place list of items or collections that were unlocked
  * @error: location to place an error on failure
  *
- * Complete asynchronous operation to lock items or collections in the secret
+ * Complete asynchronous operation to unlock items or collections in the secret
  * service.
  *
- * The secret service may not be able to lock items individually, and may
- * lock an entire collection instead.
+ * The secret service may not be able to unlock items individually, and may
+ * unlock an entire collection instead.
  *
- * Returns: the number of items or collections that were locked
+ * Returns: the number of items or collections that were unlocked
  */
 gint
-secret_service_lock_paths_finish (SecretService *self,
-                                  GAsyncResult *result,
-                                  gchar ***locked,
-                                  GError **error)
+secret_service_unlock_finish (SecretService *self,
+                              GAsyncResult *result,
+                              GList **unlocked,
+                              GError **error)
 {
 	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
-	g_return_val_if_fail (locked != NULL, -1);
 	g_return_val_if_fail (error == NULL || *error == NULL, -1);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      service_xlock_paths_async), -1);
 
-	return service_xlock_paths_finish (self, result, locked, error);
+	return service_xlock_finish (self, result, unlocked, error);
 }
 
 /**
- * secret_service_unlock_paths_sync:
+ * secret_service_unlock_sync:
  * @self: the secret service
- * @paths: the D-Bus object paths of the items or collections to unlock
+ * @objects: (element-type GLib.DBusProxy): the items or collections to unlock
  * @cancellable: optional cancellation object
- * @unlocked: (out) (array zero-terminated=1) (transfer full) (allow-none):
- *            location to place array of D-Bus paths of items or collections
- *            that were unlocked
+ * @unlocked: (out) (element-type GLib.DBusProxy) (transfer full) (allow-none):
+ *            location to place list of items or collections that were unlocked
  * @error: location to place an error on failure
  *
  * Unlock items or collections in the secret service.
  *
- * The items or collections are represented by their D-Bus object paths. If you
- * already have #SecretItem and #SecretCollection proxy objects, use use
- * secret_service_unlock_sync() instead.
- *
- * The secret service may not be able to unlock items individually, and may
- * unlock an entire collection instead.
- *
- * This method may block indefinitely and should not be used in user
- * interface threads. The secret service may prompt the user.
- * secret_service_prompt() will be used to handle any prompts that show up.
- *
- * Returns: the number of items or collections that were unlocked
- */
-gint
-secret_service_unlock_paths_sync (SecretService *self,
-                                  const gchar **paths,
-                                  GCancellable *cancellable,
-                                  gchar ***unlocked,
-                                  GError **error)
-{
-	SecretSync *sync;
-	gint count;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
-	g_return_val_if_fail (paths != NULL, -1);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
-	g_return_val_if_fail (unlocked != NULL, -1);
-	g_return_val_if_fail (error == NULL || *error == NULL, -1);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_unlock_paths (self, paths, cancellable,
-	                              _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	count = secret_service_unlock_paths_finish (self, sync->result,
-	                                             unlocked, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return count;
-}
-
-/**
- * secret_service_unlock_paths:
- * @self: the secret service
- * @paths: the D-Bus paths for items or collections to unlock
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Unlock items or collections in the secret service.
- *
- * The items or collections are represented by their D-Bus object paths. If you
- * already have #SecretItem and #SecretCollection proxy objects, use use
- * secret_service_unlock() instead.
- *
- * The secret service may not be able to unlock items individually, and may
- * unlock an entire collection instead.
- *
- * This method returns immediately and completes asynchronously. The secret
- * service may prompt the user. secret_service_prompt() will be used to handle
- * any prompts that show up.
- */
-void
-secret_service_unlock_paths (SecretService *self,
-                             const gchar **paths,
-                             GCancellable *cancellable,
-                             GAsyncReadyCallback callback,
-                             gpointer user_data)
-{
-	GSimpleAsyncResult *res;
-
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (paths != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	res = service_xlock_paths_async (self, "Unlock",
-	                                 paths, cancellable,
-	                                 callback, user_data);
-
-	g_object_unref (res);
-}
-
-/**
- * secret_service_unlock_paths_finish:
- * @self: the secret service
- * @result: asynchronous result passed to the callback
- * @unlocked: (out) (array zero-terminated=1) (transfer full) (allow-none):
- *            location to place array of D-Bus paths of items or collections
- *            that were unlocked
- * @error: location to place an error on failure
- *
- * Complete asynchronous operation to unlock items or collections in the secret
- * service.
- *
- * The secret service may not be able to unlock items individually, and may
- * unlock an entire collection instead.
- *
- * Returns: the number of items or collections that were unlocked
- */
-gint
-secret_service_unlock_paths_finish (SecretService *self,
-                                    GAsyncResult *result,
-                                    gchar ***unlocked,
-                                    GError **error)
-{
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
-	g_return_val_if_fail (error == NULL || *error == NULL, -1);
-
-	return service_xlock_paths_finish (self, result,
-	                                   unlocked, error);
-}
-
-/**
- * secret_service_unlock:
- * @self: the secret service
- * @objects: (element-type GLib.DBusProxy): the items or collections to unlock
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Unlock items or collections in the secret service.
- *
- * This method takes a list of #SecretItem or #SecretCollection proxy objects.
- * If you only have the D-Bus object paths of the items or collections, use
- * secret_service_unlock_paths() instead.
- *
- * The secret service may not be able to unlock items individually, and may
- * unlock an entire collection instead.
- *
- * This method may block indefinitely and should not be used in user
- * interface threads. The secret service may prompt the user.
- * secret_service_prompt() will be used to handle any prompts that show up.
- */
-void
-secret_service_unlock (SecretService *self,
-                       GList *objects,
-                       GCancellable *cancellable,
-                       GAsyncReadyCallback callback,
-                       gpointer user_data)
-{
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	service_xlock_async (self, "Unlock", objects, cancellable, callback, user_data);
-}
-
-/**
- * secret_service_unlock_finish:
- * @self: the secret service
- * @result: asynchronous result passed to the callback
- * @unlocked: (out) (element-type GLib.DBusProxy) (transfer full) (allow-none):
- *            location to place list of items or collections that were unlocked
- * @error: location to place an error on failure
- *
- * Complete asynchronous operation to unlock items or collections in the secret
- * service.
- *
- * The secret service may not be able to unlock items individually, and may
- * unlock an entire collection instead.
- *
- * Returns: the number of items or collections that were unlocked
- */
-gint
-secret_service_unlock_finish (SecretService *self,
-                              GAsyncResult *result,
-                              GList **unlocked,
-                              GError **error)
-{
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
-	g_return_val_if_fail (error == NULL || *error == NULL, -1);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      service_xlock_paths_async), -1);
-
-	return service_xlock_finish (self, result, unlocked, error);
-}
-
-/**
- * secret_service_unlock_sync:
- * @self: the secret service
- * @objects: (element-type GLib.DBusProxy): the items or collections to unlock
- * @cancellable: optional cancellation object
- * @unlocked: (out) (element-type GLib.DBusProxy) (transfer full) (allow-none):
- *            location to place list of items or collections that were unlocked
- * @error: location to place an error on failure
- *
- * Unlock items or collections in the secret service.
- *
- * This method takes a list of #SecretItem or #SecretCollection proxy objects.
- * If you only have the D-Bus object paths of the items or collections, use
- * secret_service_unlock_paths_sync() instead.
+ * This method takes a list of #SecretItem or #SecretCollection proxy objects.
+ * If you only have the D-Bus object paths of the items or collections, use
+ * secret_service_unlock_paths_sync() instead.
  *
  * The secret service may not be able to unlock items individually, and may
  * unlock an entire collection instead.
@@ -2180,968 +1462,208 @@ delete_closure_free (gpointer data)
 }
 
 static void
-on_delete_prompted (GObject *source,
-                    GAsyncResult *result,
-                    gpointer user_data)
+on_delete_password_complete (GObject *source,
+                             GAsyncResult *result,
+                             gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
 	DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
-	GVariant *retval;
-
-	retval = secret_service_prompt_finish (SECRET_SERVICE (source), result,
-	                                       NULL, &error);
 
-	if (error == NULL)
-		closure->deleted = TRUE;
-	else
+	closure->deleted = secret_service_delete_path_finish (self, result, &error);
+	if (error != NULL)
 		g_simple_async_result_take_error (res, error);
-	if (retval != NULL)
-		g_variant_unref (retval);
+
 	g_simple_async_result_complete (res);
+
+	g_object_unref (self);
 	g_object_unref (res);
 }
 
 static void
-on_delete_complete (GObject *source,
-                    GAsyncResult *result,
-                    gpointer user_data)
+on_search_delete_password (GObject *source,
+                           GAsyncResult *result,
+                           gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
 	DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
-	const gchar *prompt_path;
+	const gchar *path = NULL;
 	GError *error = NULL;
-	GVariant *retval;
+	gchar **locked;
+	gchar **unlocked;
 
-	retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
-	if (error == NULL) {
-		g_variant_get (retval, "(&o)", &prompt_path);
+	secret_service_search_for_paths_finish (self, result, &unlocked, &locked, &error);
+	if (error != NULL) {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete (res);
 
-		if (_secret_util_empty_path (prompt_path)) {
-			closure->deleted = TRUE;
+	} else {
+		/* Choose the first path */
+		if (unlocked && unlocked[0])
+			path = unlocked[0];
+		else if (locked && locked[0])
+			path = locked[0];
+
+		/* Nothing to delete? */
+		if (path == NULL) {
+			closure->deleted = FALSE;
 			g_simple_async_result_complete (res);
 
+		/* Delete the first path */
 		} else {
-			closure->prompt = _secret_prompt_instance (self, prompt_path);
-
-			secret_service_prompt (self, closure->prompt,
-			                       closure->cancellable,
-			                       on_delete_prompted,
-			                       g_object_ref (res));
+			closure->deleted = TRUE;
+			_secret_service_delete_path (self, path, TRUE,
+			                             closure->cancellable,
+			                             on_delete_password_complete,
+			                             g_object_ref (res));
 		}
-
-		g_variant_unref (retval);
-
-	} else {
-		g_simple_async_result_take_error (res, error);
-		g_simple_async_result_complete (res);
 	}
 
+	g_strfreev (locked);
+	g_strfreev (unlocked);
 	g_object_unref (self);
 	g_object_unref (res);
 }
 
+/**
+ * secret_service_remove:
+ * @self: the secret service
+ * @schema: (allow-none): the schema for the attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Remove a secret value from the secret service.
+ *
+ * The @attributes should be a set of key and value string pairs.
+ *
+ * If multiple items match the attributes, then only one will be deleted.
+ *
+ * This method will return immediately and complete asynchronously.
+ */
 void
-_secret_service_delete_path (SecretService *self,
-                             const gchar *object_path,
-                             gboolean is_an_item,
-                             GCancellable *cancellable,
-                             GAsyncReadyCallback callback,
-                             gpointer user_data)
+secret_service_remove (SecretService *self,
+                       const SecretSchema *schema,
+                       GHashTable *attributes,
+                       GCancellable *cancellable,
+                       GAsyncReadyCallback callback,
+                       gpointer user_data)
 {
+	const gchar *schema_name = NULL;
 	GSimpleAsyncResult *res;
 	DeleteClosure *closure;
+	GVariant *variant;
 
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (object_path != NULL);
+	g_return_if_fail (SECRET_SERVICE (self));
+	g_return_if_fail (attributes != NULL);
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
+	/* Warnings raised already */
+	if (schema != NULL && !_secret_attributes_validate (schema, attributes))
+		return;
+
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 _secret_service_delete_path);
+	                                 secret_service_remove);
 	closure = g_slice_new0 (DeleteClosure);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 	g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
 
-	g_dbus_connection_call (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
-	                        g_dbus_proxy_get_name (G_DBUS_PROXY (self)), object_path,
-	                        is_an_item ? SECRET_ITEM_INTERFACE : SECRET_COLLECTION_INTERFACE,
-	                        "Delete", g_variant_new ("()"), G_VARIANT_TYPE ("(o)"),
-	                        G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
-	                        cancellable, on_delete_complete, g_object_ref (res));
+	if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
+		schema_name = schema->name;
+	variant = _secret_attributes_to_variant (attributes, schema_name);
+
+	_secret_service_search_for_paths_variant (self, variant, cancellable,
+	                                          on_search_delete_password, g_object_ref (res));
 
 	g_object_unref (res);
 }
 
 /**
- * secret_service_delete_path:
+ * secret_service_remove_finish:
  * @self: the secret service
- * @item_path: the D-Bus path of item to delete
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to be passed to the callback
+ * @result: the asynchronous result passed to the callback
+ * @error: location to place an error on failure
  *
- * Delete a secret item from the secret service.
+ * Finish asynchronous operation to remove a secret value from the secret
+ * service.
  *
- * The item is represented by its D-Bus object path. If you already have a
- * #SecretItem proxy objects, use use secret_item_delete() instead.
- *
- * This method will return immediately and complete asynchronously.
- */
-void
-secret_service_delete_path (SecretService *self,
-                            const gchar *item_path,
-                            GCancellable *cancellable,
-                            GAsyncReadyCallback callback,
-                            gpointer user_data)
-{
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (item_path != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	_secret_service_delete_path (self, item_path, TRUE, cancellable, callback, user_data);
-}
-
-/**
- * secret_service_delete_path_finish:
- * @self: the secret service
- * @result: the asynchronous result passed to the callback
- * @error: location to place an error on failure
- *
- * Complete an asynchronous operation to delete a secret item from the secret
- * service.
- *
- * Returns: whether the deletion was successful or not
- */
-gboolean
-secret_service_delete_path_finish (SecretService *self,
-                                   GAsyncResult *result,
-                                   GError **error)
-{
-	GSimpleAsyncResult *res;
-	DeleteClosure *closure;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      _secret_service_delete_path), FALSE);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-	if (g_simple_async_result_propagate_error (res, error))
-		return FALSE;
-
-	closure = g_simple_async_result_get_op_res_gpointer (res);
-	return closure->deleted;
-}
-
-/**
- * secret_service_delete_path_sync:
- * @self: the secret service
- * @item_path: the D-Bus path of item to delete
- * @cancellable: optional cancellation object
- * @error: location to place an error on failure
- *
- * Delete a secret item from the secret service.
- *
- * The item is represented by its D-Bus object path. If you already have a
- * #SecretItem proxy objects, use use secret_item_delete_sync() instead.
- *
- * This method may block indefinitely and should not be used in user interface
- * threads.
- *
- * Returns: whether the deletion was successful or not
- */
-gboolean
-secret_service_delete_path_sync (SecretService *self,
-                                 const gchar *item_path,
-                                 GCancellable *cancellable,
-                                 GError **error)
-{
-	SecretSync *sync;
-	gboolean result;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (item_path != NULL, FALSE);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_delete_path (self, item_path, cancellable,
-	                            _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	result = secret_service_delete_path_finish (self, sync->result, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return result;
-}
-
-static void
-on_delete_password_complete (GObject *source,
-                             GAsyncResult *result,
-                             gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
-	DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	GError *error = NULL;
-
-	closure->deleted = secret_service_delete_path_finish (self, result, &error);
-	if (error != NULL)
-		g_simple_async_result_take_error (res, error);
-
-	g_simple_async_result_complete (res);
-
-	g_object_unref (self);
-	g_object_unref (res);
-}
-
-static void
-on_search_delete_password (GObject *source,
-                           GAsyncResult *result,
-                           gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
-	const gchar *path = NULL;
-	GError *error = NULL;
-	gchar **locked;
-	gchar **unlocked;
-
-	secret_service_search_for_paths_finish (self, result, &unlocked, &locked, &error);
-	if (error != NULL) {
-		g_simple_async_result_take_error (res, error);
-		g_simple_async_result_complete (res);
-
-	} else {
-		/* Choose the first path */
-		if (unlocked && unlocked[0])
-			path = unlocked[0];
-		else if (locked && locked[0])
-			path = locked[0];
-
-		/* Nothing to delete? */
-		if (path == NULL) {
-			closure->deleted = FALSE;
-			g_simple_async_result_complete (res);
-
-		/* Delete the first path */
-		} else {
-			closure->deleted = TRUE;
-			_secret_service_delete_path (self, path, TRUE,
-			                             closure->cancellable,
-			                             on_delete_password_complete,
-			                             g_object_ref (res));
-		}
-	}
-
-	g_strfreev (locked);
-	g_strfreev (unlocked);
-	g_object_unref (self);
-	g_object_unref (res);
-}
-
-/**
- * secret_service_remove:
- * @self: the secret service
- * @schema: (allow-none): the schema for the attributes
- * @attributes: (element-type utf8 utf8): the attribute keys and values
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to be passed to the callback
- *
- * Remove a secret value from the secret service.
- *
- * The @attributes should be a set of key and value string pairs.
- *
- * If multiple items match the attributes, then only one will be deleted.
- *
- * This method will return immediately and complete asynchronously.
- */
-void
-secret_service_remove (SecretService *self,
-                       const SecretSchema *schema,
-                       GHashTable *attributes,
-                       GCancellable *cancellable,
-                       GAsyncReadyCallback callback,
-                       gpointer user_data)
-{
-	const gchar *schema_name = NULL;
-	GSimpleAsyncResult *res;
-	DeleteClosure *closure;
-	GVariant *variant;
-
-	g_return_if_fail (SECRET_SERVICE (self));
-	g_return_if_fail (attributes != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	/* Warnings raised already */
-	if (schema != NULL && !_secret_attributes_validate (schema, attributes))
-		return;
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 secret_service_remove);
-	closure = g_slice_new0 (DeleteClosure);
-	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
-
-	if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME))
-		schema_name = schema->name;
-	variant = _secret_attributes_to_variant (attributes, schema_name);
-
-	_secret_service_search_for_paths_variant (self, variant, cancellable,
-	                                          on_search_delete_password, g_object_ref (res));
-
-	g_object_unref (res);
-}
-
-/**
- * secret_service_remove_finish:
- * @self: the secret service
- * @result: the asynchronous result passed to the callback
- * @error: location to place an error on failure
- *
- * Finish asynchronous operation to remove a secret value from the secret
- * service.
- *
- * Returns: whether the removal was successful or not
- */
-gboolean
-secret_service_remove_finish (SecretService *self,
-                              GAsyncResult *result,
-                              GError **error)
-{
-	GSimpleAsyncResult *res;
-	DeleteClosure *closure;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      secret_service_remove), FALSE);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-	if (g_simple_async_result_propagate_error (res, error))
-		return FALSE;
-
-	closure = g_simple_async_result_get_op_res_gpointer (res);
-	return closure->deleted;
-}
-
-/**
- * secret_service_remove_sync:
- * @self: the secret service
- * @schema: (allow-none): the schema for the attributes
- * @attributes: (element-type utf8 utf8): the attribute keys and values
- * @cancellable: optional cancellation object
- * @error: location to place an error on failure
- *
- * Remove a secret value from the secret service.
- *
- * The @attributes should be a set of key and value string pairs.
- *
- * If multiple items match the attributes, then only one will be deleted.
- *
- * This method may block indefinitely and should not be used in user interface
- * threads.
- *
- * Returns: whether the removal was successful or not
- */
-gboolean
-secret_service_remove_sync (SecretService *self,
-                            const SecretSchema *schema,
-                            GHashTable *attributes,
-                            GCancellable *cancellable,
-                            GError **error)
-{
-	SecretSync *sync;
-	gboolean result;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	/* Warnings raised already */
-	if (schema != NULL && !_secret_attributes_validate (schema, attributes))
-		return FALSE;
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_remove (self, schema, attributes, cancellable,
-	                       _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	result = secret_service_remove_finish (self, sync->result, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return result;
-}
-
-typedef struct {
-	GCancellable *cancellable;
-	SecretPrompt *prompt;
-	gchar *collection_path;
-} CollectionClosure;
-
-static void
-collection_closure_free (gpointer data)
-{
-	CollectionClosure *closure = data;
-	g_clear_object (&closure->cancellable);
-	g_clear_object (&closure->prompt);
-	g_slice_free (CollectionClosure, closure);
-}
-
-static void
-on_create_collection_prompt (GObject *source,
-                             GAsyncResult *result,
-                             gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	GError *error = NULL;
-	GVariant *value;
-
-	value = secret_service_prompt_finish (SECRET_SERVICE (source), result,
-	                                      G_VARIANT_TYPE ("o"), &error);
-	if (error != NULL)
-		g_simple_async_result_take_error (res, error);
-	if (value != NULL) {
-		closure->collection_path = g_variant_dup_string (value, NULL);
-		g_variant_unref (value);
-	}
-
-	g_simple_async_result_complete (res);
-	g_object_unref (res);
-}
-
-static void
-on_create_collection_called (GObject *source,
-                             GAsyncResult *result,
-                             gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
-	const gchar *prompt_path = NULL;
-	const gchar *collection_path = NULL;
-	GError *error = NULL;
-	GVariant *retval;
-
-	retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
-	if (error == NULL) {
-		g_variant_get (retval, "(&o&o)", &collection_path, &prompt_path);
-		if (!_secret_util_empty_path (prompt_path)) {
-			closure->prompt = _secret_prompt_instance (self, prompt_path);
-			secret_service_prompt (self, closure->prompt,
-			                       closure->cancellable, on_create_collection_prompt,
-			                       g_object_ref (res));
-
-		} else {
-			closure->collection_path = g_strdup (collection_path);
-			g_simple_async_result_complete (res);
-		}
-
-		g_variant_unref (retval);
-
-	} else {
-		g_simple_async_result_take_error (res, error);
-		g_simple_async_result_complete (res);
-	}
-
-	g_object_unref (self);
-	g_object_unref (res);
-}
-
-/**
- * secret_service_create_collection_path:
- * @self: a secret service object
- * @properties: (element-type utf8 GLib.Variant): hash table of properties for
- *              the new collection
- * @alias: (allow-none): an alias to check for before creating the new
- *         collection, or to assign to the new collection
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to be passed to the callback
- *
- * Create a new collection in the secret service, and return its path.
- *
- * Using this method requires that you setup a correct hash table of D-Bus
- * properties for the new collection. You may prefer to use
- * secret_collection_create() which does handles this for you.
- *
- * An @alias is a well-known tag for a collection, such as 'default' (ie: the
- * default collection to store items in). This allows other applications to
- * easily identify and share a collection. If a collection with the @alias
- * already exists, then instead of creating a new collection, the existing
- * collection will be returned. If no collection with this alias exists, then a
- * new collection will be created and this alias will be assigned to it.
- *
- * @properties is a set of properties for the new collection. The keys in the
- * hash table should be interface.property strings like
- * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
- * in the hash table should be #GVariant values of the properties.
- *
- * If you wish to have a
- *
- * This method will return immediately and complete asynchronously. The secret
- * service may prompt the user. secret_service_prompt() will be used to handle
- * any prompts that are required.
- */
-void
-secret_service_create_collection_path (SecretService *self,
-                                       GHashTable *properties,
-                                       const gchar *alias,
-                                       GCancellable *cancellable,
-                                       GAsyncReadyCallback callback,
-                                       gpointer user_data)
-{
-	GSimpleAsyncResult *res;
-	CollectionClosure *closure;
-	GVariant *params;
-	GVariant *props;
-	GDBusProxy *proxy;
-
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (properties != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	if (alias == NULL)
-		alias = "";
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 secret_service_create_collection_path);
-	closure = g_slice_new0 (CollectionClosure);
-	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	g_simple_async_result_set_op_res_gpointer (res, closure, collection_closure_free);
-
-	props = _secret_util_variant_for_properties (properties);
-	params = g_variant_new ("(@a{sv}s)", props, alias);
-	proxy = G_DBUS_PROXY (self);
-
-	g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
-	                        g_dbus_proxy_get_name (proxy),
-	                        g_dbus_proxy_get_object_path (proxy),
-	                        SECRET_SERVICE_INTERFACE,
-	                        "CreateCollection", params, G_VARIANT_TYPE ("(oo)"),
-	                        G_DBUS_CALL_FLAGS_NONE, -1,
-	                        closure->cancellable,
-	                        on_create_collection_called,
-	                        g_object_ref (res));
-
-	g_object_unref (res);
-
-}
-
-/**
- * secret_service_create_collection_path_finish:
- * @self: a secret service object
- * @result: the asynchronous result passed to the callback
- * @error: location to place an error on failure
- *
- * Finish asynchronous operation to create a new collection in the secret
- * service.
- *
- * Returns: (transfer full): a new string containing the D-Bus object path
- *          of the collection
- */
-gchar *
-secret_service_create_collection_path_finish (SecretService *self,
-                                              GAsyncResult *result,
-                                              GError **error)
-{
-	GSimpleAsyncResult *res;
-	CollectionClosure *closure;
-	gchar *path;
-
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      secret_service_create_collection_path), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-
-	if (g_simple_async_result_propagate_error (res, error))
-		return NULL;
-
-	closure = g_simple_async_result_get_op_res_gpointer (res);
-	path = closure->collection_path;
-	closure->collection_path = NULL;
-	return path;
-}
-
-/**
- * secret_service_create_collection_path_sync:
- * @self: a secret service object
- * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
- *              for the new collection
- * @alias: (allow-none): an alias to check for before creating the new
- *         collection, or to assign to the new collection
- * @cancellable: optional cancellation object
- * @error: location to place an error on failure
- *
- * Create a new collection in the secret service and return its path.
- *
- * Using this method requires that you setup a correct hash table of D-Bus
- * properties for the new collection. You may prefer to use
- * secret_collection_create() which does handles this for you.
- *
- * An @alias is a well-known tag for a collection, such as 'default' (ie: the
- * default collection to store items in). This allows other applications to
- * easily identify and share a collection. If a collection with the @alias
- * already exists, then instead of creating a new collection, the existing
- * collection will be returned. If no collection with this alias exists, then
- * a new collection will be created and this alias will be assigned to it.
- *
- * @properties is a set of properties for the new collection. The keys in the
- * hash table should be interface.property strings like
- * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
- * in the hash table should be #GVariant values of the properties.
- *
- * This method may block indefinitely and should not be used in user interface
- * threads. The secret service may prompt the user. secret_service_prompt()
- * will be used to handle any prompts that are required.
- *
- * Returns: (transfer full): a new string containing the D-Bus object path
- *          of the collection
- */
-gchar *
-secret_service_create_collection_path_sync (SecretService *self,
-                                            GHashTable *properties,
-                                            const gchar *alias,
-                                            GCancellable *cancellable,
-                                            GError **error)
-{
-	SecretSync *sync;
-	gchar *path;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (properties != NULL, NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_create_collection_path (self, properties, alias, cancellable,
-	                                       _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	path = secret_service_create_collection_path_finish (self, sync->result, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return path;
-}
-
-typedef struct {
-	GCancellable *cancellable;
-	GVariant *properties;
-	SecretValue *value;
-	gboolean replace;
-	gchar *collection_path;
-	SecretPrompt *prompt;
-	gchar *item_path;
-} ItemClosure;
-
-static void
-item_closure_free (gpointer data)
-{
-	ItemClosure *closure = data;
-	g_variant_unref (closure->properties);
-	secret_value_unref (closure->value);
-	g_clear_object (&closure->cancellable);
-	g_free (closure->collection_path);
-	g_clear_object (&closure->prompt);
-	g_slice_free (ItemClosure, closure);
-}
-
-static void
-on_create_item_prompt (GObject *source,
-                       GAsyncResult *result,
-                       gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	GError *error = NULL;
-	GVariant *value;
-
-	value = secret_service_prompt_finish (SECRET_SERVICE (source), result,
-	                                      G_VARIANT_TYPE ("o"), &error);
-	if (error != NULL)
-		g_simple_async_result_take_error (res, error);
-	if (value != NULL) {
-		closure->item_path = g_variant_dup_string (value, NULL);
-		g_variant_unref (value);
-	}
-
-	g_simple_async_result_complete (res);
-	g_object_unref (res);
-}
-
-static void
-on_create_item_called (GObject *source,
-                       GAsyncResult *result,
-                       gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
-	const gchar *prompt_path = NULL;
-	const gchar *item_path = NULL;
-	GError *error = NULL;
-	GVariant *retval;
-
-	retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
-	if (error == NULL) {
-		g_variant_get (retval, "(&o&o)", &item_path, &prompt_path);
-		if (!_secret_util_empty_path (prompt_path)) {
-			closure->prompt = _secret_prompt_instance (self, prompt_path);
-			secret_service_prompt (self, closure->prompt,
-			                       closure->cancellable, on_create_item_prompt,
-			                       g_object_ref (res));
-
-		} else {
-			closure->item_path = g_strdup (item_path);
-			g_simple_async_result_complete (res);
-		}
-
-		g_variant_unref (retval);
-
-	} else {
-		g_simple_async_result_take_error (res, error);
-		g_simple_async_result_complete (res);
-	}
-
-	g_object_unref (self);
-	g_object_unref (res);
-}
-
-static void
-on_create_item_session (GObject *source,
-                        GAsyncResult *result,
-                        gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	SecretService *self = SECRET_SERVICE (source);
-	SecretSession *session;
-	GVariant *params;
-	GError *error = NULL;
-	GDBusProxy *proxy;
-
-	secret_service_ensure_session_finish (self, result, &error);
-	if (error == NULL) {
-		session = _secret_service_get_session (self);
-		params = g_variant_new ("(@a{sv}@(oayays)b)",
-		                        closure->properties,
-		                        _secret_session_encode_secret (session, closure->value),
-		                        closure->replace);
-
-		proxy = G_DBUS_PROXY (self);
-		g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
-		                        g_dbus_proxy_get_name (proxy),
-		                        closure->collection_path,
-		                        SECRET_COLLECTION_INTERFACE,
-		                        "CreateItem", params, G_VARIANT_TYPE ("(oo)"),
-		                        G_DBUS_CALL_FLAGS_NONE, -1,
-		                        closure->cancellable,
-		                        on_create_item_called,
-		                        g_object_ref (res));
-	} else {
-		g_simple_async_result_take_error (res, error);
-		g_simple_async_result_complete (res);
-	}
-
-	g_object_unref (res);
-}
-
-/**
- * secret_service_create_item_path:
- * @self: a secret service object
- * @collection_path: (allow-none): the D-Bus object path of the collection in which to create item
- * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
- *              for the new collection
- * @value: the secret value to store in the item
- * @replace: whether to replace an item with the matching attributes
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to be passed to the callback
- *
- * Create a new item in a secret service collection and return its D-Bus
- * object path.
- *
- * It is often easier to use secret_password_store() or secret_item_create()
- * rather than using this function. Using this method requires that you setup
- * a correct hash table of D-Bus @properties for the new collection.
- *
- * If @replace is set to %TRUE, and an item already in the collection matches
- * the attributes (specified in @properties) then the item will be updated
- * instead of creating a new item.
- *
- * @properties is a set of properties for the new collection. The keys in the
- * hash table should be interface.property strings like
- * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
- * in the hash table should be #GVariant values of the properties.
- *
- * If @collection_path is %NULL, then the default collection will be
- * used. Use #SECRET_COLLECTION_SESSION to store the password in the session
- * collection, which doesn't get stored across login sessions.
- *
- * This method will return immediately and complete asynchronously. The secret
- * service may prompt the user. secret_service_prompt() will be used to handle
- * any prompts that are required.
- */
-void
-secret_service_create_item_path (SecretService *self,
-                                 const gchar *collection_path,
-                                 GHashTable *properties,
-                                 SecretValue *value,
-                                 gboolean replace,
-                                 GCancellable *cancellable,
-                                 GAsyncReadyCallback callback,
-                                 gpointer user_data)
-{
-	GSimpleAsyncResult *res;
-	ItemClosure *closure;
-
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (properties != NULL);
-	g_return_if_fail (value != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	if (collection_path == NULL)
-		collection_path = SECRET_COLLECTION_DEFAULT;
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 secret_service_create_item_path);
-	closure = g_slice_new0 (ItemClosure);
-	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	closure->properties = _secret_util_variant_for_properties (properties);
-	g_variant_ref_sink (closure->properties);
-	closure->replace = replace;
-	closure->value = secret_value_ref (value);
-	closure->collection_path = g_strdup (collection_path);
-	g_simple_async_result_set_op_res_gpointer (res, closure, item_closure_free);
-
-	secret_service_ensure_session (self, cancellable,
-	                               on_create_item_session,
-	                               g_object_ref (res));
-
-	g_object_unref (res);
-}
-
-/**
- * secret_service_create_item_path_finish:
- * @self: a secret service object
- * @result: the asynchronous result passed to the callback
- * @error: location to place an error on failure
- *
- * Finish asynchronous operation to create a new item in the secret
- * service.
- *
- * Returns: (transfer full): a new string containing the D-Bus object path
- *          of the item
+ * Returns: whether the removal was successful or not
  */
-gchar *
-secret_service_create_item_path_finish (SecretService *self,
-                                        GAsyncResult *result,
-                                        GError **error)
+gboolean
+secret_service_remove_finish (SecretService *self,
+                              GAsyncResult *result,
+                              GError **error)
 {
 	GSimpleAsyncResult *res;
-	ItemClosure *closure;
-	gchar *path;
+	DeleteClosure *closure;
 
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      secret_service_create_item_path), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+	                      secret_service_remove), FALSE);
 
 	res = G_SIMPLE_ASYNC_RESULT (result);
-
 	if (g_simple_async_result_propagate_error (res, error))
-		return NULL;
+		return FALSE;
 
 	closure = g_simple_async_result_get_op_res_gpointer (res);
-	path = closure->item_path;
-	closure->item_path = NULL;
-	return path;
+	return closure->deleted;
 }
 
 /**
- * secret_service_create_item_path_sync:
- * @self: a secret service object
- * @collection_path: (allow-none): the D-Bus path of the collection in which to create item
- * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
- *              for the new collection
- * @value: the secret value to store in the item
- * @replace: whether to replace an item with the matching attributes
+ * secret_service_remove_sync:
+ * @self: the secret service
+ * @schema: (allow-none): the schema for the attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
  * @cancellable: optional cancellation object
  * @error: location to place an error on failure
  *
- * Create a new item in a secret service collection and return its D-Bus
- * object path.
- *
- * It is often easier to use secret_password_store_sync() or secret_item_create_sync()
- * rather than using this function. Using this method requires that you setup
- * a correct hash table of D-Bus @properties for the new collection.
+ * Remove a secret value from the secret service.
  *
- * If @replace is set to %TRUE, and an item already in the collection matches
- * the attributes (specified in @properties) then the item will be updated
- * instead of creating a new item.
+ * The @attributes should be a set of key and value string pairs.
  *
- * @properties is a set of properties for the new collection. The keys in the
- * hash table should be interface.property strings like
- * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
- * in the hash table should be #GVariant values of the properties.
+ * If multiple items match the attributes, then only one will be deleted.
  *
  * This method may block indefinitely and should not be used in user interface
- * threads. The secret service may prompt the user. secret_service_prompt()
- * will be used to handle any prompts that are required.
+ * threads.
  *
- * Returns: (transfer full): a new string containing the D-Bus object path
- *          of the item
+ * Returns: whether the removal was successful or not
  */
-gchar *
-secret_service_create_item_path_sync (SecretService *self,
-                                      const gchar *collection_path,
-                                      GHashTable *properties,
-                                      SecretValue *value,
-                                      gboolean replace,
-                                      GCancellable *cancellable,
-                                      GError **error)
+gboolean
+secret_service_remove_sync (SecretService *self,
+                            const SecretSchema *schema,
+                            GHashTable *attributes,
+                            GCancellable *cancellable,
+                            GError **error)
 {
 	SecretSync *sync;
-	gchar *path;
+	gboolean result;
 
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (properties != NULL, NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	/* Warnings raised already */
+	if (schema != NULL && !_secret_attributes_validate (schema, attributes))
+		return FALSE;
 
 	sync = _secret_sync_new ();
 	g_main_context_push_thread_default (sync->context);
 
-	secret_service_create_item_path (self, collection_path, properties, value, replace,
-	                                 cancellable, _secret_sync_on_result, sync);
+	secret_service_remove (self, schema, attributes, cancellable,
+	                       _secret_sync_on_result, sync);
 
 	g_main_loop_run (sync->loop);
 
-	path = secret_service_create_item_path_finish (self, sync->result, error);
+	result = secret_service_remove_finish (self, sync->result, error);
 
 	g_main_context_pop_thread_default (sync->context);
 	_secret_sync_free (sync);
 
-	return path;
+	return result;
 }
 
 typedef struct {
@@ -3342,117 +1864,6 @@ secret_service_read_alias_sync (SecretService *self,
 }
 
 /**
- * secret_service_read_alias_path:
- * @self: a secret service object
- * @alias: the alias to lookup
- * @cancellable: (allow-none): optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Lookup which collection is assigned to this alias. Aliases help determine
- * well known collections, such as 'default'. This method looks up the
- * dbus object path of the well known collection.
- *
- * This method will return immediately and complete asynchronously.
- */
-void
-secret_service_read_alias_path (SecretService *self,
-                                const gchar *alias,
-                                GCancellable *cancellable,
-                                GAsyncReadyCallback callback,
-                                gpointer user_data)
-{
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (alias != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	g_dbus_proxy_call (G_DBUS_PROXY (self), "ReadAlias",
-	                   g_variant_new ("(s)", alias),
-	                   G_DBUS_CALL_FLAGS_NONE, -1,
-	                   cancellable, callback, user_data);
-}
-
-/**
- * secret_service_read_alias_path_finish:
- * @self: a secret service object
- * @result: asynchronous result passed to callback
- * @error: location to place error on failure
- *
- * Finish an asynchronous operation to lookup which collection is assigned
- * to an alias. This method returns the DBus object path of the collection
- *
- * Returns: (transfer full): the collection dbus object path, or %NULL if
- *          none assigned to the alias
- */
-gchar *
-secret_service_read_alias_path_finish (SecretService *self,
-                                       GAsyncResult *result,
-                                       GError **error)
-{
-	gchar *collection_path;
-	GVariant *retval;
-
-	retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
-	if (retval == NULL)
-		return NULL;
-
-	g_variant_get (retval, "(o)", &collection_path);
-	g_variant_unref (retval);
-
-	if (g_str_equal (collection_path, "/")) {
-		g_free (collection_path);
-		collection_path = NULL;
-	}
-
-	return collection_path;
-}
-
-/**
- * secret_service_read_alias_path_sync:
- * @self: a secret service object
- * @alias: the alias to lookup
- * @cancellable: (allow-none): optional cancellation object
- * @error: location to place error on failure
- *
- * Lookup which collection is assigned to this alias. Aliases help determine
- * well known collections, such as 'default'. This method returns the dbus
- * object path of the collection.
- *
- * This method may block and should not be used in user interface threads.
- *
- * Returns: (transfer full): the collection dbus object path, or %NULL if
- *          none assigned to the alias
- */
-gchar *
-secret_service_read_alias_path_sync (SecretService *self,
-                                     const gchar *alias,
-                                     GCancellable *cancellable,
-                                     GError **error)
-{
-	SecretSync *sync;
-	gchar *collection_path;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (alias != NULL, NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_read_alias_path (self, alias, cancellable, _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	collection_path = secret_service_read_alias_path_finish (self, sync->result, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return collection_path;
-}
-
-/**
  * secret_service_set_alias:
  * @self: a secret service object
  * @alias: the alias to assign the collection to
@@ -3558,121 +1969,3 @@ secret_service_set_alias_sync (SecretService *self,
 
 	return ret;
 }
-
-/**
- * secret_service_set_alias_path:
- * @self: a secret service object
- * @alias: the alias to assign the collection to
- * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
- * @cancellable: (allow-none): optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to pass to the callback
- *
- * Assign a collection to this alias. Aliases help determine
- * well known collections, such as 'default'. This method takes the dbus object
- * path of the collection to assign to the alias.
- *
- * This method will return immediately and complete asynchronously.
- */
-void
-secret_service_set_alias_path (SecretService *self,
-                               const gchar *alias,
-                               const gchar *collection_path,
-                               GCancellable *cancellable,
-                               GAsyncReadyCallback callback,
-                               gpointer user_data)
-{
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (alias != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	if (collection_path == NULL)
-		collection_path = "/";
-	else
-		g_return_if_fail (g_variant_is_object_path (collection_path));
-
-	g_dbus_proxy_call (G_DBUS_PROXY (self), "SetAlias",
-	                   g_variant_new ("(so)", alias, collection_path),
-	                   G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
-	                   callback, user_data);
-}
-
-/**
- * secret_service_set_alias_path_finish:
- * @self: a secret service object
- * @result: asynchronous result passed to callback
- * @error: location to place error on failure
- *
- * Finish an asynchronous operation to assign a collection to an alias.
- *
- * Returns: %TRUE if successful
- */
-gboolean
-secret_service_set_alias_path_finish (SecretService *self,
-                                      GAsyncResult *result,
-                                      GError **error)
-{
-	GVariant *retval;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
-	if (retval == NULL)
-		return FALSE;
-
-	g_variant_unref (retval);
-	return TRUE;
-}
-
-/**
- * secret_service_set_alias_path_sync:
- * @self: a secret service object
- * @alias: the alias to assign the collection to
- * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
- * @cancellable: (allow-none): optional cancellation object
- * @error: location to place error on failure
- *
- * Assign a collection to this alias. Aliases help determine
- * well known collections, such as 'default'. This method takes the dbus object
- * path of the collection to assign to the alias.
- *
- * This method may block and should not be used in user interface threads.
- *
- * Returns: %TRUE if successful
- */
-gboolean
-secret_service_set_alias_path_sync (SecretService *self,
-                                    const gchar *alias,
-                                    const gchar *collection_path,
-                                    GCancellable *cancellable,
-                                    GError **error)
-{
-	SecretSync *sync;
-	gboolean ret;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (alias != NULL, FALSE);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (collection_path == NULL)
-		collection_path = "/";
-	else
-		g_return_val_if_fail (g_variant_is_object_path (collection_path), FALSE);
-
-	sync = _secret_sync_new ();
-	g_main_context_push_thread_default (sync->context);
-
-	secret_service_set_alias_path (self, alias, collection_path,
-	                               cancellable, _secret_sync_on_result, sync);
-
-	g_main_loop_run (sync->loop);
-
-	ret = secret_service_set_alias_path_finish (self, sync->result, error);
-
-	g_main_context_pop_thread_default (sync->context);
-	_secret_sync_free (sync);
-
-	return ret;
-}
diff --git a/library/secret-paths.c b/library/secret-paths.c
new file mode 100644
index 0000000..6919d87
--- /dev/null
+++ b/library/secret-paths.c
@@ -0,0 +1,2054 @@
+/* libsecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ * Copyright 2012 Red Hat Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw gnome org>
+ */
+
+#include "config.h"
+
+#include "secret-dbus-generated.h"
+#include "secret-paths.h"
+#include "secret-private.h"
+#include "secret-service.h"
+#include "secret-types.h"
+#include "secret-value.h"
+
+
+/**
+ * SECTION:secret-paths
+ * @title: DBus Path Related Functions
+ * @short_description: Secret Service functions which operate on DBus object paths
+ *
+ * These are low level functions which operate on DBus object paths of
+ * collections or items, instead of the #SecretCollection or #SecretItem
+ * objects themselves.
+ *
+ * You can use these functions if you wish to manage access to the secret
+ * service using the DBus API directly, and only wish to use a few calls
+ * in libsecret.
+ *
+ * Stability: Unstable
+ */
+
+static void
+on_search_items_complete (GObject *source,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	GError *error = NULL;
+	GVariant *response;
+
+	response = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
+	if (error != NULL)
+		g_simple_async_result_take_error (res, error);
+	else
+		g_simple_async_result_set_op_res_gpointer (res, response,
+		                                           (GDestroyNotify)g_variant_unref);
+
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_search_for_paths:
+ * @self: the secret service
+ * @attributes: (element-type utf8 utf8): search for items matching these attributes
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Search for items matching the @attributes, and return their D-Bus object paths.
+ * All collections are searched. The @attributes should be a table of string keys
+ * and string values.
+ *
+ * This function returns immediately and completes asynchronously.
+ *
+ * When your callback is called use secret_service_search_for_paths_finish()
+ * to get the results of this function. Only the D-Bus object paths of the
+ * items will be returned. If you would like #SecretItem objects to be returned
+ * instead, then use the secret_service_search() function.
+ */
+void
+secret_service_search_for_paths (SecretService *self,
+                                 GHashTable *attributes,
+                                 GCancellable *cancellable,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (attributes != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	_secret_service_search_for_paths_variant (self, _secret_attributes_to_variant (attributes, NULL),
+	                                          cancellable, callback, user_data);
+}
+
+void
+_secret_service_search_for_paths_variant (SecretService *self,
+                                          GVariant *attributes,
+                                          GCancellable *cancellable,
+                                          GAsyncReadyCallback callback,
+                                          gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (attributes != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 secret_service_search_for_paths);
+
+	g_dbus_proxy_call (G_DBUS_PROXY (self), "SearchItems",
+	                   g_variant_new ("(@a{ss})", attributes),
+	                   G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
+	                   on_search_items_complete, g_object_ref (res));
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_search_for_paths_finish:
+ * @self: the secret service
+ * @result: asynchronous result passed to callback
+ * @unlocked: (out) (transfer full) (array zero-terminated=1) (allow-none):
+ *            location to place an array of D-Bus object paths for matching
+ *            items which were locked.
+ * @locked: (out) (transfer full) (array zero-terminated=1) (allow-none):
+ *          location to place an array of D-Bus object paths for matching
+ *          items which were locked.
+ * @error: location to place error on failure
+ *
+ * Complete asynchronous operation to search for items, and return their
+ * D-Bus object paths.
+ *
+ * Matching items that are locked or unlocked, have their D-Bus paths placed
+ * in the @locked or @unlocked arrays respectively.
+ *
+ * D-Bus object paths of the items will be returned in the @unlocked or
+ * @locked arrays. If you would to have #SecretItem objects to be returned
+ * instead, then us the secret_service_search() and
+ * secret_service_search_finish() functions.
+ *
+ * Returns: whether the search was successful or not
+ */
+gboolean
+secret_service_search_for_paths_finish (SecretService *self,
+                                        GAsyncResult *result,
+                                        gchar ***unlocked,
+                                        gchar ***locked,
+                                        GError **error)
+{
+	GVariant *response;
+	GSimpleAsyncResult *res;
+	gchar **dummy = NULL;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      secret_service_search_for_paths), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (res, error))
+		return FALSE;
+
+	if (unlocked || locked) {
+		if (!unlocked)
+			unlocked = &dummy;
+		else if (!locked)
+			locked = &dummy;
+		response = g_simple_async_result_get_op_res_gpointer (res);
+		g_variant_get (response, "(^ao^ao)", unlocked, locked);
+	}
+
+	g_strfreev (dummy);
+	return TRUE;
+}
+
+/**
+ * secret_service_search_for_paths_sync:
+ * @self: the secret service
+ * @attributes: (element-type utf8 utf8): search for items matching these attributes
+ * @cancellable: optional cancellation object
+ * @unlocked: (out) (transfer full) (array zero-terminated=1) (allow-none):
+ *            location to place an array of D-Bus object paths for matching
+ *            items which were locked.
+ * @locked: (out) (transfer full) (array zero-terminated=1) (allow-none):
+ *          location to place an array of D-Bus object paths for matching
+ *          items which were locked.
+ * @error: location to place error on failure
+ *
+ * Search for items matching the @attributes, and return their D-Bus object
+ * paths. All collections are searched. The @attributes should be a table of
+ * string keys and string values.
+ *
+ * This function may block indefinetely. Use the asynchronous version
+ * in user interface threads.
+ *
+ * Matching items that are locked or unlocked, have their D-Bus paths placed
+ * in the @locked or @unlocked arrays respectively.
+ *
+ * D-Bus object paths of the items will be returned in the @unlocked or
+ * @locked arrays. If you would to have #SecretItem objects to be returned
+ * instead, then use the secret_service_search_sync() function.
+ *
+ * Returns: whether the search was successful or not
+ */
+gboolean
+secret_service_search_for_paths_sync (SecretService *self,
+                                      GHashTable *attributes,
+                                      GCancellable *cancellable,
+                                      gchar ***unlocked,
+                                      gchar ***locked,
+                                      GError **error)
+{
+	gchar **dummy = NULL;
+	GVariant *response;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+	g_return_val_if_fail (attributes != NULL, FALSE);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	response = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "SearchItems",
+	                                   g_variant_new ("(@a{ss})",
+	                                                  _secret_attributes_to_variant (attributes, NULL)),
+	                                   G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error);
+
+	if (response != NULL) {
+		if (unlocked || locked) {
+			if (!unlocked)
+				unlocked = &dummy;
+			else if (!locked)
+				locked = &dummy;
+			g_variant_get (response, "(^ao^ao)", unlocked, locked);
+		}
+
+		g_variant_unref (response);
+	}
+
+	g_strfreev (dummy);
+
+	return response != NULL;
+}
+
+typedef struct {
+	GCancellable *cancellable;
+	GVariant *in;
+	GVariant *out;
+	GHashTable *items;
+} GetClosure;
+
+static void
+get_closure_free (gpointer data)
+{
+	GetClosure *closure = data;
+	if (closure->in)
+		g_variant_unref (closure->in);
+	if (closure->out)
+		g_variant_unref (closure->out);
+	g_clear_object (&closure->cancellable);
+	g_slice_free (GetClosure, closure);
+}
+
+static void
+on_get_secrets_complete (GObject *source,
+                         GAsyncResult *result,
+                         gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	GetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+
+	closure->out = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
+	if (error != NULL)
+		g_simple_async_result_take_error (res, error);
+	g_simple_async_result_complete (res);
+
+	g_object_unref (res);
+}
+
+static void
+on_get_secrets_session (GObject *source,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	GetClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+	const gchar *session;
+
+	session = secret_service_ensure_session_finish (SECRET_SERVICE (source),
+	                                                result, &error);
+	if (error != NULL) {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete (res);
+	} else {
+		g_dbus_proxy_call (G_DBUS_PROXY (source), "GetSecrets",
+		                   g_variant_new ("(@aoo)", closure->in, session),
+		                   G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+		                   closure->cancellable, on_get_secrets_complete,
+		                   g_object_ref (res));
+	}
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_get_secret_for_path:
+ * @self: the secret service
+ * @item_path: the D-Bus path to item to retrieve secret for
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Get the secret value for an secret item stored in the service.
+ *
+ * The item is represented by its D-Bus object path. If you already have a
+ * #SecretItem proxy object, use use secret_item_get_secret() to more simply
+ * get its secret value.
+ *
+ * This function returns immediately and completes asynchronously.
+ */
+void
+secret_service_get_secret_for_path (SecretService *self,
+                                    const gchar *item_path,
+                                    GCancellable *cancellable,
+                                    GAsyncReadyCallback callback,
+                                    gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+	GetClosure *closure;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (item_path != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 secret_service_get_secret_for_path);
+
+	closure = g_slice_new0 (GetClosure);
+	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	closure->in = g_variant_ref_sink (g_variant_new_objv (&item_path, 1));
+	g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
+
+	secret_service_ensure_session (self, cancellable,
+	                               on_get_secrets_session,
+	                               g_object_ref (res));
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_get_secret_for_path_finish:
+ * @self: the secret service
+ * @result: asynchronous result passed to callback
+ * @error: location to place an error on failure
+ *
+ * Complete asynchronous operation to get the secret value for an
+ * secret item stored in the service.
+ *
+ * Will return %NULL if the item is locked.
+ *
+ * Returns: (transfer full) (allow-none): the newly allocated secret value
+ *          for the item, which should be released with secret_value_unref()
+ */
+SecretValue *
+secret_service_get_secret_for_path_finish (SecretService *self,
+                                           GAsyncResult *result,
+                                           GError **error)
+{
+	GSimpleAsyncResult *res;
+	GetClosure *closure;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      secret_service_get_secret_for_path), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (res, error))
+		return NULL;
+
+	closure = g_simple_async_result_get_op_res_gpointer (res);
+	return _secret_service_decode_get_secrets_first (self, closure->out);
+}
+
+/**
+ * secret_service_get_secret_for_path_sync:
+ * @self: the secret service
+ * @item_path: the D-Bus path to item to retrieve secret for
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Get the secret value for an secret item stored in the service.
+ *
+ * The item is represented by its D-Bus object path. If you already have a
+ * #SecretItem proxy object, use use secret_item_get_secret_sync() to more simply
+ * get its secret value.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Will return %NULL if the item is locked.
+ *
+ * Returns: (transfer full) (allow-none): the newly allocated secret value
+ *          for the item, which should be released with secret_value_unref()
+ */
+SecretValue *
+secret_service_get_secret_for_path_sync (SecretService *self,
+                                         const gchar *item_path,
+                                         GCancellable *cancellable,
+                                         GError **error)
+{
+	SecretSync *sync;
+	SecretValue *value;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (item_path != NULL, NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_get_secret_for_path (self, item_path, cancellable,
+	                                    _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	value = secret_service_get_secret_for_path_finish (self, sync->result, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return value;
+}
+
+/**
+ * secret_service_get_secrets_for_paths:
+ * @self: the secret service
+ * @item_paths: the D-Bus paths to items to retrieve secrets for
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Get the secret values for an secret items stored in the service.
+ *
+ * The items are represented by their D-Bus object paths. If you already have
+ * #SecretItem proxy objects, use use secret_service_get_secrets() to more simply
+ * get their secret values.
+ *
+ * This function returns immediately and completes asynchronously.
+ */
+void
+secret_service_get_secrets_for_paths (SecretService *self,
+                                      const gchar **item_paths,
+                                      GCancellable *cancellable,
+                                      GAsyncReadyCallback callback,
+                                      gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+	GetClosure *closure;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (item_paths != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 secret_service_get_secret_for_path);
+
+	closure = g_slice_new0 (GetClosure);
+	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	closure->in = g_variant_ref_sink (g_variant_new_objv (item_paths, -1));
+	g_simple_async_result_set_op_res_gpointer (res, closure, get_closure_free);
+
+	secret_service_ensure_session (self, cancellable,
+	                               on_get_secrets_session,
+	                               g_object_ref (res));
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_get_secrets_for_paths_finish:
+ * @self: the secret service
+ * @result: asynchronous result passed to callback
+ * @error: location to place an error on failure
+ *
+ * Complete asynchronous operation to get the secret values for an
+ * secret items stored in the service.
+ *
+ * Items that are locked will not be included the results.
+ *
+ * Returns: (transfer full): a newly allocated hash table of item_path keys to
+ *          #SecretValue values.
+ */
+GHashTable *
+secret_service_get_secrets_for_paths_finish (SecretService *self,
+                                             GAsyncResult *result,
+                                             GError **error)
+{
+	GSimpleAsyncResult *res;
+	GetClosure *closure;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      secret_service_get_secret_for_path), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (res, error))
+		return NULL;
+
+	closure = g_simple_async_result_get_op_res_gpointer (res);
+	return _secret_service_decode_get_secrets_all (self, closure->out);
+}
+
+/**
+ * secret_service_get_secrets_for_paths_sync:
+ * @self: the secret service
+ * @item_paths: the D-Bus paths to items to retrieve secrets for
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Get the secret values for an secret items stored in the service.
+ *
+ * The items are represented by their D-Bus object paths. If you already have
+ * #SecretItem proxy objects, use use secret_service_get_secrets_sync() to more
+ * simply get their secret values.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Items that are locked will not be included the results.
+ *
+ * Returns: (transfer full): a newly allocated hash table of item_path keys to
+ *          #SecretValue values.
+ */
+GHashTable *
+secret_service_get_secrets_for_paths_sync (SecretService *self,
+                                           const gchar **item_paths,
+                                           GCancellable *cancellable,
+                                           GError **error)
+{
+	SecretSync *sync;
+	GHashTable *secrets;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (item_paths != NULL, NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_get_secrets_for_paths (self, item_paths, cancellable,
+	                                      _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	secrets = secret_service_get_secrets_for_paths_finish (self, sync->result, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return secrets;
+}
+
+
+typedef struct {
+	GCancellable *cancellable;
+	SecretPrompt *prompt;
+	GHashTable *objects;
+	GPtrArray *xlocked;
+} XlockClosure;
+
+static void
+xlock_closure_free (gpointer data)
+{
+	XlockClosure *closure = data;
+	g_clear_object (&closure->cancellable);
+	g_clear_object (&closure->prompt);
+	if (closure->xlocked)
+		g_ptr_array_unref (closure->xlocked);
+	if (closure->objects)
+		g_hash_table_unref (closure->objects);
+	g_slice_free (XlockClosure, closure);
+}
+
+static void
+on_xlock_prompted (GObject *source,
+                   GAsyncResult *result,
+                   gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	XlockClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	SecretService *self = SECRET_SERVICE (source);
+	GError *error = NULL;
+	GVariantIter iter;
+	GVariant *retval;
+	gchar *path;
+
+	retval = secret_service_prompt_finish (self, result, G_VARIANT_TYPE ("ao"), &error);
+	if (error != NULL)
+		g_simple_async_result_take_error (res, error);
+
+	if (retval != NULL) {
+		g_variant_iter_init (&iter, retval);
+		while (g_variant_iter_loop (&iter, "o", &path))
+			g_ptr_array_add (closure->xlocked, g_strdup (path));
+		g_variant_unref (retval);
+	}
+
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
+
+static void
+on_xlock_called (GObject *source,
+                 GAsyncResult *result,
+                 gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	XlockClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
+	const gchar *prompt = NULL;
+	gchar **xlocked = NULL;
+	GError *error = NULL;
+	GVariant *retval;
+	guint i;
+
+	retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
+	if (error != NULL) {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete (res);
+
+	} else {
+		g_variant_get (retval, "(^ao&o)", &xlocked, &prompt);
+
+		if (_secret_util_empty_path (prompt)) {
+			for (i = 0; xlocked[i]; i++)
+				g_ptr_array_add (closure->xlocked, g_strdup (xlocked[i]));
+			g_simple_async_result_complete (res);
+
+		} else {
+			closure->prompt = _secret_prompt_instance (self, prompt);
+			secret_service_prompt (self, closure->prompt, closure->cancellable,
+			                        on_xlock_prompted, g_object_ref (res));
+		}
+
+		g_strfreev (xlocked);
+		g_variant_unref (retval);
+	}
+
+	g_object_unref (self);
+	g_object_unref (res);
+}
+
+static GSimpleAsyncResult *
+service_xlock_paths_async (SecretService *self,
+                           const gchar *method,
+                           const gchar **paths,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+	XlockClosure *closure;
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 service_xlock_paths_async);
+	closure = g_slice_new0 (XlockClosure);
+	closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
+	closure->xlocked = g_ptr_array_new_with_free_func (g_free);
+	g_simple_async_result_set_op_res_gpointer (res, closure, xlock_closure_free);
+
+	g_dbus_proxy_call (G_DBUS_PROXY (self), method,
+	                   g_variant_new ("(@ao)", g_variant_new_objv (paths, -1)),
+	                   G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+	                   cancellable, on_xlock_called, g_object_ref (res));
+
+	return res;
+}
+
+static gint
+service_xlock_paths_finish (SecretService *self,
+                            GAsyncResult *result,
+                            gchar ***xlocked,
+                            GError **error)
+{
+	GSimpleAsyncResult *res;
+	XlockClosure *closure;
+	gint count;
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (res, error))
+		return -1;
+
+	closure = g_simple_async_result_get_op_res_gpointer (res);
+	count = closure->xlocked->len;
+
+	if (xlocked != NULL) {
+		g_ptr_array_add (closure->xlocked, NULL);
+		*xlocked = (gchar **)g_ptr_array_free (closure->xlocked, FALSE);
+		closure->xlocked = NULL;
+	}
+
+	return count;
+}
+
+/**
+ * secret_service_lock_paths_sync:
+ * @self: the secret service
+ * @paths: the D-Bus object paths of the items or collections to lock
+ * @cancellable: optional cancellation object
+ * @locked: (out) (array zero-terminated=1) (transfer full) (allow-none):
+ *          location to place array of D-Bus paths of items or collections
+ *          that were locked
+ * @error: location to place an error on failure
+ *
+ * Lock items or collections in the secret service.
+ *
+ * The items or collections are represented by their D-Bus object paths. If you
+ * already have #SecretItem and #SecretCollection proxy objects, use use
+ * secret_service_lock_sync() instead.
+ *
+ * The secret service may not be able to lock items individually, and may
+ * lock an entire collection instead.
+ *
+ * This method may block indefinitely and should not be used in user
+ * interface threads. The secret service may prompt the user.
+ * secret_service_prompt() will be used to handle any prompts that show up.
+ *
+ * Returns: the number of items or collections that were locked
+ */
+gint
+secret_service_lock_paths_sync (SecretService *self,
+                                const gchar **paths,
+                                GCancellable *cancellable,
+                                gchar ***locked,
+                                GError **error)
+{
+	SecretSync *sync;
+	gint count;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
+	g_return_val_if_fail (paths != NULL, -1);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
+	g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_lock_paths (self, paths, cancellable,
+	                            _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	count = secret_service_lock_paths_finish (self, sync->result,
+	                                           locked, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return count;
+}
+
+/**
+ * secret_service_lock_paths:
+ * @self: the secret service
+ * @paths: the D-Bus paths for items or collections to lock
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Lock items or collections in the secret service.
+ *
+ * The items or collections are represented by their D-Bus object paths. If you
+ * already have #SecretItem and #SecretCollection proxy objects, use use
+ * secret_service_lock() instead.
+ *
+ * The secret service may not be able to lock items individually, and may
+ * lock an entire collection instead.
+ *
+ * This method returns immediately and completes asynchronously. The secret
+ * service may prompt the user. secret_service_prompt() will be used to handle
+ * any prompts that show up.
+ */
+void
+secret_service_lock_paths (SecretService *self,
+                           const gchar **paths,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (paths != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	res = service_xlock_paths_async (self, "Lock", paths, cancellable,
+	                                 callback, user_data);
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_lock_paths_finish:
+ * @self: the secret service
+ * @result: asynchronous result passed to the callback
+ * @locked: (out) (array zero-terminated=1) (transfer full) (allow-none):
+ *          location to place array of D-Bus paths of items or collections
+ *          that were locked
+ * @error: location to place an error on failure
+ *
+ * Complete asynchronous operation to lock items or collections in the secret
+ * service.
+ *
+ * The secret service may not be able to lock items individually, and may
+ * lock an entire collection instead.
+ *
+ * Returns: the number of items or collections that were locked
+ */
+gint
+secret_service_lock_paths_finish (SecretService *self,
+                                  GAsyncResult *result,
+                                  gchar ***locked,
+                                  GError **error)
+{
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
+	g_return_val_if_fail (locked != NULL, -1);
+	g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+	return service_xlock_paths_finish (self, result, locked, error);
+}
+
+/**
+ * secret_service_unlock_paths_sync:
+ * @self: the secret service
+ * @paths: the D-Bus object paths of the items or collections to unlock
+ * @cancellable: optional cancellation object
+ * @unlocked: (out) (array zero-terminated=1) (transfer full) (allow-none):
+ *            location to place array of D-Bus paths of items or collections
+ *            that were unlocked
+ * @error: location to place an error on failure
+ *
+ * Unlock items or collections in the secret service.
+ *
+ * The items or collections are represented by their D-Bus object paths. If you
+ * already have #SecretItem and #SecretCollection proxy objects, use use
+ * secret_service_unlock_sync() instead.
+ *
+ * The secret service may not be able to unlock items individually, and may
+ * unlock an entire collection instead.
+ *
+ * This method may block indefinitely and should not be used in user
+ * interface threads. The secret service may prompt the user.
+ * secret_service_prompt() will be used to handle any prompts that show up.
+ *
+ * Returns: the number of items or collections that were unlocked
+ */
+gint
+secret_service_unlock_paths_sync (SecretService *self,
+                                  const gchar **paths,
+                                  GCancellable *cancellable,
+                                  gchar ***unlocked,
+                                  GError **error)
+{
+	SecretSync *sync;
+	gint count;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
+	g_return_val_if_fail (paths != NULL, -1);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
+	g_return_val_if_fail (unlocked != NULL, -1);
+	g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_unlock_paths (self, paths, cancellable,
+	                              _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	count = secret_service_unlock_paths_finish (self, sync->result,
+	                                             unlocked, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return count;
+}
+
+/**
+ * secret_service_unlock_paths:
+ * @self: the secret service
+ * @paths: the D-Bus paths for items or collections to unlock
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Unlock items or collections in the secret service.
+ *
+ * The items or collections are represented by their D-Bus object paths. If you
+ * already have #SecretItem and #SecretCollection proxy objects, use use
+ * secret_service_unlock() instead.
+ *
+ * The secret service may not be able to unlock items individually, and may
+ * unlock an entire collection instead.
+ *
+ * This method returns immediately and completes asynchronously. The secret
+ * service may prompt the user. secret_service_prompt() will be used to handle
+ * any prompts that show up.
+ */
+void
+secret_service_unlock_paths (SecretService *self,
+                             const gchar **paths,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (paths != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	res = service_xlock_paths_async (self, "Unlock",
+	                                 paths, cancellable,
+	                                 callback, user_data);
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_unlock_paths_finish:
+ * @self: the secret service
+ * @result: asynchronous result passed to the callback
+ * @unlocked: (out) (array zero-terminated=1) (transfer full) (allow-none):
+ *            location to place array of D-Bus paths of items or collections
+ *            that were unlocked
+ * @error: location to place an error on failure
+ *
+ * Complete asynchronous operation to unlock items or collections in the secret
+ * service.
+ *
+ * The secret service may not be able to unlock items individually, and may
+ * unlock an entire collection instead.
+ *
+ * Returns: the number of items or collections that were unlocked
+ */
+gint
+secret_service_unlock_paths_finish (SecretService *self,
+                                    GAsyncResult *result,
+                                    gchar ***unlocked,
+                                    GError **error)
+{
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), -1);
+	g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+	return service_xlock_paths_finish (self, result,
+	                                   unlocked, error);
+}
+
+typedef struct {
+	GCancellable *cancellable;
+	SecretPrompt *prompt;
+	gboolean deleted;
+} DeleteClosure;
+
+static void
+delete_closure_free (gpointer data)
+{
+	DeleteClosure *closure = data;
+	g_clear_object (&closure->prompt);
+	g_clear_object (&closure->cancellable);
+	g_slice_free (DeleteClosure, closure);
+}
+
+static void
+on_delete_prompted (GObject *source,
+                    GAsyncResult *result,
+                    gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+	GVariant *retval;
+
+	retval = secret_service_prompt_finish (SECRET_SERVICE (source), result,
+	                                       NULL, &error);
+
+	if (error == NULL)
+		closure->deleted = TRUE;
+	else
+		g_simple_async_result_take_error (res, error);
+	if (retval != NULL)
+		g_variant_unref (retval);
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
+
+static void
+on_delete_complete (GObject *source,
+                    GAsyncResult *result,
+                    gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
+	const gchar *prompt_path;
+	GError *error = NULL;
+	GVariant *retval;
+
+	retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+	if (error == NULL) {
+		g_variant_get (retval, "(&o)", &prompt_path);
+
+		if (_secret_util_empty_path (prompt_path)) {
+			closure->deleted = TRUE;
+			g_simple_async_result_complete (res);
+
+		} else {
+			closure->prompt = _secret_prompt_instance (self, prompt_path);
+
+			secret_service_prompt (self, closure->prompt,
+			                       closure->cancellable,
+			                       on_delete_prompted,
+			                       g_object_ref (res));
+		}
+
+		g_variant_unref (retval);
+
+	} else {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete (res);
+	}
+
+	g_object_unref (self);
+	g_object_unref (res);
+}
+
+void
+_secret_service_delete_path (SecretService *self,
+                             const gchar *object_path,
+                             gboolean is_an_item,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+	DeleteClosure *closure;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (object_path != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 _secret_service_delete_path);
+	closure = g_slice_new0 (DeleteClosure);
+	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
+
+	g_dbus_connection_call (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
+	                        g_dbus_proxy_get_name (G_DBUS_PROXY (self)), object_path,
+	                        is_an_item ? SECRET_ITEM_INTERFACE : SECRET_COLLECTION_INTERFACE,
+	                        "Delete", g_variant_new ("()"), G_VARIANT_TYPE ("(o)"),
+	                        G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+	                        cancellable, on_delete_complete, g_object_ref (res));
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_delete_path:
+ * @self: the secret service
+ * @item_path: the D-Bus path of item to delete
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Delete a secret item from the secret service.
+ *
+ * The item is represented by its D-Bus object path. If you already have a
+ * #SecretItem proxy objects, use use secret_item_delete() instead.
+ *
+ * This method will return immediately and complete asynchronously.
+ */
+void
+secret_service_delete_path (SecretService *self,
+                            const gchar *item_path,
+                            GCancellable *cancellable,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data)
+{
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (item_path != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	_secret_service_delete_path (self, item_path, TRUE, cancellable, callback, user_data);
+}
+
+/**
+ * secret_service_delete_path_finish:
+ * @self: the secret service
+ * @result: the asynchronous result passed to the callback
+ * @error: location to place an error on failure
+ *
+ * Complete an asynchronous operation to delete a secret item from the secret
+ * service.
+ *
+ * Returns: whether the deletion was successful or not
+ */
+gboolean
+secret_service_delete_path_finish (SecretService *self,
+                                   GAsyncResult *result,
+                                   GError **error)
+{
+	GSimpleAsyncResult *res;
+	DeleteClosure *closure;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      _secret_service_delete_path), FALSE);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (res, error))
+		return FALSE;
+
+	closure = g_simple_async_result_get_op_res_gpointer (res);
+	return closure->deleted;
+}
+
+/**
+ * secret_service_delete_path_sync:
+ * @self: the secret service
+ * @item_path: the D-Bus path of item to delete
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Delete a secret item from the secret service.
+ *
+ * The item is represented by its D-Bus object path. If you already have a
+ * #SecretItem proxy objects, use use secret_item_delete_sync() instead.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: whether the deletion was successful or not
+ */
+gboolean
+secret_service_delete_path_sync (SecretService *self,
+                                 const gchar *item_path,
+                                 GCancellable *cancellable,
+                                 GError **error)
+{
+	SecretSync *sync;
+	gboolean result;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+	g_return_val_if_fail (item_path != NULL, FALSE);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_delete_path (self, item_path, cancellable,
+	                            _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	result = secret_service_delete_path_finish (self, sync->result, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return result;
+}
+
+typedef struct {
+	GCancellable *cancellable;
+	SecretPrompt *prompt;
+	gchar *collection_path;
+} CollectionClosure;
+
+static void
+collection_closure_free (gpointer data)
+{
+	CollectionClosure *closure = data;
+	g_clear_object (&closure->cancellable);
+	g_clear_object (&closure->prompt);
+	g_slice_free (CollectionClosure, closure);
+}
+
+static void
+on_create_collection_prompt (GObject *source,
+                             GAsyncResult *result,
+                             gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+	GVariant *value;
+
+	value = secret_service_prompt_finish (SECRET_SERVICE (source), result,
+	                                      G_VARIANT_TYPE ("o"), &error);
+	if (error != NULL)
+		g_simple_async_result_take_error (res, error);
+	if (value != NULL) {
+		closure->collection_path = g_variant_dup_string (value, NULL);
+		g_variant_unref (value);
+	}
+
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
+
+static void
+on_create_collection_called (GObject *source,
+                             GAsyncResult *result,
+                             gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
+	const gchar *prompt_path = NULL;
+	const gchar *collection_path = NULL;
+	GError *error = NULL;
+	GVariant *retval;
+
+	retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+	if (error == NULL) {
+		g_variant_get (retval, "(&o&o)", &collection_path, &prompt_path);
+		if (!_secret_util_empty_path (prompt_path)) {
+			closure->prompt = _secret_prompt_instance (self, prompt_path);
+			secret_service_prompt (self, closure->prompt,
+			                       closure->cancellable, on_create_collection_prompt,
+			                       g_object_ref (res));
+
+		} else {
+			closure->collection_path = g_strdup (collection_path);
+			g_simple_async_result_complete (res);
+		}
+
+		g_variant_unref (retval);
+
+	} else {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete (res);
+	}
+
+	g_object_unref (self);
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_create_collection_path:
+ * @self: a secret service object
+ * @properties: (element-type utf8 GLib.Variant): hash table of properties for
+ *              the new collection
+ * @alias: (allow-none): an alias to check for before creating the new
+ *         collection, or to assign to the new collection
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Create a new collection in the secret service, and return its path.
+ *
+ * Using this method requires that you setup a correct hash table of D-Bus
+ * properties for the new collection. You may prefer to use
+ * secret_collection_create() which does handles this for you.
+ *
+ * An @alias is a well-known tag for a collection, such as 'default' (ie: the
+ * default collection to store items in). This allows other applications to
+ * easily identify and share a collection. If a collection with the @alias
+ * already exists, then instead of creating a new collection, the existing
+ * collection will be returned. If no collection with this alias exists, then a
+ * new collection will be created and this alias will be assigned to it.
+ *
+ * @properties is a set of properties for the new collection. The keys in the
+ * hash table should be interface.property strings like
+ * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
+ * in the hash table should be #GVariant values of the properties.
+ *
+ * If you wish to have a
+ *
+ * This method will return immediately and complete asynchronously. The secret
+ * service may prompt the user. secret_service_prompt() will be used to handle
+ * any prompts that are required.
+ */
+void
+secret_service_create_collection_path (SecretService *self,
+                                       GHashTable *properties,
+                                       const gchar *alias,
+                                       GCancellable *cancellable,
+                                       GAsyncReadyCallback callback,
+                                       gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+	CollectionClosure *closure;
+	GVariant *params;
+	GVariant *props;
+	GDBusProxy *proxy;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (properties != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	if (alias == NULL)
+		alias = "";
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 secret_service_create_collection_path);
+	closure = g_slice_new0 (CollectionClosure);
+	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	g_simple_async_result_set_op_res_gpointer (res, closure, collection_closure_free);
+
+	props = _secret_util_variant_for_properties (properties);
+	params = g_variant_new ("(@a{sv}s)", props, alias);
+	proxy = G_DBUS_PROXY (self);
+
+	g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+	                        g_dbus_proxy_get_name (proxy),
+	                        g_dbus_proxy_get_object_path (proxy),
+	                        SECRET_SERVICE_INTERFACE,
+	                        "CreateCollection", params, G_VARIANT_TYPE ("(oo)"),
+	                        G_DBUS_CALL_FLAGS_NONE, -1,
+	                        closure->cancellable,
+	                        on_create_collection_called,
+	                        g_object_ref (res));
+
+	g_object_unref (res);
+
+}
+
+/**
+ * secret_service_create_collection_path_finish:
+ * @self: a secret service object
+ * @result: the asynchronous result passed to the callback
+ * @error: location to place an error on failure
+ *
+ * Finish asynchronous operation to create a new collection in the secret
+ * service.
+ *
+ * Returns: (transfer full): a new string containing the D-Bus object path
+ *          of the collection
+ */
+gchar *
+secret_service_create_collection_path_finish (SecretService *self,
+                                              GAsyncResult *result,
+                                              GError **error)
+{
+	GSimpleAsyncResult *res;
+	CollectionClosure *closure;
+	gchar *path;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      secret_service_create_collection_path), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (res, error))
+		return NULL;
+
+	closure = g_simple_async_result_get_op_res_gpointer (res);
+	path = closure->collection_path;
+	closure->collection_path = NULL;
+	return path;
+}
+
+/**
+ * secret_service_create_collection_path_sync:
+ * @self: a secret service object
+ * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
+ *              for the new collection
+ * @alias: (allow-none): an alias to check for before creating the new
+ *         collection, or to assign to the new collection
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Create a new collection in the secret service and return its path.
+ *
+ * Using this method requires that you setup a correct hash table of D-Bus
+ * properties for the new collection. You may prefer to use
+ * secret_collection_create() which does handles this for you.
+ *
+ * An @alias is a well-known tag for a collection, such as 'default' (ie: the
+ * default collection to store items in). This allows other applications to
+ * easily identify and share a collection. If a collection with the @alias
+ * already exists, then instead of creating a new collection, the existing
+ * collection will be returned. If no collection with this alias exists, then
+ * a new collection will be created and this alias will be assigned to it.
+ *
+ * @properties is a set of properties for the new collection. The keys in the
+ * hash table should be interface.property strings like
+ * <literal>org.freedesktop.Secret.Collection.Label</literal>. The values
+ * in the hash table should be #GVariant values of the properties.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads. The secret service may prompt the user. secret_service_prompt()
+ * will be used to handle any prompts that are required.
+ *
+ * Returns: (transfer full): a new string containing the D-Bus object path
+ *          of the collection
+ */
+gchar *
+secret_service_create_collection_path_sync (SecretService *self,
+                                            GHashTable *properties,
+                                            const gchar *alias,
+                                            GCancellable *cancellable,
+                                            GError **error)
+{
+	SecretSync *sync;
+	gchar *path;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (properties != NULL, NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_create_collection_path (self, properties, alias, cancellable,
+	                                       _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	path = secret_service_create_collection_path_finish (self, sync->result, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return path;
+}
+
+typedef struct {
+	GCancellable *cancellable;
+	GVariant *properties;
+	SecretValue *value;
+	gboolean replace;
+	gchar *collection_path;
+	SecretPrompt *prompt;
+	gchar *item_path;
+} ItemClosure;
+
+static void
+item_closure_free (gpointer data)
+{
+	ItemClosure *closure = data;
+	g_variant_unref (closure->properties);
+	secret_value_unref (closure->value);
+	g_clear_object (&closure->cancellable);
+	g_free (closure->collection_path);
+	g_clear_object (&closure->prompt);
+	g_slice_free (ItemClosure, closure);
+}
+
+static void
+on_create_item_prompt (GObject *source,
+                       GAsyncResult *result,
+                       gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+	GVariant *value;
+
+	value = secret_service_prompt_finish (SECRET_SERVICE (source), result,
+	                                      G_VARIANT_TYPE ("o"), &error);
+	if (error != NULL)
+		g_simple_async_result_take_error (res, error);
+	if (value != NULL) {
+		closure->item_path = g_variant_dup_string (value, NULL);
+		g_variant_unref (value);
+	}
+
+	g_simple_async_result_complete (res);
+	g_object_unref (res);
+}
+
+static void
+on_create_item_called (GObject *source,
+                       GAsyncResult *result,
+                       gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	SecretService *self = SECRET_SERVICE (g_async_result_get_source_object (user_data));
+	const gchar *prompt_path = NULL;
+	const gchar *item_path = NULL;
+	GError *error = NULL;
+	GVariant *retval;
+
+	retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+	if (error == NULL) {
+		g_variant_get (retval, "(&o&o)", &item_path, &prompt_path);
+		if (!_secret_util_empty_path (prompt_path)) {
+			closure->prompt = _secret_prompt_instance (self, prompt_path);
+			secret_service_prompt (self, closure->prompt,
+			                       closure->cancellable, on_create_item_prompt,
+			                       g_object_ref (res));
+
+		} else {
+			closure->item_path = g_strdup (item_path);
+			g_simple_async_result_complete (res);
+		}
+
+		g_variant_unref (retval);
+
+	} else {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete (res);
+	}
+
+	g_object_unref (self);
+	g_object_unref (res);
+}
+
+static void
+on_create_item_session (GObject *source,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	SecretService *self = SECRET_SERVICE (source);
+	SecretSession *session;
+	GVariant *params;
+	GError *error = NULL;
+	GDBusProxy *proxy;
+
+	secret_service_ensure_session_finish (self, result, &error);
+	if (error == NULL) {
+		session = _secret_service_get_session (self);
+		params = g_variant_new ("(@a{sv}@(oayays)b)",
+		                        closure->properties,
+		                        _secret_session_encode_secret (session, closure->value),
+		                        closure->replace);
+
+		proxy = G_DBUS_PROXY (self);
+		g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+		                        g_dbus_proxy_get_name (proxy),
+		                        closure->collection_path,
+		                        SECRET_COLLECTION_INTERFACE,
+		                        "CreateItem", params, G_VARIANT_TYPE ("(oo)"),
+		                        G_DBUS_CALL_FLAGS_NONE, -1,
+		                        closure->cancellable,
+		                        on_create_item_called,
+		                        g_object_ref (res));
+	} else {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete (res);
+	}
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_create_item_path:
+ * @self: a secret service object
+ * @collection_path: (allow-none): the D-Bus object path of the collection in which to create item
+ * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
+ *              for the new collection
+ * @value: the secret value to store in the item
+ * @replace: whether to replace an item with the matching attributes
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Create a new item in a secret service collection and return its D-Bus
+ * object path.
+ *
+ * It is often easier to use secret_password_store() or secret_item_create()
+ * rather than using this function. Using this method requires that you setup
+ * a correct hash table of D-Bus @properties for the new collection.
+ *
+ * If @replace is set to %TRUE, and an item already in the collection matches
+ * the attributes (specified in @properties) then the item will be updated
+ * instead of creating a new item.
+ *
+ * @properties is a set of properties for the new collection. The keys in the
+ * hash table should be interface.property strings like
+ * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
+ * in the hash table should be #GVariant values of the properties.
+ *
+ * If @collection_path is %NULL, then the default collection will be
+ * used. Use #SECRET_COLLECTION_SESSION to store the password in the session
+ * collection, which doesn't get stored across login sessions.
+ *
+ * This method will return immediately and complete asynchronously. The secret
+ * service may prompt the user. secret_service_prompt() will be used to handle
+ * any prompts that are required.
+ */
+void
+secret_service_create_item_path (SecretService *self,
+                                 const gchar *collection_path,
+                                 GHashTable *properties,
+                                 SecretValue *value,
+                                 gboolean replace,
+                                 GCancellable *cancellable,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+	GSimpleAsyncResult *res;
+	ItemClosure *closure;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (properties != NULL);
+	g_return_if_fail (value != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	if (collection_path == NULL)
+		collection_path = SECRET_COLLECTION_DEFAULT;
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 secret_service_create_item_path);
+	closure = g_slice_new0 (ItemClosure);
+	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	closure->properties = _secret_util_variant_for_properties (properties);
+	g_variant_ref_sink (closure->properties);
+	closure->replace = replace;
+	closure->value = secret_value_ref (value);
+	closure->collection_path = g_strdup (collection_path);
+	g_simple_async_result_set_op_res_gpointer (res, closure, item_closure_free);
+
+	secret_service_ensure_session (self, cancellable,
+	                               on_create_item_session,
+	                               g_object_ref (res));
+
+	g_object_unref (res);
+}
+
+/**
+ * secret_service_create_item_path_finish:
+ * @self: a secret service object
+ * @result: the asynchronous result passed to the callback
+ * @error: location to place an error on failure
+ *
+ * Finish asynchronous operation to create a new item in the secret
+ * service.
+ *
+ * Returns: (transfer full): a new string containing the D-Bus object path
+ *          of the item
+ */
+gchar *
+secret_service_create_item_path_finish (SecretService *self,
+                                        GAsyncResult *result,
+                                        GError **error)
+{
+	GSimpleAsyncResult *res;
+	ItemClosure *closure;
+	gchar *path;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      secret_service_create_item_path), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (res, error))
+		return NULL;
+
+	closure = g_simple_async_result_get_op_res_gpointer (res);
+	path = closure->item_path;
+	closure->item_path = NULL;
+	return path;
+}
+
+/**
+ * secret_service_create_item_path_sync:
+ * @self: a secret service object
+ * @collection_path: (allow-none): the D-Bus path of the collection in which to create item
+ * @properties: (element-type utf8 GLib.Variant): hash table of D-Bus properties
+ *              for the new collection
+ * @value: the secret value to store in the item
+ * @replace: whether to replace an item with the matching attributes
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Create a new item in a secret service collection and return its D-Bus
+ * object path.
+ *
+ * It is often easier to use secret_password_store_sync() or secret_item_create_sync()
+ * rather than using this function. Using this method requires that you setup
+ * a correct hash table of D-Bus @properties for the new collection.
+ *
+ * If @replace is set to %TRUE, and an item already in the collection matches
+ * the attributes (specified in @properties) then the item will be updated
+ * instead of creating a new item.
+ *
+ * @properties is a set of properties for the new collection. The keys in the
+ * hash table should be interface.property strings like
+ * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
+ * in the hash table should be #GVariant values of the properties.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads. The secret service may prompt the user. secret_service_prompt()
+ * will be used to handle any prompts that are required.
+ *
+ * Returns: (transfer full): a new string containing the D-Bus object path
+ *          of the item
+ */
+gchar *
+secret_service_create_item_path_sync (SecretService *self,
+                                      const gchar *collection_path,
+                                      GHashTable *properties,
+                                      SecretValue *value,
+                                      gboolean replace,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+	SecretSync *sync;
+	gchar *path;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (properties != NULL, NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_create_item_path (self, collection_path, properties, value, replace,
+	                                 cancellable, _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	path = secret_service_create_item_path_finish (self, sync->result, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return path;
+}
+
+/**
+ * secret_service_read_alias_path:
+ * @self: a secret service object
+ * @alias: the alias to lookup
+ * @cancellable: (allow-none): optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Lookup which collection is assigned to this alias. Aliases help determine
+ * well known collections, such as 'default'. This method looks up the
+ * dbus object path of the well known collection.
+ *
+ * This method will return immediately and complete asynchronously.
+ */
+void
+secret_service_read_alias_path (SecretService *self,
+                                const gchar *alias,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
+{
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (alias != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	g_dbus_proxy_call (G_DBUS_PROXY (self), "ReadAlias",
+	                   g_variant_new ("(s)", alias),
+	                   G_DBUS_CALL_FLAGS_NONE, -1,
+	                   cancellable, callback, user_data);
+}
+
+/**
+ * secret_service_read_alias_path_finish:
+ * @self: a secret service object
+ * @result: asynchronous result passed to callback
+ * @error: location to place error on failure
+ *
+ * Finish an asynchronous operation to lookup which collection is assigned
+ * to an alias. This method returns the DBus object path of the collection
+ *
+ * Returns: (transfer full): the collection dbus object path, or %NULL if
+ *          none assigned to the alias
+ */
+gchar *
+secret_service_read_alias_path_finish (SecretService *self,
+                                       GAsyncResult *result,
+                                       GError **error)
+{
+	gchar *collection_path;
+	GVariant *retval;
+
+	retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
+	if (retval == NULL)
+		return NULL;
+
+	g_variant_get (retval, "(o)", &collection_path);
+	g_variant_unref (retval);
+
+	if (g_str_equal (collection_path, "/")) {
+		g_free (collection_path);
+		collection_path = NULL;
+	}
+
+	return collection_path;
+}
+
+/**
+ * secret_service_read_alias_path_sync:
+ * @self: a secret service object
+ * @alias: the alias to lookup
+ * @cancellable: (allow-none): optional cancellation object
+ * @error: location to place error on failure
+ *
+ * Lookup which collection is assigned to this alias. Aliases help determine
+ * well known collections, such as 'default'. This method returns the dbus
+ * object path of the collection.
+ *
+ * This method may block and should not be used in user interface threads.
+ *
+ * Returns: (transfer full): the collection dbus object path, or %NULL if
+ *          none assigned to the alias
+ */
+gchar *
+secret_service_read_alias_path_sync (SecretService *self,
+                                     const gchar *alias,
+                                     GCancellable *cancellable,
+                                     GError **error)
+{
+	SecretSync *sync;
+	gchar *collection_path;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (alias != NULL, NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_read_alias_path (self, alias, cancellable, _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	collection_path = secret_service_read_alias_path_finish (self, sync->result, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return collection_path;
+}
+
+/**
+ * secret_service_set_alias_path:
+ * @self: a secret service object
+ * @alias: the alias to assign the collection to
+ * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
+ * @cancellable: (allow-none): optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Assign a collection to this alias. Aliases help determine
+ * well known collections, such as 'default'. This method takes the dbus object
+ * path of the collection to assign to the alias.
+ *
+ * This method will return immediately and complete asynchronously.
+ */
+void
+secret_service_set_alias_path (SecretService *self,
+                               const gchar *alias,
+                               const gchar *collection_path,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (alias != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	if (collection_path == NULL)
+		collection_path = "/";
+	else
+		g_return_if_fail (g_variant_is_object_path (collection_path));
+
+	g_dbus_proxy_call (G_DBUS_PROXY (self), "SetAlias",
+	                   g_variant_new ("(so)", alias, collection_path),
+	                   G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
+	                   callback, user_data);
+}
+
+/**
+ * secret_service_set_alias_path_finish:
+ * @self: a secret service object
+ * @result: asynchronous result passed to callback
+ * @error: location to place error on failure
+ *
+ * Finish an asynchronous operation to assign a collection to an alias.
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+secret_service_set_alias_path_finish (SecretService *self,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+	GVariant *retval;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, error);
+	if (retval == NULL)
+		return FALSE;
+
+	g_variant_unref (retval);
+	return TRUE;
+}
+
+/**
+ * secret_service_set_alias_path_sync:
+ * @self: a secret service object
+ * @alias: the alias to assign the collection to
+ * @collection_path: (allow-none): the dbus object path of the collection to assign to the alias
+ * @cancellable: (allow-none): optional cancellation object
+ * @error: location to place error on failure
+ *
+ * Assign a collection to this alias. Aliases help determine
+ * well known collections, such as 'default'. This method takes the dbus object
+ * path of the collection to assign to the alias.
+ *
+ * This method may block and should not be used in user interface threads.
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+secret_service_set_alias_path_sync (SecretService *self,
+                                    const gchar *alias,
+                                    const gchar *collection_path,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+	SecretSync *sync;
+	gboolean ret;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+	g_return_val_if_fail (alias != NULL, FALSE);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	if (collection_path == NULL)
+		collection_path = "/";
+	else
+		g_return_val_if_fail (g_variant_is_object_path (collection_path), FALSE);
+
+	sync = _secret_sync_new ();
+	g_main_context_push_thread_default (sync->context);
+
+	secret_service_set_alias_path (self, alias, collection_path,
+	                               cancellable, _secret_sync_on_result, sync);
+
+	g_main_loop_run (sync->loop);
+
+	ret = secret_service_set_alias_path_finish (self, sync->result, error);
+
+	g_main_context_pop_thread_default (sync->context);
+	_secret_sync_free (sync);
+
+	return ret;
+}
+
+GVariant *
+secret_service_prompt_path_sync (SecretService *self,
+                                 const gchar *prompt_path,
+                                 GCancellable *cancellable,
+                                 const GVariantType *return_type,
+                                 GError **error)
+{
+	SecretPrompt *prompt;
+	GVariant *retval;
+
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (prompt_path != NULL, NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	prompt = _secret_prompt_instance (self, prompt_path);
+	retval = secret_service_prompt_sync (self, prompt, cancellable, return_type, error);
+	g_object_unref (prompt);
+
+	return retval;
+}
+
+/**
+ * secret_service_prompt_path:
+ * @self: the secret service
+ * @prompt_path: the D-Bus object path of the prompt
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Perform prompting for a #SecretPrompt.
+ *
+ * This function is called by other parts of this library to handle prompts
+ * for the various actions that can require prompting.
+ *
+ * Override the #SecretServiceClass <literal>prompt_async</literal> virtual method
+ * to change the behavior of the propmting. The default behavior is to simply
+ * run secret_prompt_perform() on the prompt.
+ */
+void
+secret_service_prompt_path (SecretService *self,
+                            const gchar *prompt_path,
+                            GCancellable *cancellable,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data)
+{
+	SecretPrompt *prompt;
+
+	g_return_if_fail (SECRET_IS_SERVICE (self));
+	g_return_if_fail (prompt_path != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	prompt = _secret_prompt_instance (self, prompt_path);
+	secret_service_prompt (self, prompt, cancellable, callback, user_data);
+	g_object_unref (prompt);
+}
+
+/**
+ * secret_service_prompt_path_finish:
+ * @self: the secret service
+ * @result: the asynchronous result passed to the callback
+ * @return_type: the variant type of the prompt result
+ * @error: location to place an error on failure
+ *
+ * Complete asynchronous operation to perform prompting for a #SecretPrompt.
+ *
+ * Returns a variant result if the prompt was completed and not dismissed. The
+ * type of result depends on the action the prompt is completing, and is defined
+ * in the Secret Service DBus API specification.
+ *
+ * Returns: (transfer full): %NULL if the prompt was dismissed or an error occurred,
+ *          a variant result if the prompt was successful
+ */
+GVariant *
+secret_service_prompt_path_finish (SecretService *self,
+                                   GAsyncResult *result,
+                                   const GVariantType *return_type,
+                                   GError **error)
+{
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	return secret_service_prompt_finish (self, result, return_type, error);
+}
diff --git a/library/secret-paths.h b/library/secret-paths.h
new file mode 100644
index 0000000..a26a5e7
--- /dev/null
+++ b/library/secret-paths.h
@@ -0,0 +1,219 @@
+/* libsecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ * Copyright 2012 Red Hat Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw gnome org>
+ */
+
+#if !defined (__SECRET_INSIDE_HEADER__) && !defined (SECRET_COMPILATION)
+#error "Only <secret/secret.h> or <secret/secret-unstable.h> can be included directly."
+#endif
+
+#ifndef __SECRET_PATHS_H__
+#define __SECRET_PATHS_H__
+
+#include <gio/gio.h>
+
+#include "secret-prompt.h"
+#include "secret-schema.h"
+#include "secret-types.h"
+#include "secret-value.h"
+
+G_BEGIN_DECLS
+
+void                 secret_service_search_for_paths              (SecretService *self,
+                                                                   GHashTable *attributes,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gboolean             secret_service_search_for_paths_finish       (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   gchar ***unlocked,
+                                                                   gchar ***locked,
+                                                                   GError **error);
+
+gboolean             secret_service_search_for_paths_sync         (SecretService *self,
+                                                                   GHashTable *attributes,
+                                                                   GCancellable *cancellable,
+                                                                   gchar ***unlocked,
+                                                                   gchar ***locked,
+                                                                   GError **error);
+
+void                 secret_service_get_secret_for_path           (SecretService *self,
+                                                                   const gchar *item_path,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+SecretValue *        secret_service_get_secret_for_path_finish    (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+SecretValue *        secret_service_get_secret_for_path_sync      (SecretService *self,
+                                                                   const gchar *item_path,
+                                                                   GCancellable *cancellable,
+                                                                   GError **error);
+
+void                 secret_service_get_secrets_for_paths         (SecretService *self,
+                                                                   const gchar **item_paths,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+GHashTable *         secret_service_get_secrets_for_paths_finish  (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+GHashTable *         secret_service_get_secrets_for_paths_sync    (SecretService *self,
+                                                                   const gchar **item_paths,
+                                                                   GCancellable *cancellable,
+                                                                   GError **error);
+
+gint                 secret_service_lock_paths_sync               (SecretService *self,
+                                                                   const gchar **paths,
+                                                                   GCancellable *cancellable,
+                                                                   gchar ***locked,
+                                                                   GError **error);
+
+void                 secret_service_lock_paths                    (SecretService *self,
+                                                                   const gchar **paths,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gint                 secret_service_lock_paths_finish             (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   gchar ***locked,
+                                                                   GError **error);
+
+gint                 secret_service_unlock_paths_sync             (SecretService *self,
+                                                                   const gchar **paths,
+                                                                   GCancellable *cancellable,
+                                                                   gchar ***unlocked,
+                                                                   GError **error);
+
+void                 secret_service_unlock_paths                  (SecretService *self,
+                                                                   const gchar **paths,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gint                 secret_service_unlock_paths_finish           (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   gchar ***unlocked,
+                                                                   GError **error);
+
+GVariant *           secret_service_prompt_path_sync              (SecretService *self,
+                                                                   const gchar *prompt_path,
+                                                                   GCancellable *cancellable,
+                                                                   const GVariantType *return_type,
+                                                                   GError **error);
+
+void                 secret_service_prompt_path                   (SecretService *self,
+                                                                   const gchar *prompt_path,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+GVariant *           secret_service_prompt_path_finish            (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   const GVariantType *return_type,
+                                                                   GError **error);
+
+void                 secret_service_delete_path                   (SecretService *self,
+                                                                   const gchar *item_path,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gboolean             secret_service_delete_path_finish            (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+gboolean             secret_service_delete_path_sync              (SecretService *self,
+                                                                   const gchar *item_path,
+                                                                   GCancellable *cancellable,
+                                                                   GError **error);
+
+void                 secret_service_create_collection_path        (SecretService *self,
+                                                                   GHashTable *properties,
+                                                                   const gchar *alias,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gchar *              secret_service_create_collection_path_finish (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+gchar *              secret_service_create_collection_path_sync   (SecretService *self,
+                                                                   GHashTable *properties,
+                                                                   const gchar *alias,
+                                                                   GCancellable *cancellable,
+                                                                   GError **error);
+
+void                 secret_service_create_item_path              (SecretService *self,
+                                                                   const gchar *collection_path,
+                                                                   GHashTable *properties,
+                                                                   SecretValue *value,
+                                                                   gboolean replace,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gchar *              secret_service_create_item_path_finish       (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+gchar *              secret_service_create_item_path_sync         (SecretService *self,
+                                                                   const gchar *collection_path,
+                                                                   GHashTable *properties,
+                                                                   SecretValue *value,
+                                                                   gboolean replace,
+                                                                   GCancellable *cancellable,
+                                                                   GError **error);
+
+void                 secret_service_read_alias_path               (SecretService *self,
+                                                                   const gchar *alias,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gchar *              secret_service_read_alias_path_finish        (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+gchar *              secret_service_read_alias_path_sync          (SecretService *self,
+                                                                   const gchar *alias,
+                                                                   GCancellable *cancellable,
+                                                                   GError **error);
+
+void                 secret_service_set_alias_path                (SecretService *self,
+                                                                   const gchar *alias,
+                                                                   const gchar *collection_path,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gboolean             secret_service_set_alias_path_finish         (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+gboolean             secret_service_set_alias_path_sync           (SecretService *self,
+                                                                   const gchar *alias,
+                                                                   const gchar *collection_path,
+                                                                   GCancellable *cancellable,
+                                                                   GError **error);
+
+G_END_DECLS
+
+#endif /* __SECRET_SERVICE_H___ */
diff --git a/library/secret-private.h b/library/secret-private.h
index e6a86d7..b4ecebd 100644
--- a/library/secret-private.h
+++ b/library/secret-private.h
@@ -139,6 +139,12 @@ SecretItem *         _secret_service_find_item_instance       (SecretService *se
 SecretCollection *   _secret_service_find_collection_instance (SecretService *self,
                                                                const gchar *collection_path);
 
+SecretValue *        _secret_service_decode_get_secrets_first (SecretService *self,
+                                                               GVariant *out);
+
+GHashTable *         _secret_service_decode_get_secrets_all   (SecretService *self,
+                                                               GVariant *out);
+
 SecretItem *         _secret_collection_find_item_instance    (SecretCollection *self,
                                                                const gchar *item_path);
 
diff --git a/library/secret-service.c b/library/secret-service.c
index 0b9e923..9a6eb16 100644
--- a/library/secret-service.c
+++ b/library/secret-service.c
@@ -19,6 +19,7 @@
 #include "secret-dbus-generated.h"
 #include "secret-enum-types.h"
 #include "secret-item.h"
+#include "secret-paths.h"
 #include "secret-private.h"
 #include "secret-service.h"
 #include "secret-types.h"
@@ -1648,89 +1649,3 @@ secret_service_prompt_finish (SecretService *self,
 
 	return (klass->prompt_finish) (self, result, return_type, error);
 }
-
-GVariant *
-secret_service_prompt_path_sync (SecretService *self,
-                                 const gchar *prompt_path,
-                                 GCancellable *cancellable,
-                                 const GVariantType *return_type,
-                                 GError **error)
-{
-	SecretPrompt *prompt;
-	GVariant *retval;
-
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (prompt_path != NULL, NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	prompt = _secret_prompt_instance (self, prompt_path);
-	retval = secret_service_prompt_sync (self, prompt, cancellable, return_type, error);
-	g_object_unref (prompt);
-
-	return retval;
-}
-
-/**
- * secret_service_prompt_path:
- * @self: the secret service
- * @prompt_path: the D-Bus object path of the prompt
- * @cancellable: optional cancellation object
- * @callback: called when the operation completes
- * @user_data: data to be passed to the callback
- *
- * Perform prompting for a #SecretPrompt.
- *
- * This function is called by other parts of this library to handle prompts
- * for the various actions that can require prompting.
- *
- * Override the #SecretServiceClass <literal>prompt_async</literal> virtual method
- * to change the behavior of the propmting. The default behavior is to simply
- * run secret_prompt_perform() on the prompt.
- */
-void
-secret_service_prompt_path (SecretService *self,
-                            const gchar *prompt_path,
-                            GCancellable *cancellable,
-                            GAsyncReadyCallback callback,
-                            gpointer user_data)
-{
-	SecretPrompt *prompt;
-
-	g_return_if_fail (SECRET_IS_SERVICE (self));
-	g_return_if_fail (prompt_path != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	prompt = _secret_prompt_instance (self, prompt_path);
-	secret_service_prompt (self, prompt, cancellable, callback, user_data);
-	g_object_unref (prompt);
-}
-
-/**
- * secret_service_prompt_path_finish:
- * @self: the secret service
- * @result: the asynchronous result passed to the callback
- * @return_type: the variant type of the prompt result
- * @error: location to place an error on failure
- *
- * Complete asynchronous operation to perform prompting for a #SecretPrompt.
- *
- * Returns a variant result if the prompt was completed and not dismissed. The
- * type of result depends on the action the prompt is completing, and is defined
- * in the Secret Service DBus API specification.
- *
- * Returns: (transfer full): %NULL if the prompt was dismissed or an error occurred,
- *          a variant result if the prompt was successful
- */
-GVariant *
-secret_service_prompt_path_finish (SecretService *self,
-                                   GAsyncResult *result,
-                                   const GVariantType *return_type,
-                                   GError **error)
-{
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
-	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
-	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-	return secret_service_prompt_finish (self, result, return_type, error);
-}
diff --git a/library/secret-service.h b/library/secret-service.h
index 8bb4e7a..a29bd47 100644
--- a/library/secret-service.h
+++ b/library/secret-service.h
@@ -162,55 +162,6 @@ gboolean             secret_service_search_sync                   (SecretService
                                                                    GList **locked,
                                                                    GError **error);
 
-void                 secret_service_search_for_paths              (SecretService *self,
-                                                                   GHashTable *attributes,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gboolean             secret_service_search_for_paths_finish       (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   gchar ***unlocked,
-                                                                   gchar ***locked,
-                                                                   GError **error);
-
-gboolean             secret_service_search_for_paths_sync         (SecretService *self,
-                                                                   GHashTable *attributes,
-                                                                   GCancellable *cancellable,
-                                                                   gchar ***unlocked,
-                                                                   gchar ***locked,
-                                                                   GError **error);
-
-void                 secret_service_get_secret_for_path           (SecretService *self,
-                                                                   const gchar *item_path,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-SecretValue *        secret_service_get_secret_for_path_finish    (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   GError **error);
-
-SecretValue *        secret_service_get_secret_for_path_sync      (SecretService *self,
-                                                                   const gchar *item_path,
-                                                                   GCancellable *cancellable,
-                                                                   GError **error);
-
-void                 secret_service_get_secrets_for_paths         (SecretService *self,
-                                                                   const gchar **item_paths,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-GHashTable *         secret_service_get_secrets_for_paths_finish  (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   GError **error);
-
-GHashTable *         secret_service_get_secrets_for_paths_sync    (SecretService *self,
-                                                                   const gchar **item_paths,
-                                                                   GCancellable *cancellable,
-                                                                   GError **error);
-
 void                 secret_service_get_secrets                   (SecretService *self,
                                                                    GList *items,
                                                                    GCancellable *cancellable,
@@ -243,23 +194,6 @@ gint                 secret_service_lock_sync                     (SecretService
                                                                    GList **locked,
                                                                    GError **error);
 
-gint                 secret_service_lock_paths_sync               (SecretService *self,
-                                                                   const gchar **paths,
-                                                                   GCancellable *cancellable,
-                                                                   gchar ***locked,
-                                                                   GError **error);
-
-void                 secret_service_lock_paths                    (SecretService *self,
-                                                                   const gchar **paths,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gint                 secret_service_lock_paths_finish             (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   gchar ***locked,
-                                                                   GError **error);
-
 void                 secret_service_unlock                        (SecretService *self,
                                                                    GList *objects,
                                                                    GCancellable *cancellable,
@@ -277,23 +211,6 @@ gint                 secret_service_unlock_sync                   (SecretService
                                                                    GList **unlocked,
                                                                    GError **error);
 
-gint                 secret_service_unlock_paths_sync             (SecretService *self,
-                                                                   const gchar **paths,
-                                                                   GCancellable *cancellable,
-                                                                   gchar ***unlocked,
-                                                                   GError **error);
-
-void                 secret_service_unlock_paths                  (SecretService *self,
-                                                                   const gchar **paths,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gint                 secret_service_unlock_paths_finish           (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   gchar ***unlocked,
-                                                                   GError **error);
-
 GVariant *           secret_service_prompt_sync                   (SecretService *self,
                                                                    SecretPrompt *prompt,
                                                                    GCancellable *cancellable,
@@ -311,23 +228,6 @@ GVariant *           secret_service_prompt_finish                 (SecretService
                                                                    const GVariantType *return_type,
                                                                    GError **error);
 
-GVariant *           secret_service_prompt_path_sync              (SecretService *self,
-                                                                   const gchar *prompt_path,
-                                                                   GCancellable *cancellable,
-                                                                   const GVariantType *return_type,
-                                                                   GError **error);
-
-void                 secret_service_prompt_path                   (SecretService *self,
-                                                                   const gchar *prompt_path,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-GVariant *           secret_service_prompt_path_finish            (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   const GVariantType *return_type,
-                                                                   GError **error);
-
 void                 secret_service_store                         (SecretService *self,
                                                                    const SecretSchema *schema,
                                                                    GHashTable *attributes,
@@ -368,21 +268,6 @@ SecretValue *        secret_service_lookup_sync                   (SecretService
                                                                    GCancellable *cancellable,
                                                                    GError **error);
 
-void                 secret_service_delete_path                   (SecretService *self,
-                                                                   const gchar *item_path,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gboolean             secret_service_delete_path_finish            (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   GError **error);
-
-gboolean             secret_service_delete_path_sync              (SecretService *self,
-                                                                   const gchar *item_path,
-                                                                   GCancellable *cancellable,
-                                                                   GError **error);
-
 void                 secret_service_remove                        (SecretService *self,
                                                                    const SecretSchema *schema,
                                                                    GHashTable *attributes,
@@ -400,44 +285,6 @@ gboolean             secret_service_remove_sync                   (SecretService
                                                                    GCancellable *cancellable,
                                                                    GError **error);
 
-void                 secret_service_create_collection_path        (SecretService *self,
-                                                                   GHashTable *properties,
-                                                                   const gchar *alias,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gchar *              secret_service_create_collection_path_finish (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   GError **error);
-
-gchar *              secret_service_create_collection_path_sync   (SecretService *self,
-                                                                   GHashTable *properties,
-                                                                   const gchar *alias,
-                                                                   GCancellable *cancellable,
-                                                                   GError **error);
-
-void                 secret_service_create_item_path              (SecretService *self,
-                                                                   const gchar *collection_path,
-                                                                   GHashTable *properties,
-                                                                   SecretValue *value,
-                                                                   gboolean replace,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gchar *              secret_service_create_item_path_finish       (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   GError **error);
-
-gchar *              secret_service_create_item_path_sync         (SecretService *self,
-                                                                   const gchar *collection_path,
-                                                                   GHashTable *properties,
-                                                                   SecretValue *value,
-                                                                   gboolean replace,
-                                                                   GCancellable *cancellable,
-                                                                   GError **error);
-
 void                 secret_service_read_alias                    (SecretService *self,
                                                                    const gchar *alias,
                                                                    GCancellable *cancellable,
@@ -453,21 +300,6 @@ SecretCollection *   secret_service_read_alias_sync               (SecretService
                                                                    GCancellable *cancellable,
                                                                    GError **error);
 
-void                 secret_service_read_alias_path               (SecretService *self,
-                                                                   const gchar *alias,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gchar *              secret_service_read_alias_path_finish        (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   GError **error);
-
-gchar *              secret_service_read_alias_path_sync          (SecretService *self,
-                                                                   const gchar *alias,
-                                                                   GCancellable *cancellable,
-                                                                   GError **error);
-
 void                 secret_service_set_alias                     (SecretService *self,
                                                                    const gchar *alias,
                                                                    SecretCollection *collection,
@@ -485,23 +317,6 @@ gboolean             secret_service_set_alias_sync                (SecretService
                                                                    GCancellable *cancellable,
                                                                    GError **error);
 
-void                 secret_service_set_alias_path                (SecretService *self,
-                                                                   const gchar *alias,
-                                                                   const gchar *collection_path,
-                                                                   GCancellable *cancellable,
-                                                                   GAsyncReadyCallback callback,
-                                                                   gpointer user_data);
-
-gboolean             secret_service_set_alias_path_finish         (SecretService *self,
-                                                                   GAsyncResult *result,
-                                                                   GError **error);
-
-gboolean             secret_service_set_alias_path_sync           (SecretService *self,
-                                                                   const gchar *alias,
-                                                                   const gchar *collection_path,
-                                                                   GCancellable *cancellable,
-                                                                   GError **error);
-
 G_END_DECLS
 
 #endif /* __SECRET_SERVICE_H___ */
diff --git a/library/secret-unstable.h b/library/secret-unstable.h
index 2d1a629..0a781bd 100644
--- a/library/secret-unstable.h
+++ b/library/secret-unstable.h
@@ -29,6 +29,7 @@
 #include <secret/secret-collection.h>
 #include <secret/secret-enum-types.h>
 #include <secret/secret-item.h>
+#include <secret/secret-paths.h>
 #include <secret/secret-prompt.h>
 #include <secret/secret-service.h>
 #include <secret/secret-value.h>
diff --git a/library/tests/Makefile.am b/library/tests/Makefile.am
index 77c0d28..fe0e86e 100644
--- a/library/tests/Makefile.am
+++ b/library/tests/Makefile.am
@@ -36,6 +36,7 @@ C_TESTS = \
 	test-prompt \
 	test-service \
 	test-session \
+	test-paths \
 	test-methods \
 	test-password \
 	test-item \
diff --git a/library/tests/test-methods.c b/library/tests/test-methods.c
index f0f6665..09de317 100644
--- a/library/tests/test-methods.c
+++ b/library/tests/test-methods.c
@@ -16,8 +16,9 @@
 #include "secret-attributes.h"
 #include "secret-collection.h"
 #include "secret-item.h"
-#include "secret-service.h"
+#include "secret-paths.h"
 #include "secret-private.h"
+#include "secret-service.h"
 
 #include "mock-service.h"
 
@@ -116,147 +117,6 @@ on_complete_get_result (GObject *source,
 }
 
 static void
-test_search_paths_sync (Test *test,
-                        gconstpointer used)
-{
-	GHashTable *attributes;
-	gboolean ret;
-	gchar **locked;
-	gchar **unlocked;
-	GError *error = NULL;
-
-	attributes = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (attributes, "number", "1");
-
-	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
-	                                             &unlocked, &locked, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	g_assert (locked);
-	g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
-
-	g_assert (unlocked);
-	g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/1");
-
-	g_strfreev (unlocked);
-	g_strfreev (locked);
-
-	g_hash_table_unref (attributes);
-}
-
-static void
-test_search_paths_async (Test *test,
-                         gconstpointer used)
-{
-	GAsyncResult *result = NULL;
-	GHashTable *attributes;
-	gboolean ret;
-	gchar **locked;
-	gchar **unlocked;
-	GError *error = NULL;
-
-	attributes = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (attributes, "number", "1");
-
-	secret_service_search_for_paths (test->service, attributes, NULL,
-	                                  on_complete_get_result, &result);
-	egg_test_wait ();
-
-	g_assert (G_IS_ASYNC_RESULT (result));
-	ret = secret_service_search_for_paths_finish (test->service, result,
-	                                               &unlocked, &locked,
-	                                               &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	g_assert (locked);
-	g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
-
-	g_assert (unlocked);
-	g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/1");
-
-	g_strfreev (unlocked);
-	g_strfreev (locked);
-	g_object_unref (result);
-
-	g_hash_table_unref (attributes);
-}
-
-static void
-test_search_paths_nulls (Test *test,
-                         gconstpointer used)
-{
-	GAsyncResult *result = NULL;
-	GHashTable *attributes;
-	gboolean ret;
-	gchar **paths;
-	GError *error = NULL;
-
-	attributes = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (attributes, "number", "1");
-
-	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
-	                                             &paths, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-	g_assert (paths != NULL);
-	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/english/1");
-	g_strfreev (paths);
-
-	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
-	                                             NULL, &paths, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-	g_assert (paths != NULL);
-	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
-	g_strfreev (paths);
-
-	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
-	                                             NULL, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	secret_service_search_for_paths (test->service, attributes, NULL,
-	                                  on_complete_get_result, &result);
-	egg_test_wait ();
-	g_assert (G_IS_ASYNC_RESULT (result));
-	ret = secret_service_search_for_paths_finish (test->service, result,
-	                                               &paths, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-	g_assert (paths != NULL);
-	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/english/1");
-	g_strfreev (paths);
-	g_clear_object (&result);
-
-	secret_service_search_for_paths (test->service, attributes, NULL,
-	                                  on_complete_get_result, &result);
-	egg_test_wait ();
-	g_assert (G_IS_ASYNC_RESULT (result));
-	ret = secret_service_search_for_paths_finish (test->service, result,
-	                                               NULL, &paths, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-	g_assert (paths != NULL);
-	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
-	g_strfreev (paths);
-	g_clear_object (&result);
-
-	secret_service_search_for_paths (test->service, attributes, NULL,
-	                                  on_complete_get_result, &result);
-	egg_test_wait ();
-	g_assert (G_IS_ASYNC_RESULT (result));
-	ret = secret_service_search_for_paths_finish (test->service, result,
-	                                               NULL, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-	g_clear_object (&result);
-
-	g_hash_table_unref (attributes);
-}
-
-static void
 test_search_sync (Test *test,
                   gconstpointer used)
 {
@@ -398,154 +258,6 @@ test_search_nulls (Test *test,
 }
 
 static void
-test_secret_for_path_sync (Test *test,
-                           gconstpointer used)
-{
-	SecretValue *value;
-	GError *error = NULL;
-	const gchar *path;
-	const gchar *password;
-	gsize length;
-
-	path = "/org/freedesktop/secrets/collection/english/1";
-	value = secret_service_get_secret_for_path_sync (test->service, path, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (value != NULL);
-
-	password = secret_value_get (value, &length);
-	g_assert_cmpuint (length, ==, 3);
-	g_assert_cmpstr (password, ==, "111");
-
-	password = secret_value_get (value, NULL);
-	g_assert_cmpstr (password, ==, "111");
-
-	secret_value_unref (value);
-}
-
-static void
-test_secret_for_path_async (Test *test,
-                            gconstpointer used)
-{
-	SecretValue *value;
-	GError *error = NULL;
-	const gchar *path;
-	const gchar *password;
-	GAsyncResult *result = NULL;
-	gsize length;
-
-	path = "/org/freedesktop/secrets/collection/english/1";
-	secret_service_get_secret_for_path (test->service, path, NULL,
-	                                     on_complete_get_result, &result);
-	g_assert (result == NULL);
-	egg_test_wait ();
-
-	value = secret_service_get_secret_for_path_finish (test->service, result, &error);
-	g_assert_no_error (error);
-	g_assert (value != NULL);
-	g_object_unref (result);
-
-	password = secret_value_get (value, &length);
-	g_assert_cmpuint (length, ==, 3);
-	g_assert_cmpstr (password, ==, "111");
-
-	password = secret_value_get (value, NULL);
-	g_assert_cmpstr (password, ==, "111");
-
-	secret_value_unref (value);
-}
-
-static void
-test_secrets_for_paths_sync (Test *test,
-                             gconstpointer used)
-{
-	const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
-	const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
-	const gchar *paths[] = {
-		path_item_one,
-		path_item_two,
-
-		/* This one is locked, and not returned */
-		"/org/freedesktop/secrets/collection/spanish/10",
-		NULL
-	};
-
-	SecretValue *value;
-	GHashTable *values;
-	GError *error = NULL;
-	const gchar *password;
-	gsize length;
-
-	values = secret_service_get_secrets_for_paths_sync (test->service, paths, NULL, &error);
-	g_assert_no_error (error);
-
-	g_assert (values != NULL);
-	g_assert_cmpuint (g_hash_table_size (values), ==, 2);
-
-	value = g_hash_table_lookup (values, path_item_one);
-	g_assert (value != NULL);
-	password = secret_value_get (value, &length);
-	g_assert_cmpuint (length, ==, 3);
-	g_assert_cmpstr (password, ==, "111");
-
-	value = g_hash_table_lookup (values, path_item_two);
-	g_assert (value != NULL);
-	password = secret_value_get (value, &length);
-	g_assert_cmpuint (length, ==, 3);
-	g_assert_cmpstr (password, ==, "222");
-
-	g_hash_table_unref (values);
-}
-
-static void
-test_secrets_for_paths_async (Test *test,
-                              gconstpointer used)
-{
-	const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
-	const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
-	const gchar *paths[] = {
-		path_item_one,
-		path_item_two,
-
-		/* This one is locked, and not returned */
-		"/org/freedesktop/secrets/collection/spanish/10",
-		NULL
-	};
-
-	SecretValue *value;
-	GHashTable *values;
-	GError *error = NULL;
-	const gchar *password;
-	GAsyncResult *result = NULL;
-	gsize length;
-
-	secret_service_get_secrets_for_paths (test->service, paths, NULL,
-	                                       on_complete_get_result, &result);
-	g_assert (result == NULL);
-	egg_test_wait ();
-
-	values = secret_service_get_secrets_for_paths_finish (test->service, result, &error);
-	g_assert_no_error (error);
-	g_object_unref (result);
-
-	g_assert (values != NULL);
-	g_assert_cmpuint (g_hash_table_size (values), ==, 2);
-
-	value = g_hash_table_lookup (values, path_item_one);
-	g_assert (value != NULL);
-	password = secret_value_get (value, &length);
-	g_assert_cmpuint (length, ==, 3);
-	g_assert_cmpstr (password, ==, "111");
-
-	value = g_hash_table_lookup (values, path_item_two);
-	g_assert (value != NULL);
-	password = secret_value_get (value, &length);
-	g_assert_cmpuint (length, ==, 3);
-	g_assert_cmpstr (password, ==, "222");
-
-	g_hash_table_unref (values);
-}
-
-static void
 test_secrets_sync (Test *test,
                    gconstpointer used)
 {
@@ -656,82 +368,6 @@ test_secrets_async (Test *test,
 }
 
 static void
-test_delete_for_path_sync (Test *test,
-                           gconstpointer used)
-
-{
-	const gchar *path_item_one = "/org/freedesktop/secrets/collection/todelete/item";
-	GError *error = NULL;
-	gboolean ret;
-
-	ret = secret_service_delete_path_sync (test->service, path_item_one, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-}
-
-static void
-test_delete_for_path_sync_prompt (Test *test,
-                                  gconstpointer used)
-
-{
-	const gchar *path_item_one = "/org/freedesktop/secrets/collection/todelete/confirm";
-	GError *error = NULL;
-	gboolean ret;
-
-	ret = secret_service_delete_path_sync (test->service, path_item_one, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-}
-
-static void
-test_lock_paths_sync (Test *test,
-                      gconstpointer used)
-{
-	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
-	const gchar *paths[] = {
-		collection_path,
-		NULL,
-	};
-
-	GError *error = NULL;
-	gchar **locked = NULL;
-	gboolean ret;
-
-	ret = secret_service_lock_paths_sync (test->service, paths, NULL, &locked, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	g_assert (locked != NULL);
-	g_assert_cmpstr (locked[0], ==, collection_path);
-	g_assert (locked[1] == NULL);
-	g_strfreev (locked);
-}
-
-static void
-test_lock_prompt_sync (Test *test,
-                       gconstpointer used)
-{
-	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockprompt";
-	const gchar *paths[] = {
-		collection_path,
-		NULL,
-	};
-
-	GError *error = NULL;
-	gchar **locked = NULL;
-	gboolean ret;
-
-	ret = secret_service_lock_paths_sync (test->service, paths, NULL, &locked, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	g_assert (locked != NULL);
-	g_assert_cmpstr (locked[0], ==, collection_path);
-	g_assert (locked[1] == NULL);
-	g_strfreev (locked);
-}
-
-static void
 test_lock_sync (Test *test,
                 gconstpointer used)
 {
@@ -761,54 +397,6 @@ test_lock_sync (Test *test,
 }
 
 static void
-test_unlock_paths_sync (Test *test,
-                        gconstpointer used)
-{
-	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
-	const gchar *paths[] = {
-		collection_path,
-		NULL,
-	};
-
-	GError *error = NULL;
-	gchar **unlocked = NULL;
-	gboolean ret;
-
-	ret = secret_service_unlock_paths_sync (test->service, paths, NULL, &unlocked, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	g_assert (unlocked != NULL);
-	g_assert_cmpstr (unlocked[0], ==, collection_path);
-	g_assert (unlocked[1] == NULL);
-	g_strfreev (unlocked);
-}
-
-static void
-test_unlock_prompt_sync (Test *test,
-                         gconstpointer used)
-{
-	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockprompt";
-	const gchar *paths[] = {
-		collection_path,
-		NULL,
-	};
-
-	GError *error = NULL;
-	gchar **unlocked = NULL;
-	gboolean ret;
-
-	ret = secret_service_unlock_paths_sync (test->service, paths, NULL, &unlocked, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	g_assert (unlocked != NULL);
-	g_assert_cmpstr (unlocked[0], ==, collection_path);
-	g_assert (unlocked[1] == NULL);
-	g_strfreev (unlocked);
-}
-
-static void
 test_unlock_sync (Test *test,
                   gconstpointer used)
 {
@@ -838,152 +426,6 @@ test_unlock_sync (Test *test,
 }
 
 static void
-test_collection_sync (Test *test,
-                      gconstpointer used)
-{
-	GHashTable *properties;
-	GError *error = NULL;
-	gchar *path;
-
-	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
-	                                    (GDestroyNotify)g_variant_unref);
-	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
-	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
-
-	path = secret_service_create_collection_path_sync (test->service, properties,
-	                                                   NULL, NULL, &error);
-
-	g_hash_table_unref (properties);
-
-	g_assert_no_error (error);
-	g_assert (path != NULL);
-	g_assert (g_str_has_prefix (path, "/org/freedesktop/secrets/collection/"));
-
-	g_free (path);
-}
-
-static void
-test_collection_async (Test *test,
-                       gconstpointer used)
-{
-	GAsyncResult *result = NULL;
-	GHashTable *properties;
-	GError *error = NULL;
-	gchar *path;
-
-	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
-	                                    (GDestroyNotify)g_variant_unref);
-	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
-	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
-
-	secret_service_create_collection_path (test->service, properties,
-	                                        NULL, NULL, on_complete_get_result, &result);
-
-	g_hash_table_unref (properties);
-	g_assert (result == NULL);
-
-	egg_test_wait ();
-
-	path = secret_service_create_collection_path_finish (test->service, result, &error);
-	g_object_unref (result);
-
-	g_assert_no_error (error);
-	g_assert (path != NULL);
-	g_assert (g_str_has_prefix (path, "/org/freedesktop/secrets/collection/"));
-
-	g_free (path);
-}
-
-static void
-test_item_sync (Test *test,
-                gconstpointer used)
-{
-	const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
-	GHashTable *properties;
-	GHashTable *attributes;
-	SecretValue *value;
-	GError *error = NULL;
-	gchar *path;
-
-	attributes = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (attributes, "even", "true");
-	g_hash_table_insert (attributes, "string", "ten");
-	g_hash_table_insert (attributes, "number", "10");
-
-	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
-	                                    (GDestroyNotify)g_variant_unref);
-	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
-	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
-	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Attributes",
-	                     g_variant_ref_sink (_secret_attributes_to_variant (attributes, "org.gnome.Test")));
-
-	g_hash_table_unref (attributes);
-
-	value = secret_value_new ("andmoreandmore", -1, "text/plain");
-
-	path = secret_service_create_item_path_sync (test->service, collection_path,
-	                                              properties, value, FALSE,
-	                                              NULL, &error);
-
-	secret_value_unref (value);
-	g_hash_table_unref (properties);
-
-	g_assert_no_error (error);
-	g_assert (path != NULL);
-	g_assert (g_str_has_prefix (path, collection_path));
-
-	g_free (path);
-}
-
-static void
-test_item_async (Test *test,
-                       gconstpointer used)
-{
-	const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
-	GHashTable *properties;
-	GHashTable *attributes;
-	SecretValue *value;
-	GError *error = NULL;
-	GAsyncResult *result = NULL;
-	gchar *path;
-
-	attributes = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (attributes, "even", "true");
-	g_hash_table_insert (attributes, "string", "ten");
-	g_hash_table_insert (attributes, "number", "10");
-
-	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
-	                                    (GDestroyNotify)g_variant_unref);
-	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
-	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
-	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Attributes",
-	                     g_variant_ref_sink (_secret_attributes_to_variant (attributes, NULL)));
-
-	g_hash_table_unref (attributes);
-
-	value = secret_value_new ("andmoreandmore", -1, "text/plain");
-
-	secret_service_create_item_path (test->service, collection_path,
-	                                  properties, value, FALSE,
-	                                  NULL, on_complete_get_result, &result);
-
-	g_assert (result == NULL);
-	secret_value_unref (value);
-	g_hash_table_unref (properties);
-
-	egg_test_wait ();
-
-	path = secret_service_create_item_path_finish (test->service, result, &error);
-	g_object_unref (result);
-
-	g_assert_no_error (error);
-	g_assert (path != NULL);
-	g_assert (g_str_has_prefix (path, collection_path));
-
-	g_free (path);
-}
-
-static void
 test_remove_sync (Test *test,
                   gconstpointer used)
 {
@@ -1485,36 +927,6 @@ test_set_alias_sync (Test *test,
 	g_object_unref (collection);
 }
 
-static void
-test_set_alias_path (Test *test,
-                     gconstpointer used)
-{
-	gchar *path;
-	GError *error = NULL;
-	gboolean ret;
-
-	path = secret_service_read_alias_path_sync (test->service, "blah", NULL, &error);
-	g_assert_no_error (error);
-	g_assert (path == NULL);
-
-	ret = secret_service_set_alias_path_sync (test->service, "blah", "/org/freedesktop/secrets/collection/english", NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	path = secret_service_read_alias_path_sync (test->service, "blah", NULL, &error);
-	g_assert_no_error (error);
-	g_assert_cmpstr (path, ==, "/org/freedesktop/secrets/collection/english");
-	g_free (path);
-
-	ret = secret_service_set_alias_path_sync (test->service, "blah", NULL, NULL, &error);
-	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	path = secret_service_read_alias_path_sync (test->service, "blah", NULL, &error);
-	g_assert_no_error (error);
-	g_assert (path == NULL);
-}
-
 int
 main (int argc, char **argv)
 {
@@ -1522,38 +934,17 @@ main (int argc, char **argv)
 	g_set_prgname ("test-service");
 	g_type_init ();
 
-	g_test_add ("/service/search-for-paths", Test, "mock-service-normal.py", setup, test_search_paths_sync, teardown);
-	g_test_add ("/service/search-for-paths-async", Test, "mock-service-normal.py", setup, test_search_paths_async, teardown);
-	g_test_add ("/service/search-for-paths-nulls", Test, "mock-service-normal.py", setup, test_search_paths_nulls, teardown);
 	g_test_add ("/service/search-sync", Test, "mock-service-normal.py", setup, test_search_sync, teardown);
 	g_test_add ("/service/search-async", Test, "mock-service-normal.py", setup, test_search_async, teardown);
 	g_test_add ("/service/search-nulls", Test, "mock-service-normal.py", setup, test_search_nulls, teardown);
 
-	g_test_add ("/service/secret-for-path-sync", Test, "mock-service-normal.py", setup, test_secret_for_path_sync, teardown);
-	g_test_add ("/service/secret-for-path-plain", Test, "mock-service-only-plain.py", setup, test_secret_for_path_sync, teardown);
-	g_test_add ("/service/secret-for-path-async", Test, "mock-service-normal.py", setup, test_secret_for_path_async, teardown);
-	g_test_add ("/service/secrets-for-paths-sync", Test, "mock-service-normal.py", setup, test_secrets_for_paths_sync, teardown);
-	g_test_add ("/service/secrets-for-paths-async", Test, "mock-service-normal.py", setup, test_secrets_for_paths_async, teardown);
 	g_test_add ("/service/secrets-sync", Test, "mock-service-normal.py", setup, test_secrets_sync, teardown);
 	g_test_add ("/service/secrets-async", Test, "mock-service-normal.py", setup, test_secrets_async, teardown);
 
-	g_test_add ("/service/delete-for-path", Test, "mock-service-delete.py", setup, test_delete_for_path_sync, teardown);
-	g_test_add ("/service/delete-for-path-with-prompt", Test, "mock-service-delete.py", setup, test_delete_for_path_sync_prompt, teardown);
-
-	g_test_add ("/service/lock-paths-sync", Test, "mock-service-lock.py", setup, test_lock_paths_sync, teardown);
-	g_test_add ("/service/lock-prompt-sync", Test, "mock-service-lock.py", setup, test_lock_prompt_sync, teardown);
 	g_test_add ("/service/lock-sync", Test, "mock-service-lock.py", setup, test_lock_sync, teardown);
 
-	g_test_add ("/service/unlock-paths-sync", Test, "mock-service-lock.py", setup, test_unlock_paths_sync, teardown);
-	g_test_add ("/service/unlock-prompt-sync", Test, "mock-service-lock.py", setup, test_unlock_prompt_sync, teardown);
 	g_test_add ("/service/unlock-sync", Test, "mock-service-lock.py", setup, test_unlock_sync, teardown);
 
-	g_test_add ("/service/create-collection-sync", Test, "mock-service-normal.py", setup, test_collection_sync, teardown);
-	g_test_add ("/service/create-collection-async", Test, "mock-service-normal.py", setup, test_collection_async, teardown);
-
-	g_test_add ("/service/create-item-sync", Test, "mock-service-normal.py", setup, test_item_sync, teardown);
-	g_test_add ("/service/create-item-async", Test, "mock-service-normal.py", setup, test_item_async, teardown);
-
 	g_test_add ("/service/lookup-sync", Test, "mock-service-normal.py", setup, test_lookup_sync, teardown);
 	g_test_add ("/service/lookup-async", Test, "mock-service-normal.py", setup, test_lookup_async, teardown);
 	g_test_add ("/service/lookup-locked", Test, "mock-service-normal.py", setup, test_lookup_locked, teardown);
@@ -1574,7 +965,6 @@ main (int argc, char **argv)
 	g_test_add ("/service/read-alias-async", Test, "mock-service-normal.py", setup, test_read_alias_async, teardown);
 
 	g_test_add ("/service/set-alias-sync", Test, "mock-service-normal.py", setup, test_set_alias_sync, teardown);
-	g_test_add ("/service/set-alias-path", Test, "mock-service-normal.py", setup, test_set_alias_path, teardown);
 
 	return egg_tests_run_with_loop ();
 }
diff --git a/library/tests/test-paths.c b/library/tests/test-paths.c
new file mode 100644
index 0000000..ba349eb
--- /dev/null
+++ b/library/tests/test-paths.c
@@ -0,0 +1,743 @@
+/* libsecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+
+#include "config.h"
+
+#include "secret-attributes.h"
+#include "secret-collection.h"
+#include "secret-item.h"
+#include "secret-paths.h"
+#include "secret-private.h"
+#include "secret-service.h"
+
+#include "mock-service.h"
+
+#include "egg/egg-testing.h"
+
+#include <glib.h>
+
+#include <errno.h>
+#include <stdlib.h>
+
+static const SecretSchema MOCK_SCHEMA = {
+	"org.mock.Schema",
+	SECRET_SCHEMA_NONE,
+	{
+		{ "number", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
+		{ "string", SECRET_SCHEMA_ATTRIBUTE_STRING },
+		{ "even", SECRET_SCHEMA_ATTRIBUTE_BOOLEAN },
+	}
+};
+
+static const SecretSchema PRIME_SCHEMA = {
+	"org.mock.Prime",
+	SECRET_SCHEMA_NONE,
+	{
+		{ "number", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
+		{ "string", SECRET_SCHEMA_ATTRIBUTE_STRING },
+		{ "prime", SECRET_SCHEMA_ATTRIBUTE_BOOLEAN },
+	}
+};
+
+static const SecretSchema NO_NAME_SCHEMA = {
+	"unused.Schema.Name",
+	SECRET_SCHEMA_DONT_MATCH_NAME,
+	{
+		{ "number", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
+		{ "string", SECRET_SCHEMA_ATTRIBUTE_STRING },
+	}
+};
+
+typedef struct {
+	SecretService *service;
+} Test;
+
+static void
+setup_mock (Test *test,
+            gconstpointer data)
+{
+	GError *error = NULL;
+	const gchar *mock_script = data;
+
+	mock_service_start (mock_script, &error);
+	g_assert_no_error (error);
+}
+
+static void
+setup (Test *test,
+       gconstpointer data)
+{
+	GError *error = NULL;
+
+	setup_mock (test, data);
+
+	test->service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
+	g_assert_no_error (error);
+}
+
+static void
+teardown_mock (Test *test,
+               gconstpointer unused)
+{
+	mock_service_stop ();
+}
+
+static void
+teardown (Test *test,
+          gconstpointer unused)
+{
+	egg_test_wait_idle ();
+
+	g_object_unref (test->service);
+	egg_assert_not_object (test->service);
+
+	teardown_mock (test, unused);
+}
+
+static void
+on_complete_get_result (GObject *source,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+	GAsyncResult **ret = user_data;
+	g_assert (ret != NULL);
+	g_assert (*ret == NULL);
+	*ret = g_object_ref (result);
+	egg_test_wait_stop ();
+}
+
+static void
+test_search_paths_sync (Test *test,
+                        gconstpointer used)
+{
+	GHashTable *attributes;
+	gboolean ret;
+	gchar **locked;
+	gchar **unlocked;
+	GError *error = NULL;
+
+	attributes = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_insert (attributes, "number", "1");
+
+	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
+	                                             &unlocked, &locked, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	g_assert (locked);
+	g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
+
+	g_assert (unlocked);
+	g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/1");
+
+	g_strfreev (unlocked);
+	g_strfreev (locked);
+
+	g_hash_table_unref (attributes);
+}
+
+static void
+test_search_paths_async (Test *test,
+                         gconstpointer used)
+{
+	GAsyncResult *result = NULL;
+	GHashTable *attributes;
+	gboolean ret;
+	gchar **locked;
+	gchar **unlocked;
+	GError *error = NULL;
+
+	attributes = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_insert (attributes, "number", "1");
+
+	secret_service_search_for_paths (test->service, attributes, NULL,
+	                                  on_complete_get_result, &result);
+	egg_test_wait ();
+
+	g_assert (G_IS_ASYNC_RESULT (result));
+	ret = secret_service_search_for_paths_finish (test->service, result,
+	                                               &unlocked, &locked,
+	                                               &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	g_assert (locked);
+	g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
+
+	g_assert (unlocked);
+	g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/1");
+
+	g_strfreev (unlocked);
+	g_strfreev (locked);
+	g_object_unref (result);
+
+	g_hash_table_unref (attributes);
+}
+
+static void
+test_search_paths_nulls (Test *test,
+                         gconstpointer used)
+{
+	GAsyncResult *result = NULL;
+	GHashTable *attributes;
+	gboolean ret;
+	gchar **paths;
+	GError *error = NULL;
+
+	attributes = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_insert (attributes, "number", "1");
+
+	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
+	                                             &paths, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+	g_assert (paths != NULL);
+	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/english/1");
+	g_strfreev (paths);
+
+	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
+	                                             NULL, &paths, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+	g_assert (paths != NULL);
+	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
+	g_strfreev (paths);
+
+	ret = secret_service_search_for_paths_sync (test->service, attributes, NULL,
+	                                             NULL, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	secret_service_search_for_paths (test->service, attributes, NULL,
+	                                  on_complete_get_result, &result);
+	egg_test_wait ();
+	g_assert (G_IS_ASYNC_RESULT (result));
+	ret = secret_service_search_for_paths_finish (test->service, result,
+	                                               &paths, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+	g_assert (paths != NULL);
+	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/english/1");
+	g_strfreev (paths);
+	g_clear_object (&result);
+
+	secret_service_search_for_paths (test->service, attributes, NULL,
+	                                  on_complete_get_result, &result);
+	egg_test_wait ();
+	g_assert (G_IS_ASYNC_RESULT (result));
+	ret = secret_service_search_for_paths_finish (test->service, result,
+	                                               NULL, &paths, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+	g_assert (paths != NULL);
+	g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
+	g_strfreev (paths);
+	g_clear_object (&result);
+
+	secret_service_search_for_paths (test->service, attributes, NULL,
+	                                  on_complete_get_result, &result);
+	egg_test_wait ();
+	g_assert (G_IS_ASYNC_RESULT (result));
+	ret = secret_service_search_for_paths_finish (test->service, result,
+	                                               NULL, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+	g_clear_object (&result);
+
+	g_hash_table_unref (attributes);
+}
+
+static void
+test_secret_for_path_sync (Test *test,
+                           gconstpointer used)
+{
+	SecretValue *value;
+	GError *error = NULL;
+	const gchar *path;
+	const gchar *password;
+	gsize length;
+
+	path = "/org/freedesktop/secrets/collection/english/1";
+	value = secret_service_get_secret_for_path_sync (test->service, path, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (value != NULL);
+
+	password = secret_value_get (value, &length);
+	g_assert_cmpuint (length, ==, 3);
+	g_assert_cmpstr (password, ==, "111");
+
+	password = secret_value_get (value, NULL);
+	g_assert_cmpstr (password, ==, "111");
+
+	secret_value_unref (value);
+}
+
+static void
+test_secret_for_path_async (Test *test,
+                            gconstpointer used)
+{
+	SecretValue *value;
+	GError *error = NULL;
+	const gchar *path;
+	const gchar *password;
+	GAsyncResult *result = NULL;
+	gsize length;
+
+	path = "/org/freedesktop/secrets/collection/english/1";
+	secret_service_get_secret_for_path (test->service, path, NULL,
+	                                     on_complete_get_result, &result);
+	g_assert (result == NULL);
+	egg_test_wait ();
+
+	value = secret_service_get_secret_for_path_finish (test->service, result, &error);
+	g_assert_no_error (error);
+	g_assert (value != NULL);
+	g_object_unref (result);
+
+	password = secret_value_get (value, &length);
+	g_assert_cmpuint (length, ==, 3);
+	g_assert_cmpstr (password, ==, "111");
+
+	password = secret_value_get (value, NULL);
+	g_assert_cmpstr (password, ==, "111");
+
+	secret_value_unref (value);
+}
+
+static void
+test_secrets_for_paths_sync (Test *test,
+                             gconstpointer used)
+{
+	const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
+	const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
+	const gchar *paths[] = {
+		path_item_one,
+		path_item_two,
+
+		/* This one is locked, and not returned */
+		"/org/freedesktop/secrets/collection/spanish/10",
+		NULL
+	};
+
+	SecretValue *value;
+	GHashTable *values;
+	GError *error = NULL;
+	const gchar *password;
+	gsize length;
+
+	values = secret_service_get_secrets_for_paths_sync (test->service, paths, NULL, &error);
+	g_assert_no_error (error);
+
+	g_assert (values != NULL);
+	g_assert_cmpuint (g_hash_table_size (values), ==, 2);
+
+	value = g_hash_table_lookup (values, path_item_one);
+	g_assert (value != NULL);
+	password = secret_value_get (value, &length);
+	g_assert_cmpuint (length, ==, 3);
+	g_assert_cmpstr (password, ==, "111");
+
+	value = g_hash_table_lookup (values, path_item_two);
+	g_assert (value != NULL);
+	password = secret_value_get (value, &length);
+	g_assert_cmpuint (length, ==, 3);
+	g_assert_cmpstr (password, ==, "222");
+
+	g_hash_table_unref (values);
+}
+
+static void
+test_secrets_for_paths_async (Test *test,
+                              gconstpointer used)
+{
+	const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
+	const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
+	const gchar *paths[] = {
+		path_item_one,
+		path_item_two,
+
+		/* This one is locked, and not returned */
+		"/org/freedesktop/secrets/collection/spanish/10",
+		NULL
+	};
+
+	SecretValue *value;
+	GHashTable *values;
+	GError *error = NULL;
+	const gchar *password;
+	GAsyncResult *result = NULL;
+	gsize length;
+
+	secret_service_get_secrets_for_paths (test->service, paths, NULL,
+	                                       on_complete_get_result, &result);
+	g_assert (result == NULL);
+	egg_test_wait ();
+
+	values = secret_service_get_secrets_for_paths_finish (test->service, result, &error);
+	g_assert_no_error (error);
+	g_object_unref (result);
+
+	g_assert (values != NULL);
+	g_assert_cmpuint (g_hash_table_size (values), ==, 2);
+
+	value = g_hash_table_lookup (values, path_item_one);
+	g_assert (value != NULL);
+	password = secret_value_get (value, &length);
+	g_assert_cmpuint (length, ==, 3);
+	g_assert_cmpstr (password, ==, "111");
+
+	value = g_hash_table_lookup (values, path_item_two);
+	g_assert (value != NULL);
+	password = secret_value_get (value, &length);
+	g_assert_cmpuint (length, ==, 3);
+	g_assert_cmpstr (password, ==, "222");
+
+	g_hash_table_unref (values);
+}
+
+static void
+test_delete_for_path_sync (Test *test,
+                           gconstpointer used)
+
+{
+	const gchar *path_item_one = "/org/freedesktop/secrets/collection/todelete/item";
+	GError *error = NULL;
+	gboolean ret;
+
+	ret = secret_service_delete_path_sync (test->service, path_item_one, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+}
+
+static void
+test_delete_for_path_sync_prompt (Test *test,
+                                  gconstpointer used)
+
+{
+	const gchar *path_item_one = "/org/freedesktop/secrets/collection/todelete/confirm";
+	GError *error = NULL;
+	gboolean ret;
+
+	ret = secret_service_delete_path_sync (test->service, path_item_one, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+}
+
+static void
+test_lock_paths_sync (Test *test,
+                      gconstpointer used)
+{
+	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
+	const gchar *paths[] = {
+		collection_path,
+		NULL,
+	};
+
+	GError *error = NULL;
+	gchar **locked = NULL;
+	gboolean ret;
+
+	ret = secret_service_lock_paths_sync (test->service, paths, NULL, &locked, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	g_assert (locked != NULL);
+	g_assert_cmpstr (locked[0], ==, collection_path);
+	g_assert (locked[1] == NULL);
+	g_strfreev (locked);
+}
+
+static void
+test_lock_prompt_sync (Test *test,
+                       gconstpointer used)
+{
+	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockprompt";
+	const gchar *paths[] = {
+		collection_path,
+		NULL,
+	};
+
+	GError *error = NULL;
+	gchar **locked = NULL;
+	gboolean ret;
+
+	ret = secret_service_lock_paths_sync (test->service, paths, NULL, &locked, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	g_assert (locked != NULL);
+	g_assert_cmpstr (locked[0], ==, collection_path);
+	g_assert (locked[1] == NULL);
+	g_strfreev (locked);
+}
+
+static void
+test_unlock_paths_sync (Test *test,
+                        gconstpointer used)
+{
+	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
+	const gchar *paths[] = {
+		collection_path,
+		NULL,
+	};
+
+	GError *error = NULL;
+	gchar **unlocked = NULL;
+	gboolean ret;
+
+	ret = secret_service_unlock_paths_sync (test->service, paths, NULL, &unlocked, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	g_assert (unlocked != NULL);
+	g_assert_cmpstr (unlocked[0], ==, collection_path);
+	g_assert (unlocked[1] == NULL);
+	g_strfreev (unlocked);
+}
+
+static void
+test_unlock_prompt_sync (Test *test,
+                         gconstpointer used)
+{
+	const gchar *collection_path = "/org/freedesktop/secrets/collection/lockprompt";
+	const gchar *paths[] = {
+		collection_path,
+		NULL,
+	};
+
+	GError *error = NULL;
+	gchar **unlocked = NULL;
+	gboolean ret;
+
+	ret = secret_service_unlock_paths_sync (test->service, paths, NULL, &unlocked, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	g_assert (unlocked != NULL);
+	g_assert_cmpstr (unlocked[0], ==, collection_path);
+	g_assert (unlocked[1] == NULL);
+	g_strfreev (unlocked);
+}
+
+static void
+test_collection_sync (Test *test,
+                      gconstpointer used)
+{
+	GHashTable *properties;
+	GError *error = NULL;
+	gchar *path;
+
+	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+	                                    (GDestroyNotify)g_variant_unref);
+	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
+	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
+
+	path = secret_service_create_collection_path_sync (test->service, properties,
+	                                                   NULL, NULL, &error);
+
+	g_hash_table_unref (properties);
+
+	g_assert_no_error (error);
+	g_assert (path != NULL);
+	g_assert (g_str_has_prefix (path, "/org/freedesktop/secrets/collection/"));
+
+	g_free (path);
+}
+
+static void
+test_collection_async (Test *test,
+                       gconstpointer used)
+{
+	GAsyncResult *result = NULL;
+	GHashTable *properties;
+	GError *error = NULL;
+	gchar *path;
+
+	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+	                                    (GDestroyNotify)g_variant_unref);
+	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
+	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
+
+	secret_service_create_collection_path (test->service, properties,
+	                                        NULL, NULL, on_complete_get_result, &result);
+
+	g_hash_table_unref (properties);
+	g_assert (result == NULL);
+
+	egg_test_wait ();
+
+	path = secret_service_create_collection_path_finish (test->service, result, &error);
+	g_object_unref (result);
+
+	g_assert_no_error (error);
+	g_assert (path != NULL);
+	g_assert (g_str_has_prefix (path, "/org/freedesktop/secrets/collection/"));
+
+	g_free (path);
+}
+
+static void
+test_item_sync (Test *test,
+                gconstpointer used)
+{
+	const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
+	GHashTable *properties;
+	GHashTable *attributes;
+	SecretValue *value;
+	GError *error = NULL;
+	gchar *path;
+
+	attributes = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_insert (attributes, "even", "true");
+	g_hash_table_insert (attributes, "string", "ten");
+	g_hash_table_insert (attributes, "number", "10");
+
+	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+	                                    (GDestroyNotify)g_variant_unref);
+	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
+	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
+	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Attributes",
+	                     g_variant_ref_sink (_secret_attributes_to_variant (attributes, "org.gnome.Test")));
+
+	g_hash_table_unref (attributes);
+
+	value = secret_value_new ("andmoreandmore", -1, "text/plain");
+
+	path = secret_service_create_item_path_sync (test->service, collection_path,
+	                                              properties, value, FALSE,
+	                                              NULL, &error);
+
+	secret_value_unref (value);
+	g_hash_table_unref (properties);
+
+	g_assert_no_error (error);
+	g_assert (path != NULL);
+	g_assert (g_str_has_prefix (path, collection_path));
+
+	g_free (path);
+}
+
+static void
+test_item_async (Test *test,
+                       gconstpointer used)
+{
+	const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
+	GHashTable *properties;
+	GHashTable *attributes;
+	SecretValue *value;
+	GError *error = NULL;
+	GAsyncResult *result = NULL;
+	gchar *path;
+
+	attributes = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_insert (attributes, "even", "true");
+	g_hash_table_insert (attributes, "string", "ten");
+	g_hash_table_insert (attributes, "number", "10");
+
+	properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+	                                    (GDestroyNotify)g_variant_unref);
+	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Label",
+	                     g_variant_ref_sink (g_variant_new_string ("Wheeee")));
+	g_hash_table_insert (properties, SECRET_COLLECTION_INTERFACE ".Attributes",
+	                     g_variant_ref_sink (_secret_attributes_to_variant (attributes, NULL)));
+
+	g_hash_table_unref (attributes);
+
+	value = secret_value_new ("andmoreandmore", -1, "text/plain");
+
+	secret_service_create_item_path (test->service, collection_path,
+	                                  properties, value, FALSE,
+	                                  NULL, on_complete_get_result, &result);
+
+	g_assert (result == NULL);
+	secret_value_unref (value);
+	g_hash_table_unref (properties);
+
+	egg_test_wait ();
+
+	path = secret_service_create_item_path_finish (test->service, result, &error);
+	g_object_unref (result);
+
+	g_assert_no_error (error);
+	g_assert (path != NULL);
+	g_assert (g_str_has_prefix (path, collection_path));
+
+	g_free (path);
+}
+
+static void
+test_set_alias_path (Test *test,
+                     gconstpointer used)
+{
+	gchar *path;
+	GError *error = NULL;
+	gboolean ret;
+
+	path = secret_service_read_alias_path_sync (test->service, "blah", NULL, &error);
+	g_assert_no_error (error);
+	g_assert (path == NULL);
+
+	ret = secret_service_set_alias_path_sync (test->service, "blah", "/org/freedesktop/secrets/collection/english", NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	path = secret_service_read_alias_path_sync (test->service, "blah", NULL, &error);
+	g_assert_no_error (error);
+	g_assert_cmpstr (path, ==, "/org/freedesktop/secrets/collection/english");
+	g_free (path);
+
+	ret = secret_service_set_alias_path_sync (test->service, "blah", NULL, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret == TRUE);
+
+	path = secret_service_read_alias_path_sync (test->service, "blah", NULL, &error);
+	g_assert_no_error (error);
+	g_assert (path == NULL);
+}
+
+int
+main (int argc, char **argv)
+{
+	g_test_init (&argc, &argv, NULL);
+	g_set_prgname ("test-service");
+	g_type_init ();
+
+	g_test_add ("/service/search-for-paths", Test, "mock-service-normal.py", setup, test_search_paths_sync, teardown);
+	g_test_add ("/service/search-for-paths-async", Test, "mock-service-normal.py", setup, test_search_paths_async, teardown);
+	g_test_add ("/service/search-for-paths-nulls", Test, "mock-service-normal.py", setup, test_search_paths_nulls, teardown);
+
+	g_test_add ("/service/secret-for-path-sync", Test, "mock-service-normal.py", setup, test_secret_for_path_sync, teardown);
+	g_test_add ("/service/secret-for-path-plain", Test, "mock-service-only-plain.py", setup, test_secret_for_path_sync, teardown);
+	g_test_add ("/service/secret-for-path-async", Test, "mock-service-normal.py", setup, test_secret_for_path_async, teardown);
+	g_test_add ("/service/secrets-for-paths-sync", Test, "mock-service-normal.py", setup, test_secrets_for_paths_sync, teardown);
+	g_test_add ("/service/secrets-for-paths-async", Test, "mock-service-normal.py", setup, test_secrets_for_paths_async, teardown);
+
+	g_test_add ("/service/delete-for-path", Test, "mock-service-delete.py", setup, test_delete_for_path_sync, teardown);
+	g_test_add ("/service/delete-for-path-with-prompt", Test, "mock-service-delete.py", setup, test_delete_for_path_sync_prompt, teardown);
+
+	g_test_add ("/service/lock-paths-sync", Test, "mock-service-lock.py", setup, test_lock_paths_sync, teardown);
+	g_test_add ("/service/lock-prompt-sync", Test, "mock-service-lock.py", setup, test_lock_prompt_sync, teardown);
+
+	g_test_add ("/service/unlock-paths-sync", Test, "mock-service-lock.py", setup, test_unlock_paths_sync, teardown);
+	g_test_add ("/service/unlock-prompt-sync", Test, "mock-service-lock.py", setup, test_unlock_prompt_sync, teardown);
+
+	g_test_add ("/service/create-collection-sync", Test, "mock-service-normal.py", setup, test_collection_sync, teardown);
+	g_test_add ("/service/create-collection-async", Test, "mock-service-normal.py", setup, test_collection_async, teardown);
+
+	g_test_add ("/service/create-item-sync", Test, "mock-service-normal.py", setup, test_item_sync, teardown);
+	g_test_add ("/service/create-item-async", Test, "mock-service-normal.py", setup, test_item_async, teardown);
+
+	g_test_add ("/service/set-alias-path", Test, "mock-service-normal.py", setup, test_set_alias_path, teardown);
+
+	return egg_tests_run_with_loop ();
+}



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