Add secret_service_read_alias() and secret_service_set_alias()
authorStef Walter <stefw@gnome.org>
Sat, 23 Jun 2012 12:09:50 +0000 (14:09 +0200)
committerStef Walter <stefw@gnome.org>
Sat, 23 Jun 2012 12:47:13 +0000 (14:47 +0200)
 * Wrappers for Secret Service ReadAlias() and SetAlias() methods
   in various permutations.

docs/reference/libsecret/libsecret-sections.txt
library/secret-methods.c
library/secret-private.h
library/secret-service.c
library/secret-service.h
library/tests/mock/service.py
library/tests/test-methods.c

index 746c29a735f6535b845c477bd6617b3affaba084..7f23f23af091fd9899e2c3e7ffdc06f1b994cf24 100644 (file)
@@ -232,6 +232,18 @@ 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
index 2a9bf3671721c8cb7b1991e07ad9aec8776805b7..9b2ca988c81765e095897536b4fbbd6f7b2d53f5 100644 (file)
@@ -3448,3 +3448,536 @@ secret_service_create_item_path_sync (SecretService *self,
 
        return path;
 }
+
+typedef struct {
+       GCancellable *cancellable;
+       SecretCollection *collection;
+} ReadClosure;
+
+static void
+read_closure_free (gpointer data)
+{
+       ReadClosure *read = data;
+       if (read->collection)
+               g_object_unref (read->collection);
+       if (read->cancellable)
+               g_object_unref (read->cancellable);
+       g_slice_free (ReadClosure, read);
+}
+
+static void
+on_read_alias_collection (GObject *source,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+       GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
+       ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
+       GError *error = NULL;
+
+       read->collection = secret_collection_new_finish (result, &error);
+       if (error != NULL)
+               g_simple_async_result_take_error (async, error);
+
+       g_simple_async_result_complete (async);
+       g_object_unref (async);
+}
+
+static void
+on_read_alias_path (GObject *source,
+                    GAsyncResult *result,
+                    gpointer user_data)
+{
+       GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
+       ReadClosure *read = g_simple_async_result_get_op_res_gpointer (async);
+       SecretService *self = SECRET_SERVICE (source);
+       GError *error = NULL;
+       gchar *collection_path;
+
+       collection_path = secret_service_read_alias_path_finish (self, result, &error);
+       if (error == NULL) {
+
+               /* No collection for this alias */
+               if (collection_path == NULL) {
+                       g_simple_async_result_complete (async);
+
+               } else {
+                       read->collection = _secret_service_find_collection_instance (self,
+                                                                                    collection_path);
+                       if (read->collection != NULL) {
+                               g_simple_async_result_complete (async);
+
+                       /* No collection loaded, but valid path, load */
+                       } else {
+                               secret_collection_new (self, collection_path, read->cancellable,
+                                                      on_read_alias_collection, g_object_ref (async));
+                       }
+               }
+
+       } else {
+               g_simple_async_result_take_error (async, error);
+               g_simple_async_result_complete (async);
+       }
+
+       g_free (collection_path);
+       g_object_unref (async);
+}
+
+/**
+ * secret_service_read_alias:
+ * @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 will return immediately and complete asynchronously.
+ */
+void
+secret_service_read_alias (SecretService *self,
+                           const gchar *alias,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
+{
+       GSimpleAsyncResult *async;
+       ReadClosure *read;
+
+       g_return_if_fail (SECRET_IS_SERVICE (self));
+       g_return_if_fail (alias != NULL);
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+       async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+                                          secret_service_read_alias);
+       read = g_slice_new0 (ReadClosure);
+       read->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+       g_simple_async_result_set_op_res_gpointer (async, read, read_closure_free);
+
+       secret_service_read_alias_path (self, alias, cancellable,
+                                       on_read_alias_path, g_object_ref (async));
+
+       g_object_unref (async);
+}
+
+/**
+ * secret_service_read_alias_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.
+ *
+ * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
+ */
+SecretCollection *
+secret_service_read_alias_finish (SecretService *self,
+                                  GAsyncResult *result,
+                                  GError **error)
+{
+       GSimpleAsyncResult *async;
+       ReadClosure *read;
+
+       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_read_alias), NULL);
+       g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+       async = G_SIMPLE_ASYNC_RESULT (result);
+       if (g_simple_async_result_propagate_error (async, error))
+               return NULL;
+       read = g_simple_async_result_get_op_res_gpointer (async);
+       if (read->collection)
+               g_object_ref (read->collection);
+       return read->collection;
+}
+
+/**
+ * secret_service_read_alias_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 may block and should not be used in user interface threads.
+ *
+ * Returns: (transfer full): the collection, or %NULL if none assigned to the alias
+ */
+SecretCollection *
+secret_service_read_alias_sync (SecretService *self,
+                                const gchar *alias,
+                                GCancellable *cancellable,
+                                GError **error)
+{
+       SecretCollection *collection;
+       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);
+
+       collection_path = secret_service_read_alias_path_sync (self, alias,
+                                                              cancellable, error);
+       if (collection_path == NULL)
+               return NULL;
+
+       /* No collection for this alias */
+       if (collection_path == NULL) {
+               collection = NULL;
+
+       } else {
+               collection = _secret_service_find_collection_instance (self,
+                                                                      collection_path);
+
+               /* No collection loaded, but valid path, load */
+               if (collection == NULL) {
+                       collection = secret_collection_new_sync (self, collection_path,
+                                                                cancellable, error);
+               }
+       }
+
+       g_free (collection_path);
+       return collection;
+}
+
+/**
+ * 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
+ * @collection: (allow-none): 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 will return immediately and complete asynchronously.
+ */
+void
+secret_service_set_alias (SecretService *self,
+                          const gchar *alias,
+                          SecretCollection *collection,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
+{
+       const gchar *collection_path;
+
+       g_return_if_fail (SECRET_IS_SERVICE (self));
+       g_return_if_fail (alias != NULL);
+       g_return_if_fail (collection == NULL || SECRET_IS_COLLECTION (collection));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+       if (collection) {
+               collection_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection));
+               g_return_if_fail (collection != NULL);
+       } else {
+               collection_path = NULL;
+       }
+
+       secret_service_set_alias_path (self, alias, collection_path, cancellable,
+                                      callback, user_data);
+}
+
+/**
+ * secret_service_set_alias_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_finish (SecretService *self,
+                                 GAsyncResult *result,
+                                 GError **error)
+{
+       g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
+       g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+       return secret_service_set_alias_path_finish (self, result, error);
+}
+
+/**
+ * secret_service_set_alias_sync:
+ * @self: a secret service object
+ * @alias: the alias to assign the collection to
+ * @collection: (allow-none): 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 may block and should not be used in user interface threads.
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+secret_service_set_alias_sync (SecretService *self,
+                               const gchar *alias,
+                               SecretCollection *collection,
+                               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);
+
+       sync = _secret_sync_new ();
+       g_main_context_push_thread_default (sync->context);
+
+       secret_service_set_alias (self, alias, collection, cancellable,
+                                 _secret_sync_on_result, sync);
+
+       g_main_loop_run (sync->loop);
+
+       ret = secret_service_set_alias_finish (self, sync->result, error);
+
+       g_main_context_pop_thread_default (sync->context);
+       _secret_sync_free (sync);
+
+       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;
+}
index 3cb0dd14032461b57bd438e048de6f601dca5f56..c079758e4696d693814f9430ef7d1534f9141ff0 100644 (file)
@@ -139,6 +139,9 @@ void                 _secret_service_search_for_paths_variant (SecretService *se
 SecretItem *         _secret_service_find_item_instance       (SecretService *self,
                                                                const gchar *item_path);
 
+SecretCollection *   _secret_service_find_collection_instance (SecretService *self,
+                                                               const gchar *collection_path);
+
 SecretItem *         _secret_collection_find_item_instance    (SecretCollection *self,
                                                                const gchar *item_path);
 
index 9753616dcda48fc8557ecdd8adc7294656e4dee9..d449f502e34ee6d7957da064592988cc1fd408ca 100644 (file)
@@ -1029,13 +1029,7 @@ _secret_service_find_item_instance (SecretService *self,
 
        collection_path = _secret_util_parent_path (item_path);
 
-       g_mutex_lock (&self->pv->mutex);
-       if (self->pv->collections) {
-               collection = g_hash_table_lookup (self->pv->collections, collection_path);
-               if (collection != NULL)
-                       g_object_ref (collection);
-       }
-       g_mutex_unlock (&self->pv->mutex);
+       collection = _secret_service_find_collection_instance (self, collection_path);
 
        g_free (collection_path);
 
@@ -1048,6 +1042,23 @@ _secret_service_find_item_instance (SecretService *self,
        return item;
 }
 
+SecretCollection *
+_secret_service_find_collection_instance (SecretService *self,
+                                          const gchar *collection_path)
+{
+       SecretCollection *collection = NULL;
+
+       g_mutex_lock (&self->pv->mutex);
+       if (self->pv->collections) {
+               collection = g_hash_table_lookup (self->pv->collections, collection_path);
+               if (collection != NULL)
+                       g_object_ref (collection);
+       }
+       g_mutex_unlock (&self->pv->mutex);
+
+       return collection;
+}
+
 SecretSession *
 _secret_service_get_session (SecretService *self)
 {
index 82f246e773522b3ce8b9009f054cfecc1709e5ad..25fc9443e3ba1bfffd431e5933bca08397a7c75f 100644 (file)
@@ -481,6 +481,70 @@ gchar *              secret_service_create_item_path_sync         (SecretService
                                                                    GCancellable *cancellable,
                                                                    GError **error);
 
+void                 secret_service_read_alias                    (SecretService *self,
+                                                                   const gchar *alias,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+SecretCollection *   secret_service_read_alias_finish             (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+SecretCollection *   secret_service_read_alias_sync               (SecretService *self,
+                                                                   const gchar *alias,
+                                                                   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,
+                                                                   GCancellable *cancellable,
+                                                                   GAsyncReadyCallback callback,
+                                                                   gpointer user_data);
+
+gboolean             secret_service_set_alias_finish              (SecretService *self,
+                                                                   GAsyncResult *result,
+                                                                   GError **error);
+
+gboolean             secret_service_set_alias_sync                (SecretService *self,
+                                                                   const gchar *alias,
+                                                                   SecretCollection *collection,
+                                                                   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___ */
index b36c2b145b7d215852f040130d5529d38469a151..6ba8ea3326e6c60f12781fca7f5fdb4cdadc5261 100644 (file)
@@ -551,8 +551,11 @@ class SecretService(dbus.service.Object):
 
        def set_alias(self, name, collection):
                self.remove_alias(name)
-               collection.add_alias(name)
-               self.aliases[name] = collection
+               if collection:
+                       collection.add_alias(name)
+                       self.aliases[name] = collection
+               elif name in self.aliases:
+                       del self.aliases[name]
 
        def remove_alias(self, name):
                if name in self.aliases:
@@ -656,9 +659,12 @@ class SecretService(dbus.service.Object):
 
        @dbus.service.method('org.freedesktop.Secret.Service')
        def SetAlias(self, name, collection):
-               if collection not in self.collections:
-                       raise NoSuchObject("no such Collection")
-               self.set_alias(name, self.collections[collection])
+               if collection == dbus.ObjectPath("/"):
+                       self.set_alias(name, None)
+               else:
+                       if collection not in self.collections:
+                               raise NoSuchObject("no such Collection")
+                       self.set_alias(name, self.collections[collection])
 
        @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
        def Get(self, interface_name, property_name):
index 377fb85b7d1f7fdc634ec180ee52460c7f6b3269..c699d4f2436617ab8f4c7324e1eb2e6985d44f7b 100644 (file)
@@ -1351,6 +1351,127 @@ test_store_async (Test *test,
        g_strfreev (paths);
 }
 
+static void
+test_read_alias_sync (Test *test,
+                      gconstpointer used)
+{
+       const gchar *collection_path;
+       SecretCollection *collection;
+       GError *error = NULL;
+
+       collection = secret_service_read_alias_sync (test->service, "default", NULL, &error);
+       g_assert_no_error (error);
+
+       collection_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection));
+       g_assert_cmpstr (collection_path, ==, "/org/freedesktop/secrets/collection/english");
+       g_object_unref (collection);
+
+       collection = secret_service_read_alias_sync (test->service, "unknown", NULL, &error);
+       g_assert_no_error (error);
+       g_assert (collection == NULL);
+}
+
+static void
+test_read_alias_async (Test *test,
+                       gconstpointer used)
+{
+       const gchar *collection_path;
+       SecretCollection *collection;
+       GAsyncResult *result = NULL;
+       GError *error = NULL;
+
+       secret_service_read_alias (test->service, "default", NULL,
+                                  on_complete_get_result, &result);
+       g_assert (result == NULL);
+       egg_test_wait ();
+
+       collection = secret_service_read_alias_finish (test->service, result, &error);
+       g_assert_no_error (error);
+       g_object_unref (result);
+
+       collection_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection));
+       g_assert_cmpstr (collection_path, ==, "/org/freedesktop/secrets/collection/english");
+       g_object_unref (collection);
+       result = NULL;
+
+       secret_service_read_alias (test->service, "unknown", NULL,
+                                  on_complete_get_result, &result);
+       g_assert (result == NULL);
+       egg_test_wait ();
+
+       collection = secret_service_read_alias_finish (test->service, result, &error);
+       g_assert_no_error (error);
+       g_assert (collection == NULL);
+       g_object_unref (result);
+}
+
+static void
+test_set_alias_sync (Test *test,
+                     gconstpointer used)
+{
+       SecretCollection *collection;
+       SecretCollection *blah;
+       GError *error = NULL;
+       gboolean ret;
+
+       blah = secret_service_read_alias_sync (test->service, "blah", NULL, &error);
+       g_assert_no_error (error);
+       g_assert (blah == NULL);
+
+       collection = secret_collection_new_sync (test->service, "/org/freedesktop/secrets/collection/english", NULL, &error);
+       g_assert_no_error (error);
+       g_assert (SECRET_IS_COLLECTION (collection));
+
+       ret = secret_service_set_alias_sync (test->service, "blah", collection, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (ret == TRUE);
+
+       blah = secret_service_read_alias_sync (test->service, "blah", NULL, &error);
+       g_assert_no_error (error);
+       g_assert_cmpstr (g_dbus_proxy_get_object_path (G_DBUS_PROXY (blah)), ==, g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection)));
+       g_object_unref (blah);
+
+       ret = secret_service_set_alias_sync (test->service, "blah", NULL, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (ret == TRUE);
+
+       blah = secret_service_read_alias_sync (test->service, "blah", NULL, &error);
+       g_assert_no_error (error);
+       g_assert (blah == NULL);
+
+       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)
 {
@@ -1406,5 +1527,11 @@ main (int argc, char **argv)
        g_test_add ("/service/store-async", Test, "mock-service-normal.py", setup, test_store_async, teardown);
        g_test_add ("/service/store-replace", Test, "mock-service-normal.py", setup, test_store_replace, teardown);
 
+       g_test_add ("/service/read-alias-sync", Test, "mock-service-normal.py", setup, test_read_alias_sync, teardown);
+       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 ();
 }