[libsecret] Add methods which handle prompts for a DBus object path



commit 279ea1cc10064261779e02656772d8546ce194df
Author: Stef Walter <stefw gnome org>
Date:   Sun Apr 29 21:34:40 2012 +0200

    Add methods which handle prompts for a DBus object path
    
     * Various prompting methods return the prompt result as
       a GVariant.
     * Added new prompt_path methods to SecretService

 docs/reference/libsecret/libsecret-sections.txt |    4 +-
 library/secret-methods.c                        |   29 ++--
 library/secret-prompt.c                         |  155 +++++++-------------
 library/secret-prompt.h                         |   12 +-
 library/secret-service.c                        |  171 +++++++++++++++++++----
 library/secret-service.h                        |   31 ++++-
 library/tests/test-prompt.c                     |   98 ++++++-------
 7 files changed, 295 insertions(+), 205 deletions(-)
---
diff --git a/docs/reference/libsecret/libsecret-sections.txt b/docs/reference/libsecret/libsecret-sections.txt
index d28e66f..746c29a 100644
--- a/docs/reference/libsecret/libsecret-sections.txt
+++ b/docs/reference/libsecret/libsecret-sections.txt
@@ -138,7 +138,6 @@ SECRET_SCHEMA_COMPAT_NETWORK
 <INCLUDE>secret/secret-unstable.h</INCLUDE>
 SecretPrompt
 SecretPromptClass
-secret_prompt_get_result_value
 secret_prompt_perform
 secret_prompt_perform_finish
 secret_prompt_perform_sync
@@ -221,6 +220,9 @@ secret_service_removev_sync
 secret_service_prompt
 secret_service_prompt_finish
 secret_service_prompt_sync
+secret_service_prompt_path
+secret_service_prompt_path_finish
+secret_service_prompt_path_sync
 secret_service_create_collection_path
 secret_service_create_collection_path_finish
 secret_service_create_collection_path_sync
diff --git a/library/secret-methods.c b/library/secret-methods.c
index 5cc5e7c..2a9bf36 100644
--- a/library/secret-methods.c
+++ b/library/secret-methods.c
@@ -1087,14 +1087,12 @@ on_xlock_prompted (GObject *source,
 	GVariantIter iter;
 	GVariant *retval;
 	gchar *path;
-	gboolean ret;
 
-	ret = secret_service_prompt_finish (self, result, &error);
+	retval = secret_service_prompt_finish (self, result, G_VARIANT_TYPE ("ao"), &error);
 	if (error != NULL)
 		g_simple_async_result_take_error (res, error);
 
-	if (ret) {
-		retval = secret_prompt_get_result_value (closure->prompt, G_VARIANT_TYPE ("ao"));
+	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));
@@ -2400,14 +2398,17 @@ on_delete_prompted (GObject *source,
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
 	DeleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
+	GVariant *retval;
 
-	secret_service_prompt_finish (SECRET_SERVICE (source), result, &error);
+	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);
 }
@@ -2913,15 +2914,13 @@ on_create_collection_prompt (GObject *source,
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
 	CollectionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
-	gboolean created;
 	GVariant *value;
 
-	created = secret_service_prompt_finish (SECRET_SERVICE (source), result, &error);
+	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 (created) {
-		value = secret_prompt_get_result_value (closure->prompt, G_VARIANT_TYPE ("o"));
+	if (value != NULL) {
 		closure->collection_path = g_variant_dup_string (value, NULL);
 		g_variant_unref (value);
 	}
@@ -3180,15 +3179,13 @@ on_create_item_prompt (GObject *source,
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
 	ItemClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
-	gboolean created;
 	GVariant *value;
 
-	created = secret_service_prompt_finish (SECRET_SERVICE (source), result, &error);
+	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 (created) {
-		value = secret_prompt_get_result_value (closure->prompt, G_VARIANT_TYPE ("o"));
+	if (value != NULL) {
 		closure->item_path = g_variant_dup_string (value, NULL);
 		g_variant_unref (value);
 	}
diff --git a/library/secret-prompt.c b/library/secret-prompt.c
index 184f456..2d2ed01 100644
--- a/library/secret-prompt.c
+++ b/library/secret-prompt.c
@@ -56,10 +56,7 @@
  */
 
 struct _SecretPromptPrivate {
-	/* Locked by mutex */
-	GMutex mutex;
 	gint prompted;
-	GVariant *last_result;
 };
 
 G_DEFINE_TYPE (SecretPrompt, secret_prompt, G_TYPE_DBUS_PROXY);
@@ -69,29 +66,11 @@ secret_prompt_init (SecretPrompt *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SECRET_TYPE_PROMPT,
 	                                        SecretPromptPrivate);
-
-	g_mutex_init (&self->pv->mutex);
-}
-
-static void
-secret_prompt_finalize (GObject *obj)
-{
-	SecretPrompt *self = SECRET_PROMPT (obj);
-
-	g_mutex_clear (&self->pv->mutex);
-	if (self->pv->last_result)
-		g_variant_unref (self->pv->last_result);
-
-	G_OBJECT_CLASS (secret_prompt_parent_class)->finalize (obj);
 }
 
 static void
 secret_prompt_class_init (SecretPromptClass *klass)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	object_class->finalize = secret_prompt_finalize;
-
 	g_type_class_add_private (klass, sizeof (SecretPromptPrivate));
 }
 
@@ -145,10 +124,13 @@ _secret_prompt_instance (SecretService *service,
  * @self: a prompt
  * @window_id: XWindow id for parent window to be transient for
  * @cancellable: optional cancellation object
+ * @return_type: the variant type of the prompt result
  * @error: location to place an error on failure
  *
- * Runs a prompt and performs the prompting. Returns %TRUE if the prompt
- * was completed and not dismissed.
+ * Runs a prompt and performs the prompting. 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.
  *
  * If @window_id is non-zero then it is used as an XWindow id. The Secret
  * Service can make its prompt transient for the window with this id. In some
@@ -160,21 +142,22 @@ _secret_prompt_instance (SecretService *service,
  * taken that appropriate user interface actions are disabled while running the
  * prompt.
  *
- * Returns: %FALSE if the prompt was dismissed or an error occurred
+ * Returns: (transfer full): %NULL if the prompt was dismissed or an error occurred
  */
-gboolean
+GVariant *
 secret_prompt_run (SecretPrompt *self,
                    gulong window_id,
                    GCancellable *cancellable,
+                   const GVariantType *return_type,
                    GError **error)
 {
 	GMainContext *context;
 	RunClosure *closure;
-	gboolean ret;
+	GVariant *retval;
 
-	g_return_val_if_fail (SECRET_IS_PROMPT (self), FALSE);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_val_if_fail (SECRET_IS_PROMPT (self), NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	context = g_main_context_get_thread_default ();
 
@@ -186,13 +169,13 @@ secret_prompt_run (SecretPrompt *self,
 
 	g_main_loop_run (closure->loop);
 
-	ret = secret_prompt_perform_finish (self, closure->result, error);
+	retval = secret_prompt_perform_finish (self, closure->result, return_type, error);
 
 	g_main_loop_unref (closure->loop);
 	g_object_unref (closure->result);
 	g_free (closure);
 
-	return ret;
+	return retval;
 }
 
 /**
@@ -200,10 +183,13 @@ secret_prompt_run (SecretPrompt *self,
  * @self: a prompt
  * @window_id: XWindow id for parent window to be transient for
  * @cancellable: optional cancellation object
+ * @return_type: the variant type of the prompt result
  * @error: location to place an error on failure
  *
- * Runs a prompt and performs the prompting. Returns %TRUE if the prompt
- * was completed and not dismissed.
+ * Runs a prompt and performs the prompting. 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.
  *
  * If @window_id is non-zero then it is used as an XWindow id. The Secret
  * Service can make its prompt transient for the window with this id. In some
@@ -213,25 +199,26 @@ secret_prompt_run (SecretPrompt *self,
  * This method may block indefinitely and should not be used in user interface
  * threads.
  *
- * Returns: %FALSE if the prompt was dismissed or an error occurred
+ * Returns: (transfer full): %NULL if the prompt was dismissed or an error occurred
  */
-gboolean
+GVariant *
 secret_prompt_perform_sync (SecretPrompt *self,
                             gulong window_id,
                             GCancellable *cancellable,
+                            const GVariantType *return_type,
                             GError **error)
 {
 	GMainContext *context;
-	gboolean ret;
+	GVariant *retval;
 
-	g_return_val_if_fail (SECRET_IS_PROMPT (self), FALSE);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_val_if_fail (SECRET_IS_PROMPT (self), NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	context = g_main_context_new ();
 	g_main_context_push_thread_default (context);
 
-	ret = secret_prompt_run (self, window_id, cancellable, error);
+	retval = secret_prompt_run (self, window_id, cancellable, return_type, error);
 
 	/* Needed to prevent memory leaks */
 	while (g_main_context_iteration (context, FALSE));
@@ -239,7 +226,7 @@ secret_prompt_perform_sync (SecretPrompt *self,
 	g_main_context_pop_thread_default (context);
 	g_main_context_unref (context);
 
-	return ret;
+	return retval;
 }
 
 typedef struct {
@@ -251,6 +238,7 @@ typedef struct {
 	gboolean dismissed;
 	gboolean vanished;
 	gboolean completed;
+	GVariant *result;
 	guint signal;
 	guint watch;
 } PerformClosure;
@@ -262,6 +250,8 @@ perform_closure_free (gpointer data)
 	g_object_unref (closure->call_cancellable);
 	g_clear_object (&closure->async_cancellable);
 	g_object_unref (closure->connection);
+	if (closure->result)
+		g_variant_unref (closure->result);
 	g_assert (closure->signal == 0);
 	g_assert (closure->watch == 0);
 	g_slice_free (PerformClosure, closure);
@@ -315,10 +305,7 @@ on_prompt_completed (GDBusConnection *connection,
 		perform_prompt_complete (res, TRUE);
 
 	} else {
-		g_mutex_lock (&self->pv->mutex);
-		g_variant_get (parameters, "(bv)", &dismissed, &self->pv->last_result);
-		g_mutex_unlock (&self->pv->mutex);
-
+		g_variant_get (parameters, "(bv)", &dismissed, &closure->result);
 		perform_prompt_complete (res, dismissed);
 	}
 
@@ -348,10 +335,8 @@ on_prompt_prompted (GObject *source,
 		perform_prompt_complete (res, TRUE);
 
 	} else {
-		g_mutex_lock (&self->pv->mutex);
 		closure->prompting = TRUE;
-		self->pv->prompted = TRUE;
-		g_mutex_unlock (&self->pv->mutex);
+		g_atomic_int_set (&self->pv->prompted, 1);
 
 		/* And now we wait for the signal */
 	}
@@ -453,10 +438,7 @@ secret_prompt_perform (SecretPrompt *self,
 	g_return_if_fail (SECRET_IS_PROMPT (self));
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
-	g_mutex_lock (&self->pv->mutex);
-	prompted = self->pv->prompted;
-	g_mutex_unlock (&self->pv->mutex);
-
+	prompted = g_atomic_int_get (&self->pv->prompted);
 	if (prompted) {
 		g_warning ("The prompt object has already had its prompt called.");
 		return;
@@ -513,76 +495,47 @@ secret_prompt_perform (SecretPrompt *self,
  * secret_prompt_perform_finish:
  * @self: a prompt
  * @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 run a prompt and perform the prompting.
  *
- * Returns: %FALSE if the prompt was dismissed or an error occurred
+ * 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
  */
-gboolean
+GVariant *
 secret_prompt_perform_finish (SecretPrompt *self,
                               GAsyncResult *result,
+                              const GVariantType *return_type,
                               GError **error)
 {
 	PerformClosure *closure;
 	GSimpleAsyncResult *res;
+	gchar *string;
 
-	g_return_val_if_fail (SECRET_IS_PROMPT (self), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_val_if_fail (SECRET_IS_PROMPT (self), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                                                      secret_prompt_perform), FALSE);
+	                                                      secret_prompt_perform), NULL);
 
 	res = G_SIMPLE_ASYNC_RESULT (result);
 
 	if (g_simple_async_result_propagate_error (res, error))
-		return FALSE;
+		return NULL;
 
 	closure = g_simple_async_result_get_op_res_gpointer (res);
-	return !closure->dismissed;
-}
-
-/**
- * secret_prompt_get_result_value:
- * @self: a prompt
- * @expected_type: (allow-none): expected variant type of the result
- *
- * Get the result returned from a completed prompt.
- *
- * After performing a prompt in the Secret Service API, the prompt can
- * return a result value. The type of value returned is dependent on
- * the prompt.
- *
- * It is not normally necessary to call this function, as this is done
- * automatically by other functions in this library.
- *
- * Returns: (transfer full): the result value which should be released with
- *          g_variant_unref() when done, or %NULL if no result
- */
-GVariant *
-secret_prompt_get_result_value (SecretPrompt *self,
-                                const GVariantType *expected_type)
-{
-	GVariant *last_result;
-	gchar *string;
-
-	g_return_val_if_fail (SECRET_IS_PROMPT (self), NULL);
-
-	g_mutex_lock (&self->pv->mutex);
-	if (self->pv->last_result)
-		last_result = g_variant_ref (self->pv->last_result);
-	else
-		last_result = NULL;
-	g_mutex_unlock (&self->pv->mutex);
-
-	if (last_result != NULL && expected_type != NULL &&
-	    !g_variant_is_of_type (last_result, expected_type)) {
-		string = g_variant_type_dup_string (expected_type);
+	if (closure->result == NULL)
+		return NULL;
+	if (return_type != NULL && !g_variant_is_of_type (closure->result, return_type)) {
+		string = g_variant_type_dup_string (return_type);
 		g_warning ("received unexpected result type %s from Completed signal instead of expected %s",
-		           g_variant_get_type_string (last_result), string);
-		g_variant_unref (last_result);
+		           g_variant_get_type_string (closure->result), string);
 		g_free (string);
 		return NULL;
 	}
-
-	return last_result;
+	return g_variant_ref (closure->result);
 }
diff --git a/library/secret-prompt.h b/library/secret-prompt.h
index 14d72d5..15b035e 100644
--- a/library/secret-prompt.h
+++ b/library/secret-prompt.h
@@ -51,14 +51,16 @@ struct _SecretPromptClass {
 
 GType               secret_prompt_get_type                  (void) G_GNUC_CONST;
 
-gboolean            secret_prompt_run                       (SecretPrompt *self,
+GVariant *          secret_prompt_run                       (SecretPrompt *self,
                                                              gulong window_id,
                                                              GCancellable *cancellable,
+                                                             const GVariantType *return_type,
                                                              GError **error);
 
-gboolean            secret_prompt_perform_sync              (SecretPrompt *self,
+GVariant *          secret_prompt_perform_sync              (SecretPrompt *self,
                                                              gulong window_id,
                                                              GCancellable *cancellable,
+                                                             const GVariantType *return_type,
                                                              GError **error);
 
 void                secret_prompt_perform                   (SecretPrompt *self,
@@ -67,13 +69,11 @@ void                secret_prompt_perform                   (SecretPrompt *self,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            secret_prompt_perform_finish            (SecretPrompt *self,
+GVariant *          secret_prompt_perform_finish            (SecretPrompt *self,
                                                              GAsyncResult *result,
+                                                             const GVariantType *return_type,
                                                              GError **error);
 
-GVariant *          secret_prompt_get_result_value          (SecretPrompt *self,
-                                                             const GVariantType *expected_type);
-
 G_END_DECLS
 
 #endif /* __SECRET_PROMPT_H___ */
diff --git a/library/secret-service.c b/library/secret-service.c
index bebbdcc..9753616 100644
--- a/library/secret-service.c
+++ b/library/secret-service.c
@@ -209,13 +209,14 @@ secret_service_finalize (GObject *obj)
 	G_OBJECT_CLASS (secret_service_parent_class)->finalize (obj);
 }
 
-static gboolean
+static GVariant *
 secret_service_real_prompt_sync (SecretService *self,
                                  SecretPrompt *prompt,
                                  GCancellable *cancellable,
+                                 const GVariantType *return_type,
                                  GError **error)
 {
-	return secret_prompt_perform_sync (prompt, 0, cancellable, error);
+	return secret_prompt_perform_sync (prompt, 0, cancellable, return_type, error);
 }
 
 static void
@@ -225,14 +226,14 @@ on_real_prompt_completed (GObject *source,
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
 	GError *error = NULL;
-	gboolean ret;
+	GVariant *retval;
 
-	ret = secret_prompt_perform_finish (SECRET_PROMPT (source), result, &error);
-	g_simple_async_result_set_op_res_gboolean (res, ret);
+	retval = secret_prompt_perform_finish (SECRET_PROMPT (source), result, NULL, &error);
+	if (retval != NULL)
+		g_simple_async_result_set_op_res_gpointer (res, retval, (GDestroyNotify)g_variant_unref);
 	if (error != NULL)
 		g_simple_async_result_take_error (res, error);
 	g_simple_async_result_complete (res);
-
 	g_object_unref (res);
 }
 
@@ -255,17 +256,36 @@ secret_service_real_prompt_async (SecretService *self,
 	g_object_unref (res);
 }
 
-static gboolean
+static GVariant *
 secret_service_real_prompt_finish (SecretService *self,
                                    GAsyncResult *result,
+                                   const GVariantType *return_type,
                                    GError **error)
 {
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (result);
+	GSimpleAsyncResult *res;
+	GVariant *retval;
+	gchar *string;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      secret_service_real_prompt_async), NULL);
 
+	res = G_SIMPLE_ASYNC_RESULT (result);
 	if (g_simple_async_result_propagate_error (res, error))
-		return FALSE;
+		return NULL;
 
-	return g_simple_async_result_get_op_res_gboolean (res);
+	retval = g_simple_async_result_get_op_res_gpointer (res);
+	if (retval == NULL)
+		return NULL;
+
+	if (return_type != NULL && !g_variant_is_of_type (retval, return_type)) {
+		string = g_variant_type_dup_string (return_type);
+		g_warning ("received unexpected result type %s from prompt's Completed signal instead of expected %s",
+		           g_variant_get_type_string (retval), string);
+		g_free (string);
+		return NULL;
+	}
+
+	return g_variant_ref (retval);
 }
 
 static void
@@ -1492,10 +1512,16 @@ secret_service_ensure_collections_sync (SecretService *self,
  * @self: the secret service
  * @prompt: the prompt
  * @cancellable: optional cancellation object
+ * @return_type: the variant type of the prompt result
  * @error: location to place an error on failure
  *
  * Perform prompting for a #SecretPrompt.
  *
+ * Runs a prompt and performs the prompting. 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.
+ *
  * This function is called by other parts of this library to handle prompts
  * for the various actions that can require prompting.
  *
@@ -1503,25 +1529,27 @@ secret_service_ensure_collections_sync (SecretService *self,
  * to change the behavior of the propmting. The default behavior is to simply
  * run secret_prompt_perform_sync() on the prompt.
  *
- * Returns: %FALSE if the prompt was dismissed or an error occurred
+ * Returns: (transfer full): %NULL if the prompt was dismissed or an error occurred,
+ *          a variant result if the prompt was successful
  */
-gboolean
+GVariant *
 secret_service_prompt_sync (SecretService *self,
                             SecretPrompt *prompt,
                             GCancellable *cancellable,
+                            const GVariantType *return_type,
                             GError **error)
 {
 	SecretServiceClass *klass;
 
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (SECRET_IS_PROMPT (prompt), FALSE);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_val_if_fail (SECRET_IS_SERVICE (self), NULL);
+	g_return_val_if_fail (SECRET_IS_PROMPT (prompt), NULL);
+	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	klass = SECRET_SERVICE_GET_CLASS (self);
-	g_return_val_if_fail (klass->prompt_sync != NULL, FALSE);
+	g_return_val_if_fail (klass->prompt_sync != NULL, NULL);
 
-	return (klass->prompt_sync) (self, prompt, cancellable, error);
+	return (klass->prompt_sync) (self, prompt, cancellable, return_type, error);
 }
 
 /**
@@ -1564,25 +1592,118 @@ secret_service_prompt (SecretService *self,
  * secret_service_prompt_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: %FALSE if the prompt was dismissed or an error occurred
+ * 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
  */
-gboolean
+GVariant *
 secret_service_prompt_finish (SecretService *self,
                               GAsyncResult *result,
+                              const GVariantType *return_type,
                               GError **error)
 {
 	SecretServiceClass *klass;
 
-	g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
-	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	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);
 
 	klass = SECRET_SERVICE_GET_CLASS (self);
-	g_return_val_if_fail (klass->prompt_finish != NULL, FALSE);
+	g_return_val_if_fail (klass->prompt_finish != NULL, NULL);
+
+	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 (klass->prompt_finish) (self, result, error);
+	return secret_service_prompt_finish (self, result, return_type, error);
 }
diff --git a/library/secret-service.h b/library/secret-service.h
index 64f8e2f..82f246e 100644
--- a/library/secret-service.h
+++ b/library/secret-service.h
@@ -58,19 +58,21 @@ struct _SecretServiceClass {
 	GType collection_gtype;
 	GType item_gtype;
 
-	gboolean (*prompt_sync)          (SecretService *self,
+	GVariant *  (* prompt_sync)      (SecretService *self,
 	                                  SecretPrompt *prompt,
 	                                  GCancellable *cancellable,
+	                                  const GVariantType *return_type,
 	                                  GError **error);
 
-	void     (*prompt_async)         (SecretService *self,
+	void        (* prompt_async)     (SecretService *self,
 	                                  SecretPrompt *prompt,
 	                                  GCancellable *cancellable,
 	                                  GAsyncReadyCallback callback,
 	                                  gpointer user_data);
 
-	gboolean (*prompt_finish)        (SecretService *self,
+	GVariant *  (* prompt_finish)    (SecretService *self,
 	                                  GAsyncResult *result,
+	                                  const GVariantType *return_type,
 	                                  GError **error);
 
 	/*< private >*/
@@ -290,9 +292,10 @@ gint                 secret_service_unlock_paths_finish           (SecretService
                                                                    gchar ***unlocked,
                                                                    GError **error);
 
-gboolean             secret_service_prompt_sync                   (SecretService *self,
+GVariant *           secret_service_prompt_sync                   (SecretService *self,
                                                                    SecretPrompt *prompt,
                                                                    GCancellable *cancellable,
+                                                                   const GVariantType *return_type,
                                                                    GError **error);
 
 void                 secret_service_prompt                        (SecretService *self,
@@ -301,8 +304,26 @@ void                 secret_service_prompt                        (SecretService
                                                                    GAsyncReadyCallback callback,
                                                                    gpointer user_data);
 
-gboolean             secret_service_prompt_finish                 (SecretService *self,
+GVariant *           secret_service_prompt_finish                 (SecretService *self,
                                                                    GAsyncResult *result,
+                                                                   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,
diff --git a/library/tests/test-prompt.c b/library/tests/test-prompt.c
index e84bebe..9a7fd29 100644
--- a/library/tests/test-prompt.c
+++ b/library/tests/test-prompt.c
@@ -83,7 +83,7 @@ test_perform_sync (Test *test,
 {
 	SecretPrompt *prompt;
 	GError *error = NULL;
-	gboolean ret;
+	GVariant *retval;
 	guint value = 0;
 	guint increment_id;
 
@@ -92,9 +92,10 @@ test_perform_sync (Test *test,
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
 
-	ret = secret_prompt_perform_sync (prompt, 0, NULL, &error);
+	retval = secret_prompt_perform_sync (prompt, 0, NULL, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
+	g_assert (retval != NULL);
+	g_variant_unref (retval);
 
 	g_assert_cmpuint (value, ==, 0);
 	g_source_remove (increment_id);
@@ -109,7 +110,7 @@ test_perform_run (Test *test,
 {
 	SecretPrompt *prompt;
 	GError *error = NULL;
-	gboolean ret;
+	GVariant *retval;
 	guint value = 0;
 	guint increment_id;
 
@@ -118,9 +119,10 @@ test_perform_run (Test *test,
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
 
-	ret = secret_prompt_run (prompt, 0, NULL, &error);
+	retval = secret_prompt_run (prompt, 0, NULL, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret);
+	g_assert (retval != NULL);
+	g_variant_unref (retval);
 
 	g_assert_cmpuint (value, >, 0);
 	g_source_remove (increment_id);
@@ -139,7 +141,7 @@ test_perform_async (Test *test,
 	SecretPrompt *prompt;
 	GError *error = NULL;
 	GAsyncResult *result = NULL;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
 
@@ -148,9 +150,10 @@ test_perform_async (Test *test,
 
 	egg_test_wait ();
 
-	ret = secret_prompt_perform_finish (prompt, result, &error);
+	retval = secret_prompt_perform_finish (prompt, result, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
+	g_assert (retval != NULL);
+	g_variant_unref (retval);
 	g_object_unref (result);
 
 	/* Make sure everything completes */
@@ -168,7 +171,7 @@ test_perform_cancel (Test *test,
 	GError *error = NULL;
 	GAsyncResult *result = NULL;
 	GCancellable *cancellable;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/delay");
 
@@ -181,9 +184,10 @@ test_perform_cancel (Test *test,
 
 	egg_test_wait ();
 
-	ret = secret_prompt_perform_finish (prompt, result, &error);
+	retval = secret_prompt_perform_finish (prompt, result, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
+	g_assert (retval != NULL);
+	g_variant_unref (retval);
 
 	g_object_unref (result);
 	g_object_unref (prompt);
@@ -200,13 +204,13 @@ test_perform_fail (Test *test,
 {
 	SecretPrompt *prompt;
 	GError *error = NULL;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/error");
 
-	ret = secret_prompt_perform_sync (prompt, 0, NULL, &error);
+	retval = secret_prompt_perform_sync (prompt, 0, NULL, NULL, &error);
 	g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED);
-	g_assert (ret == FALSE);
+	g_assert (retval == NULL);
 
 	g_object_unref (prompt);
 	egg_assert_not_object (prompt);
@@ -218,13 +222,13 @@ test_perform_vanish (Test *test,
 {
 	SecretPrompt *prompt;
 	GError *error = NULL;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/vanish");
 
-	ret = secret_prompt_perform_sync (prompt, 0, NULL, &error);
+	retval = secret_prompt_perform_sync (prompt, 0, NULL, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret == FALSE);
+	g_assert (retval == NULL);
 
 	g_object_unref (prompt);
 	egg_assert_not_object (prompt);
@@ -236,22 +240,15 @@ test_prompt_result (Test *test,
 {
 	SecretPrompt *prompt;
 	GError *error = NULL;
-	gboolean ret;
-	GVariant *result;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/result");
 
-	result = secret_prompt_get_result_value (prompt, NULL);
-	g_assert (result == NULL);
-
-	ret = secret_prompt_perform_sync (prompt, 0, NULL, &error);
+	retval = secret_prompt_perform_sync (prompt, 0, NULL, G_VARIANT_TYPE_STRING, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	result = secret_prompt_get_result_value (prompt, G_VARIANT_TYPE_STRING);
-	g_assert (result != NULL);
-	g_assert_cmpstr (g_variant_get_string (result, NULL), ==, "Special Result");
-	g_variant_unref (result);
+	g_assert (retval != NULL);
+	g_assert_cmpstr (g_variant_get_string (retval, NULL), ==, "Special Result");
+	g_variant_unref (retval);
 
 	g_object_unref (prompt);
 	egg_assert_not_object (prompt);
@@ -263,19 +260,15 @@ test_prompt_window_id (Test *test,
 {
 	SecretPrompt *prompt;
 	GError *error = NULL;
-	gboolean ret;
-	GVariant *result;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/window");
 
-	ret = secret_prompt_perform_sync (prompt, 555, NULL, &error);
+	retval = secret_prompt_perform_sync (prompt, 555, NULL, G_VARIANT_TYPE_STRING, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
-
-	result = secret_prompt_get_result_value (prompt, G_VARIANT_TYPE_STRING);
-	g_assert (result != NULL);
-	g_assert_cmpstr (g_variant_get_string (result, NULL), ==, "555");
-	g_variant_unref (result);
+	g_assert (retval != NULL);
+	g_assert_cmpstr (g_variant_get_string (retval, NULL), ==, "555");
+	g_variant_unref (retval);
 
 	g_object_unref (prompt);
 	egg_assert_not_object (prompt);
@@ -287,13 +280,14 @@ test_service_sync (Test *test,
 {
 	SecretPrompt *prompt;
 	GError *error = NULL;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
 
-	ret = secret_service_prompt_sync (test->service, prompt, NULL, &error);
+	retval = secret_service_prompt_sync (test->service, prompt, NULL, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
+	g_assert (retval != NULL);
+	g_variant_unref (retval);
 
 	g_object_unref (prompt);
 	egg_assert_not_object (prompt);
@@ -306,7 +300,7 @@ test_service_async (Test *test,
 	SecretPrompt *prompt;
 	GError *error = NULL;
 	GAsyncResult *result = NULL;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
 
@@ -315,9 +309,10 @@ test_service_async (Test *test,
 
 	egg_test_wait ();
 
-	ret = secret_service_prompt_finish (test->service, result, &error);
+	retval = secret_service_prompt_finish (test->service, result, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
+	g_assert (retval != NULL);
+	g_variant_unref (retval);
 	g_object_unref (result);
 
 	/* Make sure everything completes */
@@ -334,7 +329,7 @@ test_service_fail (Test *test,
 	SecretPrompt *prompt;
 	GError *error = NULL;
 	GAsyncResult *result = NULL;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/error");
 
@@ -343,9 +338,9 @@ test_service_fail (Test *test,
 
 	egg_test_wait ();
 
-	ret = secret_service_prompt_finish (test->service, result, &error);
+	retval = secret_service_prompt_finish (test->service, result, NULL, &error);
 	g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED);
-	g_assert (ret == FALSE);
+	g_assert (retval == NULL);
 	g_object_unref (result);
 
 	/* Make sure everything completes */
@@ -362,7 +357,7 @@ test_service_path (Test *test,
 	GError *error = NULL;
 	GAsyncResult *result = NULL;
 	SecretPrompt *prompt;
-	gboolean ret;
+	GVariant *retval;
 
 	prompt = _secret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/simple");
 
@@ -372,9 +367,10 @@ test_service_path (Test *test,
 	g_object_unref (prompt);
 	egg_test_wait ();
 
-	ret = secret_service_prompt_finish (test->service, result, &error);
+	retval = secret_service_prompt_finish (test->service, result, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (ret == TRUE);
+	g_assert (retval != NULL);
+	g_variant_unref (retval);
 	g_object_unref (result);
 
 	/* Make sure everything completes */



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