[geary/bug/788797-missing_text_caret: 4/5] Allow determining when JS has finished loading in ClientWebView.



commit f1e92feae28ec14cd74cd8d07aba7eaf0e1002e7
Author: Michael James Gratton <mike vee net>
Date:   Thu Nov 16 12:44:57 2017 +1100

    Allow determining when JS has finished loading in ClientWebView.
    
    * src/client/components/client-web-view.vala (ClientWebView): Add
      is_content_loaded property and content_loaded signal, update and fire
      when getting a contentLoaded message from the WebProcess.
    
    * ui/client-web-view.js: Fire the contentLoaded message when loading is
      complete. Add ClientPageStateTest test case to ensure it is working
      fine.
    
    * test/client/components/client-web-view-test-case.vala
      (ClientWebViewTestCase::load_body_fixture): Use is_content_loaded
      rather than is_loading as the test for loading having finished, since
      we're actually interested in when the JS has finished loaded, not the
      resources.

 src/client/components/client-web-view.vala         |   37 +++++++++++++-
 test/CMakeLists.txt                                |    1 +
 .../components/client-web-view-test-case.vala      |    2 +-
 test/js/client-page-state-test.vala                |   54 ++++++++++++++++++++
 test/main.vala                                     |    1 +
 ui/client-web-view.js                              |    1 +
 6 files changed, 93 insertions(+), 3 deletions(-)
---
diff --git a/src/client/components/client-web-view.vala b/src/client/components/client-web-view.vala
index d2a77f3..274cb3d 100644
--- a/src/client/components/client-web-view.vala
+++ b/src/client/components/client-web-view.vala
@@ -25,6 +25,8 @@ public class ClientWebView : WebKit.WebView {
 
     /** URI Scheme and delimiter for images loaded by Content-ID. */
     public const string CID_URL_PREFIX = "cid:";
+
+    private const string CONTENT_LOADED = "contentLoaded";
     private const string PREFERRED_HEIGHT_CHANGED = "preferredHeightChanged";
     private const string REMOTE_IMAGE_LOAD_BLOCKED = "remoteImageLoadBlocked";
     private const string SELECTION_CHANGED = "selectionChanged";
@@ -172,6 +174,22 @@ public class ClientWebView : WebKit.WebView {
     /** Delegate for UserContentManager message callbacks. */
     public delegate void JavaScriptMessageHandler(WebKit.JavascriptResult js_result);
 
+    /**
+     * Determines if the view's content has been fully loaded.
+     *
+     * This property is updated immediately before the {@link
+     * content_loaded} signal is fired, and is triggered by the
+     * PageState JavaScript object completing its load
+     * handler. I.e. This will be true after the in-page JavaScript has
+     * finished making any modifications to the page content.
+     *
+     * This will likely be fired after WebKitGTK sets the `is-loading`
+     * property to `FALSE` and emits `load-changed` with
+     * `WebKitLoadEvent.LOAD_FINISHED`, since they are related to
+     * network resource loading, not page content.
+     */
+    public bool is_content_loaded { get; private set; default = false; }
+
     /** Determines if the view has any selected text */
     public bool has_selection { get; private set; default = false; }
 
@@ -217,6 +235,14 @@ public class ClientWebView : WebKit.WebView {
         new Gee.HashMap<string,Geary.Memory.Buffer>();
 
 
+    /**
+     * Emitted when the view's content has finished loaded.
+     *
+     * See {@link is_content_loaded} for detail about when this is
+     * emitted.
+     */
+    public signal void content_loaded();
+
     /** Emitted when the view's selection has changed. */
     public signal void selection_changed(bool has_selection);
 
@@ -266,6 +292,9 @@ public class ClientWebView : WebKit.WebView {
             });
 
         register_message_handler(
+            CONTENT_LOADED, on_content_loaded
+        );
+        register_message_handler(
             PREFERRED_HEIGHT_CHANGED, on_preferred_height_changed
         );
         register_message_handler(
@@ -273,7 +302,7 @@ public class ClientWebView : WebKit.WebView {
         );
         register_message_handler(
             SELECTION_CHANGED, on_selection_changed
-         );
+        );
 
         // Manage zoom level
         config.bind(Configuration.CONVERSATION_VIEWER_ZOOM_KEY, this, "zoom_level");
@@ -500,6 +529,11 @@ public class ClientWebView : WebKit.WebView {
         remote_image_load_blocked();
     }
 
+    private void on_content_loaded(WebKit.JavascriptResult result) {
+        this.is_content_loaded = true;
+        content_loaded();
+    }
+
     private void on_selection_changed(WebKit.JavascriptResult result) {
         try {
             bool has_selection = WebKitUtil.to_bool(result);
@@ -518,4 +552,3 @@ public class ClientWebView : WebKit.WebView {
 
 // XXX this needs to be moved into the libsoup bindings
 extern string soup_uri_decode(string part);
-
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 052990e..e962195 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -27,6 +27,7 @@ set(TEST_SRC
   client/components/client-web-view-test-case.vala
   client/composer/composer-web-view-test.vala
 
+  js/client-page-state-test.vala
   js/composer-page-state-test.vala
   js/conversation-page-state-test.vala
 )
diff --git a/test/client/components/client-web-view-test-case.vala 
b/test/client/components/client-web-view-test-case.vala
index 68b2b1c..2a26c22 100644
--- a/test/client/components/client-web-view-test-case.vala
+++ b/test/client/components/client-web-view-test-case.vala
@@ -38,7 +38,7 @@ public abstract class ClientWebViewTestCase<V> : Gee.TestCase {
     protected virtual void load_body_fixture(string html = "") {
         ClientWebView client_view = (ClientWebView) this.test_view;
         client_view.load_html(html);
-        while (client_view.is_loading) {
+        while (!client_view.is_content_loaded) {
             Gtk.main_iteration();
         }
     }
diff --git a/test/js/client-page-state-test.vala b/test/js/client-page-state-test.vala
new file mode 100644
index 0000000..57e02cc
--- /dev/null
+++ b/test/js/client-page-state-test.vala
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017 Michael Gratton <mike vee net>
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+class ClientPageStateTest : ClientWebViewTestCase<ClientWebView> {
+
+
+    public ClientPageStateTest() {
+        base("ClientPageStateTest");
+        add_test("content_loaded", content_loaded);
+
+        try {
+            ClientWebView.load_scripts();
+        } catch (Error err) {
+            assert_not_reached();
+        }
+
+    }
+
+    public void content_loaded() {
+        bool content_loaded_triggered = false;
+        this.test_view.content_loaded.connect(() => {
+                content_loaded_triggered = true;
+            });
+
+        assert(!this.test_view.is_content_loaded);
+
+        // XXX sketchy - this call will never return if the thing we
+        // are testing does not work
+        load_body_fixture("OHHAI");
+
+        assert(this.test_view.is_content_loaded);
+        assert(content_loaded_triggered);
+    }
+
+    protected override ClientWebView set_up_test_view() {
+        WebKit.UserScript test_script;
+        test_script = new WebKit.UserScript(
+            "var geary = new PageState()",
+            WebKit.UserContentInjectedFrames.TOP_FRAME,
+            WebKit.UserScriptInjectionTime.START,
+            null,
+            null
+        );
+
+        ClientWebView view = new ClientWebView(this.config);
+        view.get_user_content_manager().add_script(test_script);
+        return view;
+    }
+
+}
diff --git a/test/main.vala b/test/main.vala
index 8fa3552..c03db0d 100644
--- a/test/main.vala
+++ b/test/main.vala
@@ -64,6 +64,7 @@ int main(string[] args) {
 
     TestSuite js = new TestSuite("js");
 
+    js.add_suite(new ClientPageStateTest().get_suite());
     js.add_suite(new ComposerPageStateTest().get_suite());
     js.add_suite(new ConversationPageStateTest().get_suite());
 
diff --git a/ui/client-web-view.js b/ui/client-web-view.js
index b9aa3d6..faab9ff 100644
--- a/ui/client-web-view.js
+++ b/ui/client-web-view.js
@@ -73,6 +73,7 @@ PageState.prototype = {
     },
     loaded: function() {
         this.isLoaded = true;
+        window.webkit.messageHandlers.contentLoaded.postMessage(null);
     },
     loadRemoteImages: function() {
         this.allowRemoteImages = true;


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