From 8f042c24aaaeb823a78d4c749a797f08cc51fe26 Mon Sep 17 00:00:00 2001 From: Niels De Graef Date: Fri, 27 May 2022 11:12:32 +0200 Subject: [PATCH] Replace some SecretSync with a sync implementation The idea behind `SecretSync` is a nice thing: it allows use to re-use our async implementations of methods for the synchronous versions. The big problem with it, is that it makes debugging issues much harder (especially with issues related to freezes) since things can seem to be stuck in `poll()` somewhere. Even though it adds quite a bit of code, I think it makes sense to replace some instances with a proper synchronous implementation. Note that we don't do this for all usages of `SecretSync` though, as some things will need some kind of main loop interaction anyway (for example, when waiting for a portal's Response signal) Another nice advantage is that it's easier to follow the logic in the sync code than the async version. --- libsecret/secret-collection.c | 23 +++---- libsecret/secret-paths.c | 122 +++++++++++++++++++++++++++------- libsecret/secret-private.h | 6 ++ 3 files changed, 112 insertions(+), 39 deletions(-) diff --git a/libsecret/secret-collection.c b/libsecret/secret-collection.c index 190e2c3..7c5172a 100644 --- a/libsecret/secret-collection.c +++ b/libsecret/secret-collection.c @@ -1705,26 +1705,19 @@ secret_collection_delete_sync (SecretCollection *self, GCancellable *cancellable, GError **error) { - SecretSync *sync; - gboolean ret; + const char *object_path; g_return_val_if_fail (SECRET_IS_COLLECTION (self), 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_collection_delete (self, cancellable, _secret_sync_on_result, sync); - - g_main_loop_run (sync->loop); - - ret = secret_collection_delete_finish (self, sync->result, error); - - g_main_context_pop_thread_default (sync->context); - _secret_sync_free (sync); - - return ret; + object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self)); + if (!_secret_service_delete_path_sync (self->pv->service, object_path, FALSE, + cancellable, error)) { + _secret_util_strip_remote_error (error); + return FALSE; + } + return TRUE; } /** diff --git a/libsecret/secret-paths.c b/libsecret/secret-paths.c index f837bb2..a6cee2a 100644 --- a/libsecret/secret-paths.c +++ b/libsecret/secret-paths.c @@ -432,28 +432,37 @@ secret_collection_search_for_dbus_paths_sync (SecretCollection *collection, GCancellable *cancellable, GError **error) { - SecretSync *sync; - gchar **paths; + const char *schema_name = NULL; + GVariant *response = NULL; + char **paths = NULL; g_return_val_if_fail (SECRET_IS_COLLECTION (collection), NULL); g_return_val_if_fail (attributes != 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); + /* Warnings raised already */ + if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE)) + return NULL; - secret_collection_search_for_dbus_paths (collection, schema, attributes, cancellable, - _secret_sync_on_result, sync); + if (schema != NULL && !(schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME)) + schema_name = schema->name; - g_main_loop_run (sync->loop); - paths = secret_collection_search_for_dbus_paths_finish (collection, sync->result, error); + response = + g_dbus_proxy_call_sync (G_DBUS_PROXY (collection), "SearchItems", + g_variant_new ("(@a{ss})", + _secret_attributes_to_variant (attributes, schema_name)), + G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error); + if (response == NULL) { + _secret_util_strip_remote_error (error); + return FALSE; + } - g_main_context_pop_thread_default (sync->context); - _secret_sync_free (sync); + g_variant_get (response, "(^ao)", &paths); + g_variant_unref (response); - return paths; + return g_steal_pointer (&paths); } /** @@ -831,28 +840,37 @@ secret_service_get_secret_for_dbus_path_sync (SecretService *self, GCancellable *cancellable, GError **error) { - SecretSync *sync; - SecretValue *value; + const char *session = NULL; + GVariant *response = NULL; + SecretValue *ret = NULL; 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); + if (!secret_service_ensure_session_sync (self, cancellable, error)) { + _secret_util_strip_remote_error (error); + return NULL; + } - secret_service_get_secret_for_dbus_path (self, item_path, cancellable, - _secret_sync_on_result, sync); + session = secret_service_get_session_dbus_path (self); + response = + g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "GetSecrets", + g_variant_new ("(@aoo)", + g_variant_new_objv (&item_path, 1), + session), + G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, + cancellable, error); + if (response) { + ret = _secret_service_decode_get_secrets_first (self, response); + } else { + _secret_util_strip_remote_error (error); + } - g_main_loop_run (sync->loop); + g_clear_pointer (&response, g_variant_unref); - value = secret_service_get_secret_for_dbus_path_finish (self, sync->result, error); - - g_main_context_pop_thread_default (sync->context); - _secret_sync_free (sync); - - return value; + return ret; } /** @@ -1527,6 +1545,62 @@ _secret_service_delete_path_finish (SecretService *self, return TRUE; } +gboolean +_secret_service_delete_path_sync (SecretService *self, + const char *object_path, + gboolean is_an_item, + GCancellable *cancellable, + GError **error) +{ + GError *err = NULL; + GVariant *prompt_variant = NULL; + gboolean ret = TRUE; + + g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE); + g_return_val_if_fail (object_path != NULL, FALSE); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); + + prompt_variant = + g_dbus_connection_call_sync (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, + &err); + if (err == NULL) { + const char *prompt_path; + + g_variant_get (prompt_variant, "(&o)", &prompt_path); + + /* show a prompt if needed */ + if (!_secret_util_empty_path (prompt_path)) { + SecretPrompt *prompt = NULL; + GVariant *prompt_result = NULL; + + prompt = _secret_prompt_instance (self, prompt_path); + prompt_result = secret_service_prompt_sync (self, + prompt, + cancellable, + NULL, + &err); + ret = (err != NULL); + g_clear_pointer (&prompt_result, g_variant_unref); + } + + } else { + ret = FALSE; + } + + g_clear_pointer (&prompt_variant, g_variant_unref); + if (err) { + _secret_util_strip_remote_error (&err); + g_propagate_error (error, err); + } + return ret; +} + /** * secret_service_delete_item_dbus_path: (skip) * @self: the secret service diff --git a/libsecret/secret-private.h b/libsecret/secret-private.h index 87633f6..81bad9a 100644 --- a/libsecret/secret-private.h +++ b/libsecret/secret-private.h @@ -140,6 +140,12 @@ gboolean _secret_service_delete_path_finish (SecretService *se GAsyncResult *result, GError **error); +gboolean _secret_service_delete_path_sync (SecretService *self, + const char *object_path, + gboolean is_an_item, + GCancellable *cancellable, + GError **error); + void _secret_service_search_for_paths_variant (SecretService *self, GVariant *attributes, GCancellable *cancellable,