[epiphany] Make ephy_web_view_has_modified_forms() asynchronous



commit b5754ac85db00de0183dbd13004917d5eb9c06a6
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Thu Mar 21 14:00:18 2013 +0100

    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 f39546b..57ceab6 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 a24f962..2e0b067 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 643d8e4..62a8741 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
@@ -3187,6 +3183,33 @@ notebook_page_removed_cb (EphyNotebook *notebook,
 }
 
 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,
                                EphyWindow *window)
@@ -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 */


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