Bug 941102 - Fix closeWindow not matching WebDriver command close. r=dburns
authorAndreas Tolfsen <ato@mozilla.com>
Fri, 17 Jan 2014 10:03:43 -0500
changeset 163958 586b1a34c3a16e5050034e5bec67d3ced6d7133f
parent 163957 a3cde257eb1b8f3c896126e8a88e82f96a3027ec
child 163959 d95b51c157ec1aeaa9c858514913716d346760a1
push id38593
push userryanvm@gmail.com
push dateFri, 17 Jan 2014 15:03:48 +0000
treeherdermozilla-inbound@3687b6b2e48d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdburns
bugs941102
milestone29.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 941102 - Fix closeWindow not matching WebDriver command close. r=dburns The closeWindow request type name has been left for backwards compatibility.
testing/marionette/client/marionette/marionette.py
testing/marionette/marionette-server.js
--- a/testing/marionette/client/marionette/marionette.py
+++ b/testing/marionette/client/marionette/marionette.py
@@ -789,25 +789,25 @@ class Marionette(object):
     @property
     def page_source(self):
         '''
         A string representation of the DOM.
         '''
         response = self._send_message('getPageSource', 'value')
         return response
 
-    def close(self, window_id=None):
-        '''
-        Closes the window that is in use by Marionette.
+    def close(self):
+        """Close the current window, ending the session if it's the last
+        window currently open.
 
-        :param window_id: id of the window you wish to closed
-        '''
-        if not window_id:
-            window_id = self.current_window_handle
-        response = self._send_message('closeWindow', 'ok', value=window_id)
+        On B2G this method is a noop and will return immediately.
+
+        """
+
+        response = self._send_message("close", "ok")
         return response
 
     def set_context(self, context):
         '''
         Sets the context that marionette commands are running in.
 
         :param context: Context, may be one of the class properties
          `CONTEXT_CHROME` or `CONTEXT_CONTENT`.
--- a/testing/marionette/marionette-server.js
+++ b/testing/marionette/marionette-server.js
@@ -25,17 +25,17 @@ loader.loadSubScript("chrome://marionett
 
 let specialpowers = {};
 loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js",
                      specialpowers);
 specialpowers.specialPowersObserver = new specialpowers.SpecialPowersObserver();
 specialpowers.specialPowersObserver.init();
 
 Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");  
+Cu.import("resource://gre/modules/NetUtil.jsm");
 
 Services.prefs.setBoolPref("marionette.contentListener", false);
 let appName = Services.appinfo.name;
 
 // dumpn needed/used by dbg-transport.js
 this.dumpn = function dumpn(str) {
   logger.trace(str);
 }
@@ -303,17 +303,17 @@ MarionetteServerConnection.prototype = {
   },
 
   getMarionetteID: function MDA_getMarionette() {
     this.conn.send({ "from": "root", "id": this.actorID });
   },
 
   /**
    * Send ack to client
-   * 
+   *
    * @param string command_id
    *        Unique identifier assigned to the client's request.
    *        Used to distinguish the asynchronous responses.
    */
   sendOk: function MDA_sendOk(command_id) {
     this.sendToClient({from:this.actorID, ok: true}, command_id);
   },
 
@@ -332,17 +332,17 @@ MarionetteServerConnection.prototype = {
    */
   sendError: function MDA_sendError(message, status, trace, command_id) {
     let error_msg = {message: message, status: status, stacktrace: trace};
     this.sendToClient({from:this.actorID, error: error_msg}, command_id);
   },
 
   /**
    * Gets the current active window
-   * 
+   *
    * @return nsIDOMWindow
    */
   getCurrentWindow: function MDA_getCurrentWindow() {
     let type = null;
     if (this.curFrame == null) {
       if (this.curBrowser == null) {
         if (this.context == "content") {
           type = 'navigator:browser';
@@ -368,17 +368,17 @@ MarionetteServerConnection.prototype = {
     if (appName != "B2G" && this.context == "content") {
       type = 'navigator:browser';
     }
     return Services.wm.getEnumerator(type);
   },
 
   /**
    * Create a new BrowserObj for window and add to known browsers
-   * 
+   *
    * @param nsIDOMWindow win
    *        Window for which we will create a BrowserObj
    *
    * @return string
    *        Returns the unique server-assigned ID of the window
    */
   addBrowser: function MDA_addBrowser(win) {
     let browser = new BrowserObj(win, this);
@@ -389,20 +389,20 @@ MarionetteServerConnection.prototype = {
     this.curBrowser = this.browsers[winId];
     if (this.curBrowser.elementManager.seenItems[winId] == undefined) {
       //add this to seenItems so we can guarantee the user will get winId as this window's id
       this.curBrowser.elementManager.seenItems[winId] = Cu.getWeakReference(win);
     }
   },
 
   /**
-   * Start a new session in a new browser. 
+   * Start a new session in a new browser.
    *
-   * If newSession is true, we will switch focus to the start frame 
-   * when it registers. Also, if it is in desktop, then a new tab 
+   * If newSession is true, we will switch focus to the start frame
+   * when it registers. Also, if it is in desktop, then a new tab
    * with the start page uri (about:blank) will be opened.
    *
    * @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
    */
   startBrowser: function MDA_startBrowser(win, newSession) {
@@ -486,32 +486,32 @@ MarionetteServerConnection.prototype = {
    * the case of execute_async calls that timeout and then later send a
    * response, and other situations.  See bug 779011. See setScriptTimeout()
    * for a basic example.
    */
 
   /**
    * Create a new session. This creates a BrowserObj.
    *
-   * In a desktop environment, this opens a new 'about:blank' tab for 
+   * In a desktop environment, this opens a new 'about:blank' tab for
    * the client to test in.
    *
    */
   newSession: function MDA_newSession() {
     this.command_id = this.getCommandId();
     this.newSessionCommandId = this.command_id;
 
     this.scriptTimeout = 10000;
 
     function waitForWindow() {
       let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
       let win = this.getCurrentWindow();
       if (!win ||
           (appName == "Firefox" && !win.gBrowser) ||
-          (appName == "Fennec" && !win.BrowserApp)) { 
+          (appName == "Fennec" && !win.BrowserApp)) {
         checkTimer.initWithCallback(waitForWindow.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
       }
       else {
         this.startBrowser(win, true);
       }
     }
 
 
@@ -694,17 +694,17 @@ MarionetteServerConnection.prototype = {
 
     if (directInject && async &&
         (timeout == null || timeout == 0)) {
       this.sendError("Please set a timeout", 21, null, command_id);
       return;
     }
 
     if (this.importedScripts.exists()) {
-      let stream = Cc["@mozilla.org/network/file-input-stream;1"].  
+      let stream = Cc["@mozilla.org/network/file-input-stream;1"].
                     createInstance(Ci.nsIFileInputStream);
       stream.init(this.importedScripts, -1, 0, 0);
       let data = NetUtil.readInputStreamToString(stream, stream.available());
       script = data + script;
     }
 
     let res = Cu.evalInSandbox(script, sandbox, "1.8", "dummy file", 0);
 
@@ -723,27 +723,27 @@ MarionetteServerConnection.prototype = {
   /**
    * Execute the given script either as a function body (executeScript)
    * or directly (for 'mochitest' like JS Marionette tests)
    *
    * @param object aRequest
    *        'script' member is the script to run
    *        'args' member holds the arguments to the script
    * @param boolean directInject
-   *        if true, it will be run directly and not as a 
+   *        if true, it will be run directly and not as a
    *        function body
    */
   execute: function MDA_execute(aRequest, directInject) {
     let inactivityTimeout = aRequest.parameters.inactivityTimeout;
     let timeout = aRequest.parameters.scriptTimeout ? aRequest.parameters.scriptTimeout : this.scriptTimeout;
     let command_id = this.command_id = this.getCommandId();
     let script;
     this.logRequest("execute", aRequest);
     if (aRequest.parameters.newSandbox == undefined) {
-      //if client does not send a value in newSandbox, 
+      //if client does not send a value in newSandbox,
       //then they expect the same behaviour as webdriver
       aRequest.parameters.newSandbox = true;
     }
     if (this.context == "content") {
       this.sendAsync("executeScript",
                      {
                        script: aRequest.parameters.script,
                        args: aRequest.parameters.args,
@@ -800,17 +800,17 @@ MarionetteServerConnection.prototype = {
         return marionette.generate_results();
       };
 
       if (directInject) {
         script = aRequest.parameters.script;
       }
       else {
         script = "let func = function() {" +
-                       aRequest.parameters.script + 
+                       aRequest.parameters.script +
                      "};" +
                      "func.apply(null, __marionetteParams);";
       }
       this.executeScriptInSandbox(_chromeSandbox, script, directInject,
                                   false, command_id, timeout);
     }
     catch (e) {
       let error = createStackMessage(e,
@@ -849,17 +849,17 @@ MarionetteServerConnection.prototype = {
    *        'timeout' member will be used as the script timeout if it is given
    */
   executeJSScript: function MDA_executeJSScript(aRequest) {
     let timeout = aRequest.parameters.scriptTimeout ? aRequest.parameters.scriptTimeout : this.scriptTimeout;
     let command_id = this.command_id = this.getCommandId();
 
     //all pure JS scripts will need to call Marionette.finish() to complete the test.
     if (aRequest.newSandbox == undefined) {
-      //if client does not send a value in newSandbox, 
+      //if client does not send a value in newSandbox,
       //then they expect the same behaviour as webdriver
       aRequest.newSandbox = true;
     }
     if (this.context == "chrome") {
       if (aRequest.parameters.async) {
         this.executeWithCallback(aRequest, aRequest.parameters.async);
       }
       else {
@@ -880,37 +880,37 @@ MarionetteServerConnection.prototype = {
                        line: aRequest.parameters.line,
                      },
                      command_id);
    }
   },
 
   /**
    * This function is used by executeAsync and executeJSScript to execute a script
-   * in a sandbox. 
-   * 
+   * in a sandbox.
+   *
    * For executeJSScript, it will return a message only when the finish() method is called.
-   * For executeAsync, it will return a response when marionetteScriptFinished/arguments[arguments.length-1] 
+   * For executeAsync, it will return a response when marionetteScriptFinished/arguments[arguments.length-1]
    * method is called, or if it times out.
    *
    * @param object aRequest
    *        'script' member holds the script to execute
    *        'args' member holds the arguments for the script
    * @param boolean directInject
-   *        if true, it will be run directly and not as a 
+   *        if true, it will be run directly and not as a
    *        function body
    */
   executeWithCallback: function MDA_executeWithCallback(aRequest, directInject) {
     let inactivityTimeout = aRequest.parameters.inactivityTimeout;
     let timeout = aRequest.parameters.scriptTimeout ? aRequest.parameters.scriptTimeout : this.scriptTimeout;
     let command_id = this.command_id = this.getCommandId();
     let script;
     this.logRequest("executeWithCallback", aRequest);
     if (aRequest.parameters.newSandbox == undefined) {
-      //if client does not send a value in newSandbox, 
+      //if client does not send a value in newSandbox,
       //then they expect the same behaviour as webdriver
       aRequest.parameters.newSandbox = true;
     }
 
     if (this.context == "content") {
       this.sendAsync("executeAsyncScript",
                      {
                        script: aRequest.parameters.script,
@@ -1061,17 +1061,17 @@ MarionetteServerConnection.prototype = {
     function checkLoad() {
       end = new Date().getTime();
       let elapse = end - start;
       if (this.pageTimeout == null || elapse <= this.pageTimeout){
         if (curWindow.document.readyState == "complete") {
           sendOk(command_id);
           return;
         }
-        else{ 
+        else{
           checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT);
         }
       }
       else{
         sendError("Error loading page", 13, null, command_id);
         return;
       }
     }//end
@@ -1118,17 +1118,17 @@ MarionetteServerConnection.prototype = {
 
   /**
    * Gets the page source of the content document
    */
   getPageSource: function MDA_getPageSource(){
     this.command_id = this.getCommandId();
     if (this.context == "chrome"){
       let curWindow = this.getCurrentWindow();
-      let XMLSerializer = curWindow.XMLSerializer; 
+      let XMLSerializer = curWindow.XMLSerializer;
       let pageSource = new XMLSerializer().serializeToString(curWindow.document);
       this.sendResponse(pageSource, this.command_id);
     }
     else {
       this.sendAsync("getPageSource", {}, this.command_id);
     }
   },
 
@@ -1169,17 +1169,17 @@ MarionetteServerConnection.prototype = {
   },
 
   /**
    * Get the server-assigned IDs of all available windows
    */
   getWindows: function MDA_getWindows() {
     this.command_id = this.getCommandId();
     let res = [];
-    let winEn = this.getWinEnumerator(); 
+    let winEn = this.getWinEnumerator();
     while(winEn.hasMoreElements()) {
       let foundWin = winEn.getNext();
       let winId = foundWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
       winId = winId + ((appName == "B2G") ? '-b2g' : '');
       res.push(winId)
     }
     this.sendResponse(res, this.command_id);
   },
@@ -1188,17 +1188,17 @@ MarionetteServerConnection.prototype = {
    * Switch to a window based on name or server-assigned id.
    * Searches based on name, then id.
    *
    * @param object aRequest
    *        'name' member holds the name or id of the window to switch to
    */
   switchToWindow: function MDA_switchToWindow(aRequest) {
     let command_id = this.command_id = this.getCommandId();
-    let winEn = this.getWinEnumerator(); 
+    let winEn = this.getWinEnumerator();
     while(winEn.hasMoreElements()) {
       let foundWin = winEn.getNext();
       let winId = foundWin.QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIDOMWindowUtils)
                           .outerWindowID;
       winId = winId + ((appName == "B2G") ? '-b2g' : '');
       if (aRequest.parameters.name == foundWin.name || aRequest.parameters.name == winId) {
         if (this.browsers[winId] == undefined) {
@@ -1235,17 +1235,17 @@ MarionetteServerConnection.prototype = {
   },
 
   /**
    * Switch to a given frame within the current window
    *
    * @param object aRequest
    *        'element' is the element to switch to
    *        'id' if element is not set, then this
-   *                holds either the id, name or index 
+   *                holds either the id, name or index
    *                of the frame to switch to
    */
   switchToFrame: function MDA_switchToFrame(aRequest) {
     let command_id = this.command_id = this.getCommandId();
     this.logRequest("switchToFrame", aRequest);
     let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     let curWindow = this.getCurrentWindow();
     let checkLoad = function() {
@@ -1272,17 +1272,17 @@ MarionetteServerConnection.prototype = {
         return;
       }
       if (aRequest.parameters.element != undefined) {
         if (this.curBrowser.elementManager.seenItems[aRequest.parameters.element] != undefined) {
           let wantedFrame = this.curBrowser.elementManager.getKnownElement(aRequest.parameters.element, curWindow); //HTMLIFrameElement
           let numFrames = curWindow.frames.length;
           for (let i = 0; i < numFrames; i++) {
             if (curWindow.frames[i].frameElement == wantedFrame) {
-              curWindow = curWindow.frames[i]; 
+              curWindow = curWindow.frames[i];
               this.curFrame = curWindow;
               if (aRequest.parameters.focus) {
                 this.curFrame.focus();
               }
               checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
               return;
           }
         }
@@ -1614,17 +1614,17 @@ MarionetteServerConnection.prototype = {
     }
   },
 
   /**
    * Get the text of an element, if any. Includes the text of all child elements.
    *
    * @param object aRequest
    *        'id' member holds the reference id to
-   *        the element that will be inspected 
+   *        the element that will be inspected
    */
   getElementText: function MDA_getElementText(aRequest) {
     let command_id = this.command_id = this.getCommandId();
     if (this.context == "chrome") {
       //Note: for chrome, we look at text nodes, and any node with a "label" field
       try {
         let el = this.curBrowser.elementManager.getKnownElement(
             aRequest.parameters.id, this.getCurrentWindow());
@@ -1644,17 +1644,17 @@ MarionetteServerConnection.prototype = {
     }
   },
 
   /**
    * Get the tag name of the element.
    *
    * @param object aRequest
    *        'id' member holds the reference id to
-   *        the element that will be inspected 
+   *        the element that will be inspected
    */
   getElementTagName: function MDA_getElementTagName(aRequest) {
     let command_id = this.command_id = this.getCommandId();
     if (this.context == "chrome") {
       try {
         let el = this.curBrowser.elementManager.getKnownElement(
             aRequest.parameters.id, this.getCurrentWindow());
         this.sendResponse(el.tagName.toLowerCase(), command_id);
@@ -1670,17 +1670,17 @@ MarionetteServerConnection.prototype = {
     }
   },
 
   /**
    * Check if element is displayed
    *
    * @param object aRequest
    *        'id' member holds the reference id to
-   *        the element that will be checked 
+   *        the element that will be checked
    */
   isElementDisplayed: function MDA_isElementDisplayed(aRequest) {
     let command_id = this.command_id = this.getCommandId();
     if (this.context == "chrome") {
       try {
         let el = this.curBrowser.elementManager.getKnownElement(
             aRequest.parameters.id, this.getCurrentWindow());
         this.sendResponse(utils.isElementDisplayed(el), command_id);
@@ -1861,17 +1861,17 @@ MarionetteServerConnection.prototype = {
                    this.command_id);
   },
 
   /**
    * Clear the text of an element
    *
    * @param object aRequest
    *        'id' member holds the reference id to
-   *        the element that will be cleared 
+   *        the element that will be cleared
    */
   clearElement: function MDA_clearElement(aRequest) {
     let command_id = this.command_id = this.getCommandId();
     if (this.context == "chrome") {
       //the selenium atom doesn't work here
       try {
         let el = this.curBrowser.elementManager.getKnownElement(
             aRequest.parameters.id, this.getCurrentWindow());
@@ -1933,66 +1933,65 @@ MarionetteServerConnection.prototype = {
   deleteCookie: function MDA_deleteCookie(aRequest) {
     this.command_id = this.getCommandId();
     this.sendAsync("deleteCookie",
                    { name:aRequest.parameters.name },
                    this.command_id);
   },
 
   /**
-   * Closes the Browser Window.
-   *
-   * If it is B2G it returns straight away and does not do anything
+   * Close the current window, ending the session if it's the last
+   * window currently open.
    *
-   * If is desktop it calculates how many windows are open and if there is only 
-   * 1 then it deletes the session otherwise it closes the window
+   * On B2G this method is a noop and will return immediately.
    */
-  closeWindow: function MDA_closeWindow() {
+  close: function MDA_close() {
     let command_id = this.command_id = this.getCommandId();
     if (appName == "B2G") {
       // We can't close windows so just return
       this.sendOk(command_id);
     }
     else {
       // Get the total number of windows
       let numOpenWindows = 0;
       let winEnum = this.getWinEnumerator();
       while (winEnum.hasMoreElements()) {
         numOpenWindows += 1;
         winEnum.getNext();
       }
 
       // if there is only 1 window left, delete the session
-      if (numOpenWindows === 1){
+      if (numOpenWindows === 1) {
         try {
           this.sessionTearDown();
         }
         catch (e) {
-          this.sendError("Could not clear session", 500, e.name + ": " + e.message, command_id);
+          this.sendError("Could not clear session", 500,
+                         e.name + ": " + e.message, command_id);
           return;
         }
         this.sendOk(command_id);
         return;
       }
 
-      try{
-        this.messageManager.removeDelayedFrameScript(FRAME_SCRIPT); 
+      try {
+        this.messageManager.removeDelayedFrameScript(FRAME_SCRIPT);
         this.getCurrentWindow().close();
         this.sendOk(command_id);
       }
       catch (e) {
         this.sendError("Could not close window: " + e.message, 13, e.stack,
                        command_id);
       }
     }
-  }, 
+  },
 
   /**
    * Deletes the session.
-   * 
+   *
    * If it is a desktop environment, it will close the session's tab and close all listeners
    *
    * If it is a B2G environment, it will make the main content listener sleep, and close
    * all other listeners. The main content listener persists after disconnect (it's the homescreen),
    * and can safely be reused.
    */
   sessionTearDown: function MDA_sessionTearDown() {
     if (this.curBrowser != null) {
@@ -2010,17 +2009,17 @@ MarionetteServerConnection.prototype = {
       //delete session in each frame in each browser
       for (let win in this.browsers) {
         for (let i in this.browsers[win].knownFrames) {
           this.globalMessageManager.broadcastAsyncMessage("Marionette:deleteSession" + this.browsers[win].knownFrames[i], {});
         }
       }
       let winEnum = this.getWinEnumerator();
       while (winEnum.hasMoreElements()) {
-        winEnum.getNext().messageManager.removeDelayedFrameScript(FRAME_SCRIPT); 
+        winEnum.getNext().messageManager.removeDelayedFrameScript(FRAME_SCRIPT);
       }
       this.curBrowser.frameManager.removeMessageManagerListeners(this.globalMessageManager);
     }
     this.switchToGlobalMessageManager();
     // reset frame to the top-most frame
     this.curFrame = null;
     if (this.mainFrame) {
       this.mainFrame.focus();
@@ -2084,17 +2083,17 @@ MarionetteServerConnection.prototype = {
     try {
       cb(message.result);
     }
     catch(e) {
       this.sendError(e.message, e.code, e.stack, -1);
       return;
     }
   },
-  
+
   importScript: function MDA_importScript(aRequest) {
     let command_id = this.command_id = this.getCommandId();
     let converter =
       Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
           createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
     let result = {};
     let data = converter.convertToByteArray(aRequest.parameters.script, result);
@@ -2276,27 +2275,27 @@ MarionetteServerConnection.prototype = {
           }
           this.currentFrameElement = message.json.frameValue;
         }
         break;
       case "Marionette:register":
         // This code processes the content listener's registration information
         // and either accepts the listener, or ignores it
         let nullPrevious = (this.curBrowser.curFrameId == null);
-        let listenerWindow = 
+        let listenerWindow =
                             Services.wm.getOuterWindowWithId(message.json.value);
 
         //go in here if we're already in a remote frame.
         if ((!listenerWindow || listenerWindow.location.href != message.json.href) &&
             (this.curBrowser.frameManager.currentRemoteFrame !== null)) {
           // The outerWindowID from an OOP frame will not be meaningful to
           // the parent process here, since each process maintains its own
           // independent window list.  So, it will either be null (!listenerWindow)
           // if we're already in a remote frame,
-          // or it will point to some random window, which will hopefully 
+          // or it will point to some random window, which will hopefully
           // cause an href mismatch.  Currently this only happens
           // in B2G for OOP frames registered in Marionette:switchToFrame, so
           // we'll acknowledge the switchToFrame message here.
           // XXX: Should have a better way of determining that this message
           // is from a remote frame.
           this.curBrowser.frameManager.currentRemoteFrame.targetFrameId = this.generateFrameId(message.json.value);
           this.sendOk(this.command_id);
         }
@@ -2376,17 +2375,18 @@ MarionetteServerConnection.prototype.req
   "getActiveFrame": MarionetteServerConnection.prototype.getActiveFrame,
   "switchToFrame": MarionetteServerConnection.prototype.switchToFrame,
   "switchToWindow": MarionetteServerConnection.prototype.switchToWindow,
   "deleteSession": MarionetteServerConnection.prototype.deleteSession,
   "emulatorCmdResult": MarionetteServerConnection.prototype.emulatorCmdResult,
   "importScript": MarionetteServerConnection.prototype.importScript,
   "clearImportedScripts": MarionetteServerConnection.prototype.clearImportedScripts,
   "getAppCacheStatus": MarionetteServerConnection.prototype.getAppCacheStatus,
-  "closeWindow": MarionetteServerConnection.prototype.closeWindow,
+  "close": MarionetteServerConnection.prototype.close,
+  "closeWindow": MarionetteServerConnection.prototype.close,  // deprecated
   "setTestName": MarionetteServerConnection.prototype.setTestName,
   "screenShot": MarionetteServerConnection.prototype.screenShot,
   "addCookie": MarionetteServerConnection.prototype.addCookie,
   "getAllCookies": MarionetteServerConnection.prototype.getAllCookies,
   "deleteAllCookies": MarionetteServerConnection.prototype.deleteAllCookies,
   "deleteCookie": MarionetteServerConnection.prototype.deleteCookie,
   "getActiveElement": MarionetteServerConnection.prototype.getActiveElement,
   "getScreenOrientation": MarionetteServerConnection.prototype.getScreenOrientation,
@@ -2435,17 +2435,17 @@ BrowserObj.prototype = {
       case "Fennec":
         this.browser = win.BrowserApp;
         break;
     }
   },
   /**
    * Called when we start a session with this browser.
    *
-   * In a desktop environment, if newTab is true, it will start 
+   * In a desktop environment, if newTab is true, it will start
    * a new 'about:blank' tab and change focus to this tab.
    *
    * This will also set the active messagemanager for this object
    *
    * @param boolean newTab
    *        If true, create new tab
    */
   startSession: function BO_startSession(newTab, win, callback) {
@@ -2502,17 +2502,17 @@ BrowserObj.prototype = {
    */
   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 
+   * 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
    * @param object frameWindow
    *        the DOMWindow object of the frame that's being registered
    */
   register: function BO_register(uid, frameWindow) {