Bug 1095260 - Make the response from a switchToWindow call correspond to the completion of loading the marionette listener script.;r=automatedtester
authorChris Manchester <cmanchester@mozilla.com>
Fri, 21 Nov 2014 13:58:00 -0500
changeset 216953 28ed24c69091982439bd31b3c7cbbee176ad165d
parent 216947 5b2f62c1faf9146e0d2673030fc9fb2b076f917c
child 216954 e00f07b0609e76f919f20b04303171f59e8dd893
push id27871
push usercbook@mozilla.com
push dateMon, 24 Nov 2014 12:32:57 +0000
treeherdermozilla-central@b8e1741b7d5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersautomatedtester
bugs1095260
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1095260 - Make the response from a switchToWindow call correspond to the completion of loading the marionette listener script.;r=automatedtester
testing/marionette/client/marionette/www/test_windows.html
testing/marionette/marionette-server.js
--- a/testing/marionette/client/marionette/www/test_windows.html
+++ b/testing/marionette/client/marionette/www/test_windows.html
@@ -3,12 +3,12 @@
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
     <title>XHTML Test Page</title>
 </head>
 <body>
-    <p><a href="resultPage.html" onClick='javascript:window.open("resultPage.html",null, "menubar=0,location=1,resizable=1,scrollbars=1,status=0,dialog=1,width=700,height=375");' name="windowOne">Open new window</a></p>
+    <p><a href="resultPage.html" onClick='javascript:window.open("resultPage.html",null, "menubar=0,location=1,resizable=1,scrollbars=1,status=0,width=700,height=375");' name="windowOne">Open new window</a></p>
 </body>
 </html>
 
--- a/testing/marionette/marionette-server.js
+++ b/testing/marionette/marionette-server.js
@@ -476,26 +476,42 @@ MarionetteServerConnection.prototype = {
    * Loads the Marionette frame script into the browser if needed.
    *
    * @param nsIDOMWindow win
    *        Window whose browser we need to access
    * @param boolean newSession
    *        True if this is the first time we're talking to this browser
    */
   whenBrowserStarted: function MDA_whenBrowserStarted(win, newSession) {
+    utils.window = win;
+
     try {
+      let mm = win.window.messageManager;
+      if (!newSession) {
+        // Loading the frame script corresponds to a situation we need to
+        // return to the server. If the messageManager is a message broadcaster
+        // with no children, we don't have a hope of coming back from this call,
+        // so send the ack here. Otherwise, make a note of how many child scripts
+        // will be loaded so we known when it's safe to return.
+        if (mm.childCount === 0) {
+          this.sendOk(this.command_id);
+        } else {
+          this.curBrowser.frameRegsPending = mm.childCount;
+        }
+      }
+
       if (!Services.prefs.getBoolPref("marionette.contentListener") || !newSession) {
-        this.curBrowser.loadFrameScript(FRAME_SCRIPT, win);
+        mm.loadFrameScript(FRAME_SCRIPT, true, true);
+        Services.prefs.setBoolPref("marionette.contentListener", true);
       }
     }
     catch (e) {
       //there may not always be a content process
       logger.info("could not load listener into content for page: " + win.location.href);
     }
-    utils.window = win;
   },
 
   /**
    * Recursively get all labeled text
    *
    * @param nsIDOMElement el
    *        The parent element
    * @param array lines
@@ -1400,18 +1416,18 @@ MarionetteServerConnection.prototype = {
       if (aRequest.parameters.name == foundWin.name || aRequest.parameters.name == winId) {
         if (this.browsers[winId] == undefined) {
           //enable Marionette in that browser window
           this.startBrowser(foundWin, false);
         }
         else {
           utils.window = foundWin;
           this.curBrowser = this.browsers[winId];
+          this.sendOk(command_id);
         }
-        this.sendOk(command_id);
         return;
       }
     }
     this.sendError("Unable to locate window " + aRequest.parameters.name, 23, null,
                    command_id);
   },
 
   getActiveFrame: function MDA_getActiveFrame() {
@@ -2782,16 +2798,26 @@ MarionetteServerConnection.prototype = {
                               this.newSessionCommandId)) {
             return;
           }
           if (this.curBrowser.newSession) {
             this.getSessionCapabilities();
             this.newSessionCommandId = null;
           }
         }
+        if (this.curBrowser.frameRegsPending) {
+          if (this.curBrowser.frameRegsPending > 0) {
+            this.curBrowser.frameRegsPending -= 1;
+          }
+          if (this.curBrowser.frameRegsPending === 0) {
+            // In case of a freshly registered window, we're responsible here
+            // for sending the ack.
+            this.sendOk(this.command_id);
+          }
+        }
         return [reg, mainContent];
       case "Marionette:emitTouchEvent":
         let globalMessageManager = Cc["@mozilla.org/globalmessagemanager;1"]
                              .getService(Ci.nsIMessageBroadcaster);
         globalMessageManager.broadcastAsyncMessage(
           "MarionetteMainListener:emitTouchEvent", message.json);
         return;
     }
@@ -2961,29 +2987,16 @@ BrowserObj.prototype = {
    * @param string uri
    *      URI to open
    */
   addTab: function BO_addTab(uri) {
     return this.browser.addTab(uri, true);
   },
 
   /**
-   * Loads content listeners if we don't already have them
-   *
-   * @param string script
-   *        path of script to load
-   * @param nsIDOMWindow frame
-   *        frame to load the script in
-   */
-  loadFrameScript: function BO_loadFrameScript(script, frame) {
-    frame.window.messageManager.loadFrameScript(script, true, true);
-    Services.prefs.setBoolPref("marionette.contentListener", true);
-  },
-
-  /**
    * Registers a new frame, and sets its current frame id to this frame
    * if it is not already assigned, and if a) we already have a session
    * or b) we're starting a new session and it is the right start frame.
    *
    * @param string uid
    *        frame uid for use by marionette
    * @param number id
    *        incoming window id assigned by gecko