Bug 1261842 - Make Marionette listener ensure that the loaded document is the one that was actually requested. r?ato draft
authorMike Conley <mconley@mozilla.com>
Fri, 27 May 2016 16:26:16 -0400
changeset 392013 d12b17a53e8bb2c6664ba1cab79d92b905bbbf6e
parent 392012 2be7c7e47dbc556c247974e82fc17d44a0bc9b1b
child 392014 1198e282cd285fa88620c45c8bd1f335f6cfd742
push id23919
push usermconley@mozilla.com
push dateFri, 22 Jul 2016 20:54:03 +0000
reviewersato
bugs1261842
milestone50.0a1
Bug 1261842 - Make Marionette listener ensure that the loaded document is the one that was actually requested. r?ato Before, it was assumed that the next load was the one that the Marionette client had asked for, when this might not be the case. For example, when a new window opens, it's possible for the initial about:blank load to be fired in content after the parent has asked for a page to be loaded. MozReview-Commit-ID: GPoJgbCvSju
testing/marionette/listener.js
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -25,16 +25,18 @@ Cu.import("chrome://marionette/content/i
 Cu.import("chrome://marionette/content/logging.js");
 Cu.import("chrome://marionette/content/proxy.js");
 Cu.import("chrome://marionette/content/simpletest.js");
 
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+Cu.importGlobalProperties(["URL"]);
+
 var contentLog = new logging.ContentLogger();
 
 var isB2G = false;
 
 var marionetteTestName;
 var winUtil = content.QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIDOMWindowUtils);
 var listenerId = null; // unique ID of this listener
@@ -922,44 +924,50 @@ function pollForReadyState(msg, start, c
 /**
  * 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();
+  let requestedURL = new URL(msg.json.url).toString();
 
   // 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 correctFrame =
+      !event.originalTarget.defaultView.frameElement ||
+      event.originalTarget.defaultView.frameElement == curContainer.frame.frameElement;
+
+    let correctURL = curContainer.frame.location == requestedURL;
+
+    if (correctFrame && correctURL) {
       pollForReadyState(msg, start, () => {
         removeEventListener("DOMContentLoaded", onDOMContentLoaded, 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);
   }
   addEventListener("DOMContentLoaded", onDOMContentLoaded, false);
   if (isB2G) {
-    curContainer.frame.location = msg.json.url;
+    curContainer.frame.location = requestedURL;
   } else {
     // We need to move to the top frame before navigating
     sendSyncMessage("Marionette:switchedToFrame", { frameValue: null });
     curContainer.frame = content;
-    curContainer.frame.location = msg.json.url;
+    curContainer.frame.location = requestedURL;
   }
 }
 
  /**
  * 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.
  */