[gcr] gcr: Implement prompt-close in GcrSystemPrompt and GcrSystemPrompter
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcr] gcr: Implement prompt-close in GcrSystemPrompt and GcrSystemPrompter
- Date: Mon, 22 Oct 2012 14:02:06 +0000 (UTC)
commit d042d43ae1f44c37334fd620ad1e5625f06aa88f
Author: Stef Walter <stefw gnome org>
Date: Fri Sep 21 10:23:23 2012 +0200
gcr: Implement prompt-close in GcrSystemPrompt and GcrSystemPrompter
* Properly relay the prompt-close signal from GcrSystemPrompter
back to GcrSystemPrompt by firing the PromptDone callback method
on the caller's DBus interface.
* Make sure GcrSystemPrompt emits prompt-close appropriately for
all the various paths that can close the prompt.
* Add testing of the above, and changes in the mock prompter for this.
https://bugzilla.gnome.org/show_bug.cgi?id=678611
docs/reference/gcr/gcr-sections.txt | 1 +
gcr/gcr-base.symbols | 1 +
gcr/gcr-mock-prompter.c | 44 +++++++
gcr/gcr-mock-prompter.h | 2 +
gcr/gcr-system-prompt.c | 212 +++++++++++++++++++++--------------
gcr/gcr-system-prompter.c | 58 ++++++++--
gcr/tests/frob-system-prompt.c | 3 +
gcr/tests/test-system-prompt.c | 99 ++++++++++++++++
8 files changed, 324 insertions(+), 96 deletions(-)
---
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index 2b21ca9..b39923e 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -851,6 +851,7 @@ gcr_mock_prompter_expect_confirm_cancel
gcr_mock_prompter_expect_confirm_ok
gcr_mock_prompter_expect_password_cancel
gcr_mock_prompter_expect_password_ok
+gcr_mock_prompter_expect_close
gcr_mock_prompter_get_delay_msec
gcr_mock_prompter_set_delay_msec
gcr_mock_prompter_is_expecting
diff --git a/gcr/gcr-base.symbols b/gcr/gcr-base.symbols
index bcf7bfb..c794829 100644
--- a/gcr/gcr-base.symbols
+++ b/gcr/gcr-base.symbols
@@ -100,6 +100,7 @@ gcr_import_interaction_supplement
gcr_import_interaction_supplement_async
gcr_import_interaction_supplement_finish
gcr_import_interaction_supplement_prep
+gcr_mock_prompter_expect_close
gcr_mock_prompter_expect_confirm_cancel
gcr_mock_prompter_expect_confirm_ok
gcr_mock_prompter_expect_password_cancel
diff --git a/gcr/gcr-mock-prompter.c b/gcr/gcr-mock-prompter.c
index 1ef31e0..564ed2d 100644
--- a/gcr/gcr-mock-prompter.c
+++ b/gcr/gcr-mock-prompter.c
@@ -88,6 +88,7 @@ struct _GcrMockPromptClass {
};
typedef struct {
+ gboolean close;
gboolean proceed;
gchar *password;
GList *properties;
@@ -403,6 +404,17 @@ on_timeout_complete (gpointer data)
return FALSE;
}
+static gboolean
+on_timeout_complete_and_close (gpointer data)
+{
+ GSimpleAsyncResult *res = data;
+ GcrPrompt *prompt = GCR_PROMPT (g_async_result_get_source_object (data));
+ g_simple_async_result_complete (res);
+ gcr_prompt_close (prompt);
+ g_object_unref (prompt);
+ return FALSE;
+}
+
static void
gcr_mock_prompt_confirm_async (GcrPrompt *prompt,
GCancellable *cancellable,
@@ -428,6 +440,10 @@ gcr_mock_prompt_confirm_async (GcrPrompt *prompt,
g_critical ("password prompt requested, but not expected");
g_simple_async_result_set_op_res_gboolean (res, FALSE);
+ } else if (response->close) {
+ complete_func = on_timeout_complete_and_close;
+ g_simple_async_result_set_op_res_gboolean (res, FALSE);
+
} else if (response->password) {
g_critical ("confirmation prompt requested, but password prompt expected");
g_simple_async_result_set_op_res_gboolean (res, FALSE);
@@ -504,6 +520,10 @@ gcr_mock_prompt_password_async (GcrPrompt *prompt,
g_critical ("password prompt requested, but not expected");
g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
+ } else if (response->close) {
+ g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
+ complete_func = on_timeout_complete_and_close;
+
} else if (!response->password) {
g_critical ("password prompt requested, but confirmation prompt expected");
g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
@@ -798,6 +818,30 @@ gcr_mock_prompter_expect_password_cancel (void)
}
/**
+ * gcr_mock_prompter_expect_close:
+ *
+ * Queue an expected response on the mock prompter.
+ *
+ * Expects any prompt, and closes the prompt when it gets it.
+ */
+void
+gcr_mock_prompter_expect_close (void)
+{
+ MockResponse *response;
+
+ g_assert (running != NULL);
+
+ g_mutex_lock (running->mutex);
+
+ response = g_new0 (MockResponse, 1);
+ response->close = TRUE;
+
+ g_queue_push_tail (&running->responses, response);
+
+ g_mutex_unlock (running->mutex);
+}
+
+/**
* gcr_mock_prompter_is_expecting:
*
* Check if the mock prompter is expecting a response. This will be %TRUE
diff --git a/gcr/gcr-mock-prompter.h b/gcr/gcr-mock-prompter.h
index 43c53cb..3e2cf26 100644
--- a/gcr/gcr-mock-prompter.h
+++ b/gcr/gcr-mock-prompter.h
@@ -55,6 +55,8 @@ void gcr_mock_prompter_expect_password_ok (const gchar *p
void gcr_mock_prompter_expect_password_cancel (void);
+void gcr_mock_prompter_expect_close (void);
+
gboolean gcr_mock_prompter_is_expecting (void);
G_END_DECLS
diff --git a/gcr/gcr-system-prompt.c b/gcr/gcr-system-prompt.c
index b66e30e..640aa77 100644
--- a/gcr/gcr-system-prompt.c
+++ b/gcr/gcr-system-prompt.c
@@ -390,15 +390,100 @@ gcr_system_prompt_constructed (GObject *obj)
}
static void
+on_prompter_stop_prompting (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *async = NULL;
+ GError *error = NULL;
+ GVariant *retval;
+
+ retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+ if (error != NULL) {
+ _gcr_debug ("failed to stop prompting: %s", egg_error_message (error));
+ g_clear_error (&error);
+ }
+
+ if (retval)
+ g_variant_unref (retval);
+
+ if (user_data) {
+ async = G_SIMPLE_ASYNC_RESULT (user_data);
+ g_simple_async_result_complete (async);
+ g_object_unref (async);
+ }
+}
+
+static void
+perform_close (GcrSystemPrompt *self,
+ GSimpleAsyncResult *async,
+ GCancellable *cancellable)
+{
+ GSimpleAsyncResult *res;
+ CallClosure *closure;
+ gboolean called = FALSE;
+ gboolean closed;
+
+ closed = self->pv->closed;
+ self->pv->closed = TRUE;
+
+ if (!closed)
+ _gcr_debug ("closing prompt");
+
+ if (self->pv->pending) {
+ res = g_object_ref (self->pv->pending);
+ g_clear_object (&self->pv->pending);
+ closure = g_simple_async_result_get_op_res_gpointer (res);
+ g_cancellable_cancel (closure->cancellable);
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+ }
+
+ if (self->pv->prompt_registered) {
+ g_dbus_connection_unregister_object (self->pv->connection,
+ self->pv->prompt_registered);
+ self->pv->prompt_registered = 0;
+ }
+
+ if (self->pv->begun_prompting) {
+ if (self->pv->connection && self->pv->prompt_path) {
+ _gcr_debug ("Calling the prompter %s method", GCR_DBUS_PROMPTER_METHOD_STOP);
+ g_dbus_connection_call (self->pv->connection,
+ self->pv->prompter_bus_name,
+ GCR_DBUS_PROMPTER_OBJECT_PATH,
+ GCR_DBUS_PROMPTER_INTERFACE,
+ GCR_DBUS_PROMPTER_METHOD_STOP,
+ g_variant_new ("(o)", self->pv->prompt_path),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1, cancellable,
+ on_prompter_stop_prompting,
+ async ? g_object_ref (async) : NULL);
+ called = TRUE;
+ }
+ self->pv->begun_prompting = FALSE;
+ }
+
+ g_free (self->pv->prompt_path);
+ self->pv->prompt_path = NULL;
+
+ g_clear_object (&self->pv->connection);
+
+ if (!called && async)
+ g_simple_async_result_complete_in_idle (async);
+
+ /* Emit the signal if necessary, after closed */
+ if (!closed)
+ gcr_prompt_close (GCR_PROMPT (self));
+}
+
+static void
gcr_system_prompt_dispose (GObject *obj)
{
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (obj);
g_clear_object (&self->pv->exchange);
-
- _gcr_debug ("closing prompt asynchronously: %s", self->pv->prompt_path);
- if (self->pv->connection)
- gcr_system_prompt_close_async (self, NULL, NULL, NULL);
+ perform_close (self, NULL, NULL);
g_hash_table_remove_all (self->pv->properties);
g_hash_table_remove_all (self->pv->dirty_properties);
@@ -559,17 +644,15 @@ prompt_method_done (GcrSystemPrompt *self,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
- GSimpleAsyncResult *res;
-
- g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (self->pv->pending));
-
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
- res = g_object_ref (self->pv->pending);
- g_clear_object (&self->pv->pending);
- g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
- g_simple_async_result_complete (res);
- g_object_unref (res);
+ /*
+ * At this point we're done prompting, and calling StopPrompting
+ * on the prompter is no longer necessary. It may have already been
+ * called, or the prompter may have stopped on its own accord.
+ */
+ self->pv->begun_prompting = FALSE;
+ perform_close (self, NULL, NULL);
}
static void
@@ -951,8 +1034,9 @@ on_perform_prompt_complete (GObject *source,
retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
if (error != NULL) {
+ self->pv->pending = NULL;
g_simple_async_result_take_error (res, error);
- g_simple_async_result_complete_in_idle (res);
+ g_simple_async_result_complete (res);
}
if (retval)
@@ -984,13 +1068,20 @@ perform_prompt_async (GcrSystemPrompt *self,
return;
}
- _gcr_debug ("prompting for password");
-
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, source_tag);
closure = g_new0 (CallClosure, 1);
closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
g_simple_async_result_set_op_res_gpointer (res, closure, call_closure_free);
+ if (self->pv->closed) {
+ self->pv->last_response = g_strdup (GCR_DBUS_PROMPT_REPLY_NONE);
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+ return;
+ }
+
+ _gcr_debug ("prompting for password");
+
exchange = gcr_system_prompt_get_secret_exchange (self);
if (self->pv->received)
sent = gcr_secret_exchange_send (exchange, NULL, 0);
@@ -1107,12 +1198,29 @@ gcr_system_prompt_confirm_finish (GcrPrompt *prompt,
}
static void
+gcr_system_prompt_real_close (GcrPrompt *prompt)
+{
+ GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (prompt);
+
+ /*
+ * Setting this before calling close_async allows us to prevent firing
+ * this signal again in a loop.
+ */
+
+ if (!self->pv->closed) {
+ self->pv->closed = TRUE;
+ perform_close (self, NULL, NULL);
+ }
+}
+
+static void
gcr_system_prompt_prompt_iface (GcrPromptIface *iface)
{
iface->prompt_password_async = gcr_system_prompt_password_async;
iface->prompt_password_finish = gcr_system_prompt_password_finish;
iface->prompt_confirm_async = gcr_system_prompt_confirm_async;
iface->prompt_confirm_finish = gcr_system_prompt_confirm_finish;
+ iface->prompt_close = gcr_system_prompt_real_close;
}
/**
@@ -1299,8 +1407,8 @@ gcr_system_prompt_open_for_prompter (const gchar *prompter_name,
* @cancellable: an optional cancellation object
* @error: location to place an error on failure
*
- * Close this prompt. After calling this function, no further methods may be
- * called on this object. The prompt object is not unreferenced by this
+ * Close this prompt. After calling this function, no further prompts will
+ * succeed on this object. The prompt object is not unreferenced by this
* function, and you must unreference it once done.
*
* This call may block, use the gcr_system_prompt_close_async() to perform
@@ -1335,28 +1443,6 @@ gcr_system_prompt_close (GcrSystemPrompt *self,
return result;
}
-static void
-on_prompter_stop_prompting (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- GError *error = NULL;
- GVariant *retval;
-
- retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
- if (error != NULL) {
- _gcr_debug ("failed to stop prompting: %s", egg_error_message (error));
- g_clear_error (&error);
- }
-
- if (retval)
- g_variant_unref (retval);
-
- g_simple_async_result_complete (res);
- g_object_unref (res);
-}
-
/**
* gcr_system_prompt_close_async:
* @self: the prompt
@@ -1378,25 +1464,9 @@ gcr_system_prompt_close_async (GcrSystemPrompt *self,
{
GSimpleAsyncResult *res;
CallClosure *closure;
- gboolean called = FALSE;
g_return_if_fail (GCR_SYSTEM_PROMPT (self));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- g_return_if_fail (self->pv->connection != NULL);
- g_return_if_fail (self->pv->prompt_path != NULL);
- g_return_if_fail (self->pv->closed == FALSE);
-
- _gcr_debug ("closing prompt");
- self->pv->closed = TRUE;
-
- if (self->pv->pending) {
- res = g_object_ref (self->pv->pending);
- g_clear_object (&self->pv->pending);
- closure = g_simple_async_result_get_op_res_gpointer (res);
- g_cancellable_cancel (closure->cancellable);
- g_simple_async_result_complete_in_idle (res);
- g_object_unref (res);
- }
res = g_simple_async_result_new (NULL, callback, user_data,
gcr_system_prompt_close_async);
@@ -1407,36 +1477,8 @@ gcr_system_prompt_close_async (GcrSystemPrompt *self,
g_main_context_ref (closure->context);
g_simple_async_result_set_op_res_gpointer (res, closure, call_closure_free);
- if (self->pv->prompt_registered) {
- g_dbus_connection_unregister_object (self->pv->connection,
- self->pv->prompt_registered);
- self->pv->prompt_registered = 0;
- }
+ perform_close (self, res, closure->cancellable);
- if (self->pv->begun_prompting) {
- if (self->pv->connection) {
- g_dbus_connection_call (self->pv->connection,
- self->pv->prompter_bus_name,
- GCR_DBUS_PROMPTER_OBJECT_PATH,
- GCR_DBUS_PROMPTER_INTERFACE,
- GCR_DBUS_PROMPTER_METHOD_STOP,
- g_variant_new ("(o)", self->pv->prompt_path),
- G_VARIANT_TYPE ("()"),
- G_DBUS_CALL_FLAGS_NO_AUTO_START,
- -1, closure->cancellable,
- on_prompter_stop_prompting,
- g_object_ref (res));
- called = TRUE;
- }
- }
-
- g_free (self->pv->prompt_path);
- self->pv->prompt_path = NULL;
-
- g_clear_object (&self->pv->connection);
-
- if (!called)
- g_simple_async_result_complete_in_idle (res);
g_object_unref (res);
}
diff --git a/gcr/gcr-system-prompter.c b/gcr/gcr-system-prompter.c
index fb03ec8..ba16dcc 100644
--- a/gcr/gcr-system-prompter.c
+++ b/gcr/gcr-system-prompter.c
@@ -121,6 +121,8 @@ typedef struct {
GHashTable *changed;
GcrSecretExchange *exchange;
gboolean received;
+ gboolean closed;
+ guint close_sig;
} ActivePrompt;
static void prompt_send_ready (ActivePrompt *active,
@@ -151,6 +153,14 @@ on_prompt_notify (GObject *object,
g_hash_table_replace (active->changed, key, key);
}
+static void
+on_prompt_close (GcrPrompt *prompt,
+ gpointer user_data)
+{
+ ActivePrompt *active = user_data;
+ prompt_stop_prompting (active->prompter, active->callback, TRUE, FALSE);
+}
+
static Callback *
callback_dup (Callback *original)
{
@@ -195,9 +205,13 @@ active_prompt_unref (gpointer data)
ActivePrompt *active = data;
if (g_atomic_int_dec_and_test (&active->refs)) {
+ callback_free (active->callback);
g_object_unref (active->prompter);
g_object_unref (active->cancellable);
- g_signal_handlers_disconnect_by_func (active->prompt, on_prompt_notify, active);
+ if (g_signal_handler_is_connected (active->prompt, active->notify_sig))
+ g_signal_handler_disconnect (active->prompt, active->notify_sig);
+ if (g_signal_handler_is_connected (active->prompt, active->close_sig))
+ g_signal_handler_disconnect (active->prompt, active->close_sig);
g_object_unref (active->prompt);
g_hash_table_destroy (active->changed);
if (active->exchange)
@@ -221,17 +235,15 @@ active_prompt_create (GcrSystemPrompter *self,
ActivePrompt *active;
active = g_slice_new0 (ActivePrompt);
- if (!g_hash_table_lookup_extended (self->pv->callbacks, lookup,
- (gpointer *)&active->callback, NULL))
- g_return_val_if_reached (NULL);
-
active->refs = 1;
+ active->callback = callback_dup (lookup);
active->prompter = g_object_ref (self);
active->cancellable = g_cancellable_new ();
g_signal_emit (self, signals[NEW_PROMPT], 0, &active->prompt);
g_return_val_if_fail (active->prompt != NULL, NULL);
active->notify_sig = g_signal_connect (active->prompt, "notify", G_CALLBACK (on_prompt_notify), active);
+ active->close_sig = g_signal_connect (active->prompt, "prompt-close", G_CALLBACK (on_prompt_close), active);
active->changed = g_hash_table_new (g_direct_hash, g_direct_equal);
/* Insert us into the active hash table */
@@ -481,11 +493,26 @@ prompt_stop_prompting (GcrSystemPrompter *self,
{
ActivePrompt *active;
GVariant *retval;
+ gpointer watch;
+
+ _gcr_debug ("stopping prompting for operation %s %s",
+ callback->path, callback->name);
/* Get a pointer to our actual callback */
if (!g_hash_table_lookup_extended (self->pv->callbacks, callback,
- (gpointer *)&callback, NULL))
+ (gpointer *)&callback, &watch)) {
+ _gcr_debug ("couldn't find the callback for prompting operation %s %s",
+ callback->path, callback->name);
return;
+ }
+
+ /*
+ * We remove these from the callbacks hash table so that we don't
+ * do this stuff more than once. However we still need the callback
+ * to be valid.
+ */
+ if (!g_hash_table_steal (self->pv->callbacks, callback))
+ g_assert_not_reached ();
/* Removed from the waiting queue */
g_queue_remove (&self->pv->waiting, callback);
@@ -493,16 +520,19 @@ prompt_stop_prompting (GcrSystemPrompter *self,
/* Close any active prompt */
active = g_hash_table_lookup (self->pv->active, callback);
if (active != NULL) {
+ active_prompt_ref (active);
+ g_hash_table_remove (self->pv->active, callback);
+
if (!active->ready) {
_gcr_debug ("cancelling active prompting operation for %s %s",
callback->path, callback->name);
g_cancellable_cancel (active->cancellable);
}
- _gcr_debug ("disposing the prompt");
-
+ _gcr_debug ("closing the prompt");
+ gcr_prompt_close (active->prompt);
g_object_run_dispose (G_OBJECT (active->prompt));
- g_hash_table_remove (self->pv->active, callback);
+ active_prompt_unref (active);
}
/* Notify the caller */
@@ -540,8 +570,14 @@ prompt_stop_prompting (GcrSystemPrompter *self,
-1, NULL, NULL, NULL);
}
- /* And all traces gone, including watch */
- g_hash_table_remove (self->pv->callbacks, callback);
+ /*
+ * And all traces gone, including watch. We stole these values from
+ * the callbacks hashtable above. Now free them
+ */
+
+ callback_free (callback);
+ unwatch_name (watch);
+
g_object_notify (G_OBJECT (self), "prompting");
}
diff --git a/gcr/tests/frob-system-prompt.c b/gcr/tests/frob-system-prompt.c
index 39919b3..b743adf 100644
--- a/gcr/tests/frob-system-prompt.c
+++ b/gcr/tests/frob-system-prompt.c
@@ -25,6 +25,8 @@
#include "gcr/gcr.h"
+#include "egg/egg-testing.h"
+
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
@@ -67,6 +69,7 @@ on_prompt_clicked (GtkToolButton *button,
g_print ("password: %s\n", password);
g_object_unref (prompt);
+ egg_assert_not_object (prompt);
}
static gboolean
diff --git a/gcr/tests/test-system-prompt.c b/gcr/tests/test-system-prompt.c
index d0450b5..0d48124 100644
--- a/gcr/tests/test-system-prompt.c
+++ b/gcr/tests/test-system-prompt.c
@@ -513,6 +513,15 @@ test_prompt_close (Test *test,
}
static void
+on_prompt_close (GcrPrompt *prompt,
+ gpointer user_data)
+{
+ gboolean *prompt_closed = (gboolean *)user_data;
+ g_assert (*prompt_closed == FALSE);
+ *prompt_closed = TRUE;
+}
+
+static void
test_close_cancels (Test *test,
gconstpointer unused)
{
@@ -520,6 +529,7 @@ test_close_cancels (Test *test,
GError *error = NULL;
const gchar *password = NULL;
GAsyncResult *result = NULL;
+ gboolean prompt_closed;
gcr_mock_prompter_set_delay_msec (3000);
gcr_mock_prompter_expect_password_ok ("booo", NULL);
@@ -528,11 +538,15 @@ test_close_cancels (Test *test,
g_assert_no_error (error);
g_assert (GCR_IS_SYSTEM_PROMPT (prompt));
+ prompt_closed = FALSE;
+ g_signal_connect_after (prompt, "prompt-close", G_CALLBACK (on_prompt_close), &prompt_closed);
+
gcr_prompt_password_async (prompt, NULL, on_async_result, &result);
gcr_system_prompt_close (GCR_SYSTEM_PROMPT (prompt), NULL, &error);
g_assert_no_error (error);
+ g_assert (prompt_closed == TRUE);
egg_test_wait ();
password = gcr_prompt_password_finish (prompt, result, &error);
@@ -544,6 +558,89 @@ test_close_cancels (Test *test,
egg_assert_not_object (prompt);
}
+static void
+test_close_from_prompter (Test *test,
+ gconstpointer unused)
+{
+ GcrPrompt *prompt;
+ GError *error = NULL;
+ gboolean ret;
+ const gchar *password;
+ gboolean prompt_closed;
+
+ gcr_mock_prompter_expect_close ();
+
+ prompt = gcr_system_prompt_open_for_prompter (test->prompter_name, 1, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (GCR_IS_SYSTEM_PROMPT (prompt));
+
+ prompt_closed = FALSE;
+ g_signal_connect_after (prompt, "prompt-close", G_CALLBACK (on_prompt_close), &prompt_closed);
+
+ ret = gcr_prompt_confirm_run (prompt, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (ret == GCR_PROMPT_REPLY_CANCEL);
+
+ /* The prompt should be closed now, these shouldn't reach the mock prompter */
+
+ while (!prompt_closed)
+ g_main_context_iteration (NULL, TRUE);
+
+ ret = gcr_prompt_confirm_run (prompt, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (ret == GCR_PROMPT_REPLY_CANCEL);
+
+ password = gcr_prompt_password_run (prompt, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (password == NULL);
+
+ g_object_unref (prompt);
+ egg_assert_not_object (prompt);
+}
+
+static void
+test_after_close_dismisses (Test *test,
+ gconstpointer unused)
+{
+ GcrPrompt *prompt;
+ GError *error = NULL;
+ gboolean ret;
+ const gchar *password;
+ gboolean prompt_closed;
+
+ gcr_mock_prompter_expect_confirm_ok (NULL);
+
+ prompt = gcr_system_prompt_open_for_prompter (test->prompter_name, 1, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (GCR_IS_SYSTEM_PROMPT (prompt));
+
+ prompt_closed = FALSE;
+ g_signal_connect_after (prompt, "prompt-close", G_CALLBACK (on_prompt_close), &prompt_closed);
+
+
+ ret = gcr_prompt_confirm_run (prompt, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (ret == GCR_PROMPT_REPLY_CONTINUE);
+
+ gcr_prompt_close (prompt);
+ g_assert (prompt_closed);
+
+ /* These should never even reach the mock prompter */
+
+ ret = gcr_prompt_confirm_run (prompt, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (ret == GCR_PROMPT_REPLY_CANCEL);
+
+ password = gcr_prompt_password_run (prompt, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (password == NULL);
+
+ while (g_main_context_iteration (NULL, FALSE));
+
+ g_object_unref (prompt);
+ egg_assert_not_object (prompt);
+}
+
int
main (int argc, char **argv)
{
@@ -568,6 +665,8 @@ main (int argc, char **argv)
g_test_add ("/gcr/system-prompt/properties-reset", Test, NULL, setup, test_prompt_properties_reset, teardown);
g_test_add ("/gcr/system-prompt/close", Test, NULL, setup, test_prompt_close, teardown);
g_test_add ("/gcr/system-prompt/close-cancels", Test, NULL, setup, test_close_cancels, teardown);
+ g_test_add ("/gcr/system-prompt/after-close-dismisses", Test, NULL, setup, test_after_close_dismisses, teardown);
+ g_test_add ("/gcr/system-prompt/close-from-prompter", Test, NULL, setup, test_close_from_prompter, teardown);
return egg_tests_run_with_loop ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]