From b5754ac85db00de0183dbd13004917d5eb9c06a6 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Thu, 21 Mar 2013 14:00:18 +0100 Subject: Make ephy_web_view_has_modified_forms() asynchronous https://bugzilla.gnome.org/show_bug.cgi?id=695642 --- embed/ephy-web-view.c | 73 +++++++++++++------ embed/ephy-web-view.h | 8 ++- src/ephy-window.c | 192 +++++++++++++++++++++++++++++++++++++------------- 3 files changed, 203 insertions(+), 70 deletions(-) diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c index f39546b9d..57ceab62f 100644 --- a/embed/ephy-web-view.c +++ b/embed/ephy-web-view.c @@ -2545,6 +2545,26 @@ ephy_web_view_set_typed_address (EphyWebView *view, g_object_notify (G_OBJECT (view), "typed-address"); } +#ifdef HAVE_WEBKIT2 +static void +has_modified_forms_cb (GDBusProxy *web_extension, + GAsyncResult *result, + GTask *task) +{ + GVariant *return_value; + gboolean retval = FALSE; + + return_value = g_dbus_proxy_call_finish (web_extension, result, NULL); + if (return_value) { + g_variant_get (return_value, "(b)", &retval); + g_variant_unref (return_value); + } + + g_task_return_boolean (task, retval); + g_object_unref (task); +} +#endif + /** * ephy_web_view_has_modified_forms: * @view: an #EphyWebView @@ -2559,33 +2579,46 @@ ephy_web_view_set_typed_address (EphyWebView *view, * * Return value: %TRUE if @view has user-modified forms **/ -gboolean -ephy_web_view_has_modified_forms (EphyWebView *view) +void +ephy_web_view_has_modified_forms (EphyWebView *view, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { - return FALSE; -#if 0 + GTask *task = g_task_new (view, cancellable, callback, user_data); +#ifdef HAVE_WEBKIT2 GDBusProxy *web_extension; - GVariant *result; - gboolean retval = FALSE; - /* FIXME: This should be async */ web_extension = ephy_embed_shell_get_web_extension_proxy (ephy_embed_shell_get_default ()); - if (!web_extension) - return FALSE; - result = g_dbus_proxy_call_sync (web_extension, - "HasModifiedForms", - g_variant_new ("(t)", webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view))), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL); + if (web_extension) { + g_dbus_proxy_call (web_extension, + "HasModifiedForms", + g_variant_new ("(t)", webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view))), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + (GAsyncReadyCallback)has_modified_forms_cb, + g_object_ref (task)); + } else { + g_task_return_boolean (task, FALSE); + } +#else + WebKitDOMDocument *document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); + + g_task_return_boolean (task, ephy_web_dom_utils_has_modified_forms (document)); +#endif + g_object_unref (task); +} - g_variant_get (result, "(b)", &retval); - g_variant_unref (result); +gboolean +ephy_web_view_has_modified_forms_finish (EphyWebView *view, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, view), FALSE); - return retval; -#endif + return g_task_propagate_boolean (G_TASK (result), error); } /** diff --git a/embed/ephy-web-view.h b/embed/ephy-web-view.h index a24f96269..2e0b0672c 100644 --- a/embed/ephy-web-view.h +++ b/embed/ephy-web-view.h @@ -144,7 +144,13 @@ const char * ephy_web_view_get_typed_address (EphyWebView void ephy_web_view_set_typed_address (EphyWebView *view, const char *address); gboolean ephy_web_view_get_is_blank (EphyWebView *view); -gboolean ephy_web_view_has_modified_forms (EphyWebView *view); +void ephy_web_view_has_modified_forms (EphyWebView *view, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean ephy_web_view_has_modified_forms_finish (EphyWebView *view, + GAsyncResult *result, + GError **error); void ephy_web_view_get_security_level (EphyWebView *view, EphyWebViewSecurityLevel *level, GTlsCertificate **certificate, diff --git a/src/ephy-window.c b/src/ephy-window.c index 643d8e4e3..62a874108 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -386,6 +386,8 @@ struct _EphyWindowPrivate guint key_theme_is_emacs : 1; guint updating_address : 1; guint show_lock : 1; + guint force_close : 1; + guint checking_modified_forms : 1; }; enum @@ -469,25 +471,19 @@ construct_confirm_close_dialog (EphyWindow *window, static gboolean confirm_close_with_modified_forms (EphyWindow *window) { - if (g_settings_get_boolean (EPHY_SETTINGS_MAIN, - EPHY_PREFS_WARN_ON_CLOSE_UNSUBMITTED_DATA)) - { - GtkWidget *dialog; - int response; + GtkWidget *dialog; + int response; - dialog = construct_confirm_close_dialog (window, - _("There are unsubmitted changes to form elements"), - _("If you close the document anyway, " - "you will lose that information."), - _("Close _Document")); - response = gtk_dialog_run (GTK_DIALOG (dialog)); + dialog = construct_confirm_close_dialog (window, + _("There are unsubmitted changes to form elements"), + _("If you close the document anyway, " + "you will lose that information."), + _("Close _Document")); + response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); + gtk_widget_destroy (dialog); - return response == GTK_RESPONSE_ACCEPT; - } - - return TRUE; + return response == GTK_RESPONSE_ACCEPT; } static gboolean @@ -3186,6 +3182,33 @@ notebook_page_removed_cb (EphyNotebook *notebook, tab_accels_update (window); } +static void +ephy_window_close_tab (EphyWindow *window, + EphyEmbed *tab) +{ + gtk_widget_destroy (GTK_WIDGET (tab)); + + /* If that was the last tab, destroy the window. */ + if (gtk_notebook_get_n_pages (window->priv->notebook) == 0) + { + gtk_widget_destroy (GTK_WIDGET (window)); + } +} + +static void +tab_has_modified_forms_cb (EphyWebView *view, + GAsyncResult *result, + EphyWindow *window) +{ + gboolean has_modified_forms; + + has_modified_forms = ephy_web_view_has_modified_forms_finish (view, result, NULL); + if (!has_modified_forms || confirm_close_with_modified_forms (window)) + { + ephy_window_close_tab (window, EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (view)); + } +} + static void notebook_page_close_request_cb (EphyNotebook *notebook, EphyEmbed *embed, @@ -3207,18 +3230,18 @@ notebook_page_close_request_cb (EphyNotebook *notebook, } } - if ((!ephy_web_view_has_modified_forms (ephy_embed_get_web_view (embed)) || - confirm_close_with_modified_forms (window))) + if (g_settings_get_boolean (EPHY_SETTINGS_MAIN, + EPHY_PREFS_WARN_ON_CLOSE_UNSUBMITTED_DATA)) { - gtk_widget_destroy (GTK_WIDGET (embed)); + ephy_web_view_has_modified_forms (ephy_embed_get_web_view (embed), + NULL, + (GAsyncReadyCallback)tab_has_modified_forms_cb, + window); } - - /* If that was the last tab, destroy the window. */ - if (gtk_notebook_get_n_pages (priv->notebook) == 0) + else { - gtk_widget_destroy (GTK_WIDGET (window)); + ephy_window_close_tab (window, embed); } - } static GtkWidget * @@ -4401,6 +4424,94 @@ ephy_window_is_on_current_workspace (EphyWindow *window) return wnck_window_is_on_workspace (wnck_window, workspace); } +typedef struct { + EphyWindow *window; + GCancellable *cancellable; + + guint embeds_to_check; + EphyEmbed *modified_embed; +} ModifiedFormsData; + +static void +modified_forms_data_free (ModifiedFormsData *data) +{ + g_object_unref (data->cancellable); + + g_slice_free (ModifiedFormsData, data); +} + +static void +continue_window_close_after_modified_forms_check (ModifiedFormsData *data) +{ + gboolean should_close; + + data->window->priv->checking_modified_forms = FALSE; + + if (data->modified_embed) + { + /* jump to the first tab with modified forms */ + impl_set_active_child (EPHY_EMBED_CONTAINER (data->window), + data->modified_embed); + if (!confirm_close_with_modified_forms (data->window)) + return; + } + + data->window->priv->force_close = TRUE; + should_close = ephy_window_close (data->window); + data->window->priv->force_close = FALSE; + if (should_close) + gtk_widget_destroy (GTK_WIDGET (data->window)); +} + +static void +has_modified_forms_cb (EphyWebView *view, + GAsyncResult *result, + ModifiedFormsData *data) +{ + gboolean has_modified_forms; + + data->embeds_to_check--; + has_modified_forms = ephy_web_view_has_modified_forms_finish (view, result, NULL); + if (has_modified_forms) + { + /* Cancel all others */ + g_cancellable_cancel (data->cancellable); + data->modified_embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (view); + } + + if (data->embeds_to_check > 0) + return; + + continue_window_close_after_modified_forms_check (data); + modified_forms_data_free (data); +} + +static void +ephy_window_check_modified_forms (EphyWindow *window) +{ + GList *tabs, *l; + ModifiedFormsData *data; + + window->priv->checking_modified_forms = TRUE; + + data = g_slice_new0 (ModifiedFormsData); + data->window = window; + data->cancellable = g_cancellable_new (); + data->embeds_to_check = gtk_notebook_get_n_pages (window->priv->notebook); + + tabs = impl_get_children (EPHY_EMBED_CONTAINER (window)); + for (l = tabs; l != NULL; l = l->next) + { + EphyEmbed *embed = (EphyEmbed *) l->data; + + ephy_web_view_has_modified_forms (ephy_embed_get_web_view (embed), + data->cancellable, + (GAsyncReadyCallback)has_modified_forms_cb, + data); + } + g_list_free (tabs); +} + /** * ephy_window_close: * @window: an #EphyWindow @@ -4414,45 +4525,28 @@ ephy_window_is_on_current_workspace (EphyWindow *window) gboolean ephy_window_close (EphyWindow *window) { - EphyEmbed *modified_embed = NULL; - GList *tabs, *l; - gboolean modified = FALSE; - /* We ignore the delete_event if the disable_quit lockdown has been set */ if (g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN, EPHY_PREFS_LOCKDOWN_QUIT)) return FALSE; - tabs = impl_get_children (EPHY_EMBED_CONTAINER (window)); - for (l = tabs; l != NULL; l = l->next) - { - EphyEmbed *embed = (EphyEmbed *) l->data; - - g_return_val_if_fail (EPHY_IS_EMBED (embed), FALSE); - - if (ephy_web_view_has_modified_forms (ephy_embed_get_web_view (embed))) - { - modified = TRUE; - modified_embed = embed; - break; - } + if (window->priv->checking_modified_forms) { + /* stop window close */ + return FALSE; } - g_list_free (tabs); - if (modified) + if (g_settings_get_boolean (EPHY_SETTINGS_MAIN, + EPHY_PREFS_WARN_ON_CLOSE_UNSUBMITTED_DATA)) { - /* jump to the first tab with modified forms */ - impl_set_active_child (EPHY_EMBED_CONTAINER (window), - modified_embed); - - if (confirm_close_with_modified_forms (window) == FALSE) + if (!window->priv->force_close && + gtk_notebook_get_n_pages (window->priv->notebook) > 0) { + ephy_window_check_modified_forms (window); /* stop window close */ return FALSE; } } - if (window_has_ongoing_downloads (window) && confirm_close_with_downloads (window) == FALSE) { /* stop window close */ -- cgit v1.2.3