--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -869,98 +869,104 @@ function multiAction(args, maxLen) {
// now concurrent event is made of sets where each set contain a list of actions that need to be fired.
// note: each action belongs to a different finger
// pendingTouches keeps track of current touches that's on the screen
let pendingTouches = [];
setDispatch(concurrentEvent, pendingTouches);
}
-/*
- * This implements the latter part of a get request (for the case we need to resume one
- * when a remoteness update happens in the middle of a navigate request). This is most of
- * of the work of a navigate request, but doesn't assume DOMContentLoaded is yet to fire.
+/**
+ * This implements the latter part of a get request (for the case we
+ * need to resume one when a remoteness update happens in the middle of a
+ * navigate request). This is most of of the work of a navigate request,
+ * but doesn't assume DOMContentLoaded is yet to fire.
*/
-function pollForReadyState(msg, start, callback) {
+function pollForReadyState(msg, start = undefined, callback = undefined) {
let {pageTimeout, url, command_id} = msg.json;
- start = start ? start : new Date().getTime();
-
+ if (!start) {
+ start = new Date().getTime();
+ }
if (!callback) {
callback = () => {};
}
- let end = null;
- function checkLoad() {
+ let checkLoad = function() {
navTimer.cancel();
- end = new Date().getTime();
- let aboutErrorRegex = /about:.+(error)\?/;
- let elapse = end - start;
+
let doc = curContainer.frame.document;
- if (pageTimeout == null || elapse <= pageTimeout) {
+ let now = new Date().getTime();
+ if (pageTimeout == null || (now - start) <= pageTimeout) {
+ // document fully loaded
if (doc.readyState == "complete") {
callback();
sendOk(command_id);
+
+ // we have reached an error url without requesting it
} else if (doc.readyState == "interactive" &&
- aboutErrorRegex.exec(doc.baseURI) &&
- !doc.baseURI.startsWith(url)) {
- // We have reached an error url without requesting it.
+ /about:.+(error)\?/.exec(doc.baseURI) &&
+ !doc.baseURI.startsWith(url)) {
callback();
sendError(new UnknownError("Error loading page"), command_id);
- } else if (doc.readyState == "interactive" &&
- doc.baseURI.startsWith("about:")) {
+
+ // return early for about: urls
+ } else if (doc.readyState == "interactive" && doc.baseURI.startsWith("about:")) {
callback();
sendOk(command_id);
+
+ // document not fully loaded
} else {
navTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT);
}
+
} else {
callback();
sendError(new TimeoutError("Error loading page, timed out (checkLoad)"), command_id);
}
- }
+ };
checkLoad();
}
/**
* Navigate to the given URL. The operation will be performed on the
* current browsing context, which means it handles the case where we
* navigate within an iframe. All other navigation is handled by the
* driver (in chrome space).
*/
function get(msg) {
let start = new Date().getTime();
// Prevent DOMContentLoaded events from frames from invoking this
// code, unless the event is coming from the frame associated with
// the current window (i.e. someone has used switch_to_frame).
- onDOMContentLoaded = function onDOMContentLoaded(event) {
- if (!event.originalTarget.defaultView.frameElement ||
- event.originalTarget.defaultView.frameElement == curContainer.frame.frameElement) {
+ let onLoad = function(event) {
+ let frameEl = event.originalTarget.defaultView.frameElement;
+ if (!frameEl || frameEl == curContainer.frame.frameElement) {
pollForReadyState(msg, start, () => {
- removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
+ removeEventListener("DOMContentLoaded", onLoad, false);
});
}
};
- function timerFunc() {
- removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
- sendError(new TimeoutError("Error loading page, timed out (onDOMContentLoaded)"), msg.json.command_id);
- }
- if (msg.json.pageTimeout != null) {
- navTimer.initWithCallback(timerFunc, msg.json.pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
+ if (msg.json.pageTimeout) {
+ let onTimeout = function() {
+ removeEventListener("DOMContentLoaded", loadEv, false);
+ sendError(new TimeoutError("Error loading page, timed out (onDOMContentLoaded)"), msg.json.command_id);
+ };
+ navTimer.initWithCallback(onTimeout, msg.json.pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
}
- addEventListener("DOMContentLoaded", onDOMContentLoaded, false);
- if (isB2G) {
- curContainer.frame.location = msg.json.url;
- } else {
- // We need to move to the top frame before navigating
- sendSyncMessage("Marionette:switchedToFrame", { frameValue: null });
+
+ addEventListener("DOMContentLoaded", onLoad, false);
+
+ // in Firefox we need to move to the top frame before navigating
+ if (!isB2G) {
+ sendSyncMessage("Marionette:switchedToFrame", {frameValue: null});
curContainer.frame = content;
- curContainer.frame.location = msg.json.url;
}
+ curContainer.frame.location = msg.json.url;
}
/**
* Cancel the polling and remove the event listener associated with a current
* navigation request in case we're interupted by an onbeforeunload handler
* and navigation doesn't complete.
*/
function cancelRequest() {
@@ -1300,17 +1306,17 @@ function switchToShadowRoot(id) {
let command_id = msg.json.command_id;
curContainer.frame = curContainer.frame.parent;
let parentElement = seenEls.add(curContainer.frame);
sendSyncMessage(
"Marionette:switchedToFrame", {frameValue: parentElement});
sendOk(msg.json.command_id);
- }
+}
/**
* Switch to frame given either the server-assigned element id,
* its index in window.frames, or the iframe's name or id.
*/
function switchToFrame(msg) {
let command_id = msg.json.command_id;
function checkLoad() {