GCancellable *cancellable;
SecretService *service;
GVariant *attributes;
- SecretPrompt *prompt;
- gboolean deleted;
+ gint deleted;
+ gint deleting;
} DeleteClosure;
static void
if (closure->service)
g_object_unref (closure->service);
g_variant_unref (closure->attributes);
- g_clear_object (&closure->prompt);
g_clear_object (&closure->cancellable);
g_slice_free (DeleteClosure, closure);
}
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
+ gboolean deleted;
- closure->deleted = _secret_service_delete_path_finish (SECRET_SERVICE (source), result, &error);
+ closure->deleting--;
+
+ deleted = _secret_service_delete_path_finish (SECRET_SERVICE (source), result, &error);
if (error != NULL)
g_simple_async_result_take_error (res, error);
+ if (deleted)
+ closure->deleted++;
- g_simple_async_result_complete (res);
+ if (closure->deleting <= 0)
+ g_simple_async_result_complete (res);
g_object_unref (res);
}
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
- const gchar *path = NULL;
GError *error = NULL;
- gchar **locked;
- gchar **unlocked;
-
- secret_service_search_for_dbus_paths_finish (SECRET_SERVICE (source), 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);
+ gchar **unlocked = NULL;
+ gint i;
- /* Delete the first path */
- } else {
- closure->deleted = TRUE;
- _secret_service_delete_path (closure->service, path, TRUE,
+ secret_service_search_for_dbus_paths_finish (SECRET_SERVICE (source), result, &unlocked, NULL, &error);
+ if (error == NULL) {
+ for (i = 0; unlocked[i] != NULL; i++) {
+ _secret_service_delete_path (closure->service, unlocked[i], TRUE,
closure->cancellable,
on_delete_password_complete,
g_object_ref (res));
+ closure->deleting++;
}
+
+ if (closure->deleting == 0)
+ g_simple_async_result_complete (res);
+ } else {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
}
- g_strfreev (locked);
g_strfreev (unlocked);
g_object_unref (res);
}
g_variant_ref_sink (closure->attributes);
g_simple_async_result_set_op_res_gpointer (res, closure, delete_closure_free);
+ /* A double check to make sure we don't delete everything, should have been checked earlier */
+ g_assert (g_variant_n_children (closure->attributes) > 0);
+
if (service == NULL) {
secret_service_get (SECRET_SERVICE_NONE, cancellable,
on_delete_service, g_object_ref (res));
return FALSE;
closure = g_simple_async_result_get_op_res_gpointer (res);
- return closure->deleted;
+ return closure->deleted > 0;
}
/**
*
* The @attributes should be a set of key and value string pairs.
*
- * If multiple items match the attributes, then only one will be deleted.
+ * All unlocked items that match the attributes will be deleted.
*
* This method will return immediately and complete asynchronously.
*
* @result: the asynchronous result passed to the callback
* @error: location to place an error on failure
*
- * Finish an asynchronous operation to remove a password from the secret
+ * Finish an asynchronous operation to remove passwords from the secret
* service.
*
- * Returns: whether the removal was successful or not
+ * Returns: whether any passwords were removed
*/
gboolean
secret_password_remove_finish (GAsyncResult *result,
* @error: location to place an error on failure
* @...: the attribute keys and values, terminated with %NULL
*
- * Remove a password from the secret service.
+ * Remove passwords from the secret service.
*
* The variable argument list should contain pairs of a) The attribute name as
* a null-terminated string, followed by b) attribute value, either a character
* string, an int number, or a gboolean value, as defined in the password
* @schema. The list of attribtues should be terminated with a %NULL.
*
- * If multiple items match the attributes, then only one will be deleted.
+ * All unlocked items that match the attributes 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
+ * Returns: whether the any passwords were removed
*/
gboolean
secret_password_remove_sync (const SecretSchema* schema,
*
* The @attributes should be a set of key and value string pairs.
*
- * If multiple items match the attributes, then only one will be deleted.
+ * All unlocked items that match the attributes 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
+ * Returns: whether any passwords were removed
*
* Rename to: secret_password_remove_sync
*/
"number", 3,
NULL);
+ /* Locked items can't be removed via this API */
ret = secret_service_remove_sync (test->service, &MOCK_SCHEMA, attributes, NULL, &error);
g_hash_table_unref (attributes);
g_assert_no_error (error);
- g_assert (ret == TRUE);
+ g_assert (ret == FALSE);
}
static void
test_remove_no_name (Test *test,
gconstpointer used)
{
+ const gchar *paths[] = { "/org/freedesktop/secrets/collection/german", NULL };
GError *error = NULL;
GHashTable *attributes;
gboolean ret;
g_assert_no_error (error);
g_assert (ret == FALSE);
+ /* We need this collection unlocked for the next test */
+ secret_service_unlock_dbus_paths_sync (test->service, paths, NULL, NULL, &error);
+ g_assert_no_error (error);
+
/* We have an item with 5 in prime schema, but should match anyway becase of flags */
ret = secret_service_remove_sync (test->service, &NO_NAME_SCHEMA, attributes, NULL, &error);
g_assert_no_error (error);
#include "config.h"
#include "secret-password.h"
+#include "secret-paths.h"
#include "secret-private.h"
#include "mock-service.h"
test_remove_no_name (Test *test,
gconstpointer used)
{
+ const gchar *paths[] = { "/org/freedesktop/secrets/collection/german", NULL };
+ SecretService *service;
GError *error = NULL;
gboolean ret;
g_assert_no_error (error);
g_assert (ret == FALSE);
+ /* We need this collection unlocked for the next test */
+ service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
+ g_assert_no_error (error);
+ secret_service_unlock_dbus_paths_sync (service, paths, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_object_unref (service);
+
/* We have an item with 5 in prime schema, but should match anyway becase of flags */
ret = secret_password_remove_sync (&NO_NAME_SCHEMA, NULL, &error,
"number", 5,