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.
This commit is contained in:
parent
7ad97fb5d9
commit
f1e92feae2
6 changed files with 93 additions and 3 deletions
|
|
@ -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);
|
||||
|
||||
|
|
@ -265,6 +291,9 @@ public class ClientWebView : WebKit.WebView {
|
|||
return Gdk.EVENT_PROPAGATE;
|
||||
});
|
||||
|
||||
register_message_handler(
|
||||
CONTENT_LOADED, on_content_loaded
|
||||
);
|
||||
register_message_handler(
|
||||
PREFERRED_HEIGHT_CHANGED, on_preferred_height_changed
|
||||
);
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
54
test/js/client-page-state-test.vala
Normal file
54
test/js/client-page-state-test.vala
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ PageState.prototype = {
|
|||
},
|
||||
loaded: function() {
|
||||
this.isLoaded = true;
|
||||
window.webkit.messageHandlers.contentLoaded.postMessage(null);
|
||||
},
|
||||
loadRemoteImages: function() {
|
||||
this.allowRemoteImages = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue