Bug 693959 - convert quit.js to specialpowers. r=ted
authorJoel Maher <jmaher@mozilla.com>
Fri, 14 Oct 2011 07:52:02 -0400
changeset 78738 0ffe9e4d56e6af306e6c622ab420f3153c837f9c
parent 78737 8e0f443496ac0c1f965470a8250b708f21de4815
child 78739 c7aa590bd507686740180e09c9e416dd408ba46a
push id2661
push userjmaher@mozilla.com
push dateFri, 14 Oct 2011 11:53:14 +0000
treeherdermozilla-inbound@c7aa590bd507 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs693959
milestone10.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 693959 - convert quit.js to specialpowers. r=ted
testing/mochitest/Makefile.in
testing/mochitest/browser-harness.xul
testing/mochitest/harness-overlay.xul
testing/mochitest/ipc-overlay.xul
testing/mochitest/ipc.js
testing/mochitest/jar.mn
testing/mochitest/plain-loop.html
testing/mochitest/runtests.py
testing/mochitest/server.js
testing/mochitest/specialpowers/components/SpecialPowersObserver.js
testing/mochitest/specialpowers/content/specialpowers.js
testing/mochitest/tests/SimpleTest/ChromePowers.js
testing/mochitest/tests/SimpleTest/Makefile.in
testing/mochitest/tests/SimpleTest/SimpleTest.js
testing/mochitest/tests/SimpleTest/TestRunner.js
testing/mochitest/tests/SimpleTest/quit.js
testing/mochitest/tests/SimpleTest/setup.js
testing/mochitest/tests/index.html
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -86,18 +86,16 @@ include $(topsrcdir)/build/automation-bu
 		$(topsrcdir)/build/mobile/remoteautomation.py \
 		gen_template.pl \
 		server.js \
 		harness-overlay.xul \
 		harness.xul \
 		browser-test-overlay.xul \
 		browser-test.js \
 		chrome-harness.js \
-		ipc-overlay.xul \
-		ipc.js \
 		browser-harness.xul \
 		redirect.html \
 		$(topsrcdir)/build/pgo/server-locations.txt \
 		$(topsrcdir)/netwerk/test/httpserver/httpd.js \
 		mozprefs.js \
 		pywebsocket_wrapper.py \
  	 	plain-loop.html \
 		$(NULL)	
--- a/testing/mochitest/browser-harness.xul
+++ b/testing/mochitest/browser-harness.xul
@@ -41,17 +41,16 @@
 
 <window id="browserTestHarness"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="TestStart();"
         title="Browser chrome tests"
         width="1024">
   <script src="chrome://mochikit/content/tests/SimpleTest/MozillaLogger.js"/>
   <script src="chrome://mochikit/content/tests/SimpleTest/LogController.js"/>
-  <script src="chrome://mochikit/content/tests/SimpleTest/quit.js"/>
   <script src="chrome://mochikit/content/chrome-harness.js"/>
   <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
     #results {
       margin: 5px;
       background-color: window;
       -moz-user-select: text;
     }
 
@@ -261,17 +260,18 @@
                               }).join("\n") + "</div>";
     }
 
     function testsFinished(aTests) {
       // Focus our window, to display the results
       window.focus();
 
       if (gConfig.closeWhenDone) {
-        goQuitApplication();
+        let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup);
+        appStartup.quit(Ci.nsIAppStartup.eForceQuit);
         return;
       }
 
       // UI
       document.getElementById("results").innerHTML = getHTMLLogFromTests(aTests);
       setStatus("Done.");
     }
 
--- a/testing/mochitest/harness-overlay.xul
+++ b/testing/mochitest/harness-overlay.xul
@@ -16,18 +16,16 @@
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js"/>
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/>
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/TestRunner.js"/>
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/MozillaLogger.js"/>
-  <script type="text/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/quit.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/chrome-harness.js" />
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/setup.js" />
   <script type="application/javascript;version=1.7"><![CDATA[
 
 if (Cc === undefined) {
   var Cc = Components.classes;
deleted file mode 100644
--- a/testing/mochitest/ipc-overlay.xul
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0"?>
-<!-- ***** BEGIN LICENSE BLOCK *****
-   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
-   -
-   - The contents of this file are subject to the Mozilla Public License Version
-   - 1.1 (the "License"); you may not use this file except in compliance with
-   - the License. You may obtain a copy of the License at
-   - http://www.mozilla.org/MPL/
-   -
-   - Software distributed under the License is distributed on an "AS IS" basis,
-   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-   - for the specific language governing rights and limitations under the
-   - License.
-   -
-   - The Original Code is Mozilla's layout acceptance tests.
-   -
-   - The Initial Developer of the Original Code is the Mozilla Foundation.
-   - Portions created by the Initial Developer are Copyright (C) 2006
-   - the Initial Developer. All Rights Reserved.
-   -
-   - Contributor(s):
-   -   Joel Maher <joel.maher@gmail.com>, Mozilla Corporation (original author)
-   -
-   - Alternatively, the contents of this file may be used under the terms of
-   - either the GNU General Public License Version 2 or later (the "GPL"), or
-   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-   - in which case the provisions of the GPL or the LGPL are applicable instead
-   - of those above. If you wish to allow use of your version of this file only
-   - under the terms of either the GPL or the LGPL, and not to allow others to
-   - use your version of this file under the terms of the MPL, indicate your
-   - decision by deleting the provisions above and replace them with the notice
-   - and other provisions required by the LGPL or the GPL. If you do not delete
-   - the provisions above, a recipient may use your version of this file under
-   - the terms of any one of the MPL, the GPL or the LGPL.
-   -
-   - ***** END LICENSE BLOCK ***** -->
-
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/static/harness.css" 
-                 type="text/css"?>
-
-<overlay id="browserTestOverlay"
-         xmlns:html="http://www.w3.org/1999/xhtml"
-         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-         xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-<window>
-<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/quit.js" />
-<script type="application/javascript;version=1.7">
-
-function messageHandler(m) {
-  var data = m.json.data;
-  switch(m.json.type) {
-  case 'QuitApplication':
-    messageManager.removeMessageListener("chromeEvent", messageHandler);
-    goQuitApplication();
-    break;
-  case 'Focus':
-    window.focus();
-    break;
-  default:
-    break;
-  }
-}
-
-function setup() {
-  window.removeEventListener("load", setup, false);
-  messageManager.loadFrameScript("chrome://mochikit/content/ipc.js", true);
-  messageManager.addMessageListener("chromeEvent", messageHandler);
-}
-
-window.addEventListener("load", setup, false);
-</script>
-</window></overlay>
deleted file mode 100644
--- a/testing/mochitest/ipc.js
+++ /dev/null
@@ -1,205 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla's layout acceptance tests.
- *
- * The Initial Developer of the Original Code is the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Joel Maher <joel.maher@gmail.com>, Mozilla Corporation (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-if (Cc === undefined) {
-  var Cc = Components.classes;
-  var Ci = Components.interfaces;
-}
-
-function ipcEvent(e) {
-    var sync = e.getData("sync");
-    var type = e.getData("type");
-    var data = JSON.parse(e.getData("data"));
-
-    switch(type) {
-    case 'waitForFocus':
-      if (content)
-        var wrapper = content.wrappedJSObject.frames[0].SimpleTest;
-      else
-        var wrapper = SimpleTest;
-      ipctest.waitForFocus(wrapper[data.callback], data.targetWindow, data.expectBlankPage);
-      break;
-    default:
-      if (type == 'QuitApplication') {
-        removeEventListener("contentEvent", function (e) { ipcEvent(e); }, false, true);
-      }
-
-      if (sync == 1) {
-        return sendSyncMessage("chromeEvent", {"type":type, "data":data});
-      } else {
-        sendAsyncMessage("chromeEvent", {"type":type, "data":data});
-      }
-    }
-};
-
-var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
-                 .getService(Components.interfaces.nsIXULRuntime);
-
-//check if we are in content process
-if (xulRuntime.processType == 2) {
-  addEventListener("contentEvent", function (e) { ipcEvent(e); }, false, true);
-}
-
-var ipctest = {};
-
-ipctest.waitForFocus_started = false;
-ipctest.waitForFocus_loaded = false;
-ipctest.waitForFocus_focused = false;
-
-ipctest.waitForFocus = function (callback, targetWindow, expectBlankPage) {
-
-    if (targetWindow && targetWindow != undefined) {
-      var tempID = targetWindow;
-      targetWindow = null;
-      var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
-                         .getService(Ci.nsIWindowMediator);
-      var wm_enum = wm.getXULWindowEnumerator(null);
-
-      while(wm_enum.hasMoreElements()) {
-        var win = wm_enum.getNext().QueryInterface(Ci.nsIXULWindow)
-                  .docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow)
-                  .content.wrappedJSObject;
-
-        var domutils = win.QueryInterface(Ci.nsIInterfaceRequestor).
-                           getInterface(Ci.nsIDOMWindowUtils);
-
-        if (domutils.outerWindowID == tempID) {
-          targetWindow = win;
-        }
-      }
-    }
-
-    if (targetWindow == null || targetWindow == undefined)
-      if (content)
-        targetWindow = content.document.defaultView;
-      else
-        targetWindow = window;
-
-    ipctest.waitForFocus_started = false;
-    expectBlankPage = !!expectBlankPage;
-
-    var fm = Cc["@mozilla.org/focus-manager;1"].
-                        getService(Ci.nsIFocusManager);
-
-    var childTargetWindow = { };
-    fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow);
-    childTargetWindow = childTargetWindow.value;
-
-    function debugFocusLog(prefix) {
-        if (content)
-          var wrapper = content.wrappedJSObject.frames[0].SimpleTest;
-        else
-          var wrapper = SimpleTest;
-        wrapper.ok(true, prefix + " -- loaded: " + targetWindow.document.readyState +
-           " active window: " +
-               (fm.activeWindow ? "(" + fm.activeWindow + ") " + fm.activeWindow.location : "<no window active>") +
-           " focused window: " +
-               (fm.focusedWindow ? "(" + fm.focusedWindow + ") " + fm.focusedWindow.location : "<no window focused>") +
-           " desired window: (" + targetWindow + ") " + targetWindow.location +
-           " child window: (" + childTargetWindow + ") " + childTargetWindow.location);
-    }
-
-    debugFocusLog("before wait for focus");
-
-    function maybeRunTests() {
-        debugFocusLog("maybe run tests <load:" +
-                      ipctest.waitForFocus_loaded + ", focus:" + ipctest.waitForFocus_focused + ">");
-        if (ipctest.waitForFocus_loaded &&
-            ipctest.waitForFocus_focused &&
-            !ipctest.waitForFocus_started) {
-            ipctest.waitForFocus_started = true;
-            if (content)
-              content.setTimeout(function() { callback(); }, 0, targetWindow);
-            else
-              setTimeout(function() { callback(); }, 0, targetWindow);
-        }
-    }
-
-    function waitForEvent(event) {
-        try {
-            debugFocusLog("waitForEvent called <type:" + event.type + ", target" + event.target + ">");
-
-            // Check to make sure that this isn't a load event for a blank or
-            // non-blank page that wasn't desired.
-            if (event.type == "load" && (expectBlankPage != (event.target.location == "about:blank")))
-                return;
-
-            ipctest["waitForFocus_" + event.type + "ed"] = true;
-            var win = (event.type == "load") ? targetWindow : childTargetWindow;
-            win.removeEventListener(event.type, waitForEvent, true);
-            maybeRunTests();
-        } catch (e) {
-        }
-    }
-
-    // If the current document is about:blank and we are not expecting a blank
-    // page (or vice versa), and the document has not yet loaded, wait for the
-    // page to load. A common situation is to wait for a newly opened window
-    // to load its content, and we want to skip over any intermediate blank
-    // pages that load. This issue is described in bug 554873.
-    ipctest.waitForFocus_loaded =
-        (expectBlankPage == (targetWindow.location == "about:blank")) &&
-        targetWindow.document.readyState == "complete";
-    if (!ipctest.waitForFocus_loaded) {
-        targetWindow.addEventListener("load", waitForEvent, true);
-    }
-
-    // Check if the desired window is already focused.
-    var focusedChildWindow = { };
-    if (fm.activeWindow) {
-        fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow);
-        focusedChildWindow = focusedChildWindow.value;
-    }
-
-    // If this is a child frame, ensure that the frame is focused.
-    ipctest.waitForFocus_focused = (focusedChildWindow == childTargetWindow);
-    if (ipctest.waitForFocus_focused) {
-        maybeRunTests();
-    }
-    else {
-        //TODO: is this really the childTargetWindow 
-        //      and are we really doing something with it here?
-        if (content) {
-          var wr = childTargetWindow.wrappedJSObject;
-          wr.addEventListener("focus", waitForEvent, true);
-          sendAsyncMessage("chromeEvent", {"type":"Focus", "data":{}});
-          wr.focus();
-        } else {
-          childTargetWindow.addEventListener("focus", waitForEvent, true);
-          childTargetWindow.focus();
-        }
-    }
-};
--- a/testing/mochitest/jar.mn
+++ b/testing/mochitest/jar.mn
@@ -1,32 +1,29 @@
 mochikit.jar:
 % content mochikit %content/
   content/browser-harness.xul (browser-harness.xul)
   content/browser-test.js (browser-test.js)
   content/browser-test-overlay.xul (browser-test-overlay.xul)
   content/chrome-harness.js (chrome-harness.js)
   content/harness-overlay.xul (harness-overlay.xul)
   content/harness.xul (harness.xul)
-  content/ipc.js (ipc.js)
-  content/ipc-overlay.xul (ipc-overlay.xul)
   content/mozprefs.js (mozprefs.js)
   content/redirect.html (redirect.html)
   content/server.js (server.js)
   content/dynamic/getMyDirectory.sjs (dynamic/getMyDirectory.sjs)
   content/static/harness.css (static/harness.css)
   content/tests/SimpleTest/ChromePowers.js (tests/SimpleTest/ChromePowers.js)
   content/tests/SimpleTest/specialpowersAPI.js (tests/SimpleTest/specialpowersAPI.js)
   content/tests/SimpleTest/SpecialPowersObserverAPI.js (tests/SimpleTest/SpecialPowersObserverAPI.js)
   content/tests/SimpleTest/EventUtils.js (tests/SimpleTest/EventUtils.js)
   content/tests/SimpleTest/ChromeUtils.js (tests/SimpleTest/ChromeUtils.js)
   content/tests/SimpleTest/MozillaLogger.js (tests/SimpleTest/MozillaLogger.js)
   content/tests/SimpleTest/LogController.js (tests/SimpleTest/LogController.js)
   content/tests/SimpleTest/PluginUtils.js (tests/SimpleTest/PluginUtils.js)
-  content/tests/SimpleTest/quit.js (tests/SimpleTest/quit.js)
   content/tests/SimpleTest/setup.js (tests/SimpleTest/setup.js)
   content/tests/SimpleTest/SimpleTest.js (tests/SimpleTest/SimpleTest.js)
   content/tests/SimpleTest/test.css (tests/SimpleTest/test.css)
   content/tests/SimpleTest/TestRunner.js (tests/SimpleTest/TestRunner.js)
   content/tests/SimpleTest/WindowSnapshot.js (tests/SimpleTest/WindowSnapshot.js)
   content/tests/SimpleTest/mockObjects.js (../../toolkit/content/tests/browser/common/mockObjects.js)
   content/tests/SimpleTest/docshell_helpers.js (../..//docshell/test/chrome/docshell_helpers.js)
 
--- a/testing/mochitest/plain-loop.html
+++ b/testing/mochitest/plain-loop.html
@@ -1,15 +1,14 @@
 <html>
 <head>
   <link rel="stylesheet" type="text/css" href="/static/harness.css" />
   <script type="text/javascript" src="/tests/SimpleTest/LogController.js"></script>        
   <script type="text/javascript" src="/tests/SimpleTest/TestRunner.js"></script>        
   <script type="text/javascript" src="/tests/SimpleTest/MozillaFileLogger.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/quit.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/setup.js"></script>
   </head>
   <script type="text/javascript">
 
 function loadTests()
 {
   var links = {};
   var params = {};
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -556,17 +556,17 @@ class Mochitest(object):
     return browserEnv
 
   def buildURLOptions(self, options, env):
     """ Add test control options from the command line to the url 
 
         URL parameters to test URL:
 
         autorun -- kick off tests automatically
-        closeWhenDone -- runs quit.js after tests
+        closeWhenDone -- closes the browser after the tests
         hideResultsTable -- hides the table of individual test results
         logFile -- logs test run to an absolute path
         totalChunks -- how many chunks to split tests into
         thisChunk -- which chunk to run
         timeout -- per-test timeout in seconds
         repeat -- How many times to repeat the test, ie: repeat=1 will run the test twice.
     """
   
@@ -808,26 +808,18 @@ toolbar#nav-bar {
 
     # Support Firefox (browser) and SeaMonkey (navigator).
     chrome = ""
     if options.browserChrome or options.chrome or options.a11y:
       chrome += """
 overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul
 overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
 """
-    else:
-      #only do the ipc-overlay.xul for mochitest-plain.  
-      #Currently there are focus issues in chrome tests and issues with new windows and dialogs when using ipc
-      chrome += """
-overlay chrome://browser/content/browser.xul chrome://mochikit/content/ipc-overlay.xul
-overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/ipc-overlay.xul
-"""
 
     self.installChromeJar(jarDir, chrome, options)
-
     return manifest
 
   def installChromeJar(self, jarDirName, chrome, options):
     """
       copy mochijar directory to profile as an extension so we have chrome://mochikit for all harness code
     """
     self.automation.installExtension(os.path.join(self.SCRIPT_DIRECTORY, jarDirName), \
                                      options.profilePath, "mochikit@mozilla.org")
--- a/testing/mochitest/server.js
+++ b/testing/mochitest/server.js
@@ -617,18 +617,16 @@ function testListing(metadata, response)
         ),
         SCRIPT({type: "text/javascript",
                  src: "/tests/SimpleTest/LogController.js"}),
         SCRIPT({type: "text/javascript",
                  src: "/tests/SimpleTest/TestRunner.js"}),
         SCRIPT({type: "text/javascript",
                  src: "/tests/SimpleTest/MozillaLogger.js"}),
         SCRIPT({type: "text/javascript",
-                 src: "/tests/SimpleTest/quit.js"}),
-        SCRIPT({type: "text/javascript",
                  src: "/tests/SimpleTest/setup.js"}),
         SCRIPT({type: "text/javascript"},
                "window.onload =  hookup; gTestList=" + tests + ";"
         )
       ),
       BODY(
         DIV({class: "container"},
           H2("--> ", A({href: "#", id: "runtests"}, "Run Tests"), " <--"),
--- a/testing/mochitest/specialpowers/components/SpecialPowersObserver.js
+++ b/testing/mochitest/specialpowers/components/SpecialPowersObserver.js
@@ -84,16 +84,17 @@ SpecialPowersObserver.prototype = new Sp
         break;
 
       case "chrome-document-global-created":
         if (!this._isFrameScriptLoaded) {
           // Register for any messages our API needs us to handle
           this._messageManager.addMessageListener("SPPrefService", this);
           this._messageManager.addMessageListener("SPProcessCrashService", this);
           this._messageManager.addMessageListener("SPPingService", this);
+          this._messageManager.addMessageListener("SpecialPowers.Quit", this);
 
           this._messageManager.loadFrameScript(CHILD_LOGGER_SCRIPT, true);
           this._messageManager.loadFrameScript(CHILD_SCRIPT_API, true);
           this._messageManager.loadFrameScript(CHILD_SCRIPT, true);
           this._isFrameScriptLoaded = true;
         }
         break;
 
@@ -166,14 +167,18 @@ SpecialPowersObserver.prototype = new Sp
         if (aMessage.json.op == "ping") {
           aMessage.target
                   .QueryInterface(Ci.nsIFrameLoaderOwner)
                   .frameLoader
                   .messageManager
                   .sendAsyncMessage("SPPingService", { op: "pong" });
         }
         break;
+      case "SpecialPowers.Quit":
+        let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup);
+        appStartup.quit(Ci.nsIAppStartup.eForceQuit);
+        break;
       default:
         return this._receiveMessage(aMessage);
     }
   };
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]);
--- a/testing/mochitest/specialpowers/content/specialpowers.js
+++ b/testing/mochitest/specialpowers/content/specialpowers.js
@@ -95,16 +95,20 @@ SpecialPowers.prototype._messageReceived
           handler();
         }
       }
       break;
   }
   return true;
 };
 
+SpecialPowers.prototype.quit = function() {
+  sendAsyncMessage("SpecialPowers.Quit", {});
+};
+
 SpecialPowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) {
   this._pongHandlers.push(aCallback);
   sendAsyncMessage("SPPingService", { op: "ping" });
 };
 
 // Expose everything but internal APIs (starting with underscores) to
 // web content.  We cannot use Object.keys to view SpecialPowers.prototype since
 // we are using the functions from SpecialPowersAPI.prototype
--- a/testing/mochitest/tests/SimpleTest/ChromePowers.js
+++ b/testing/mochitest/tests/SimpleTest/ChromePowers.js
@@ -73,16 +73,20 @@ ChromePowers.prototype.registerProcessCr
 };
 
 ChromePowers.prototype.unregisterProcessCrashObservers = function() {
   this._sendSyncMessage("SPProcessCrashService", { op: "unregister-observer" });
 };
 
 ChromePowers.prototype._receiveMessage = function(aMessage) {
   switch (aMessage.name) {
+    case "SpecialPowers.Quit":
+      let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup);
+      appStartup.quit(Ci.nsIAppStartup.eForceQuit);
+      break;
     case "SPProcessCrashService":
       if (aMessage.json.op == "register-observer" || aMessage.json.op == "unregister-observer") {
         // Hack out register/unregister specifically for browser-chrome leaks
         break;
       } else if (aMessage.type == "crash-observed") {
         var self = this;
         msg.dumpIDs.forEach(function(id) {
           self._encounteredCrashDumpFiles.push(id + ".dmp");
@@ -91,16 +95,23 @@ ChromePowers.prototype._receiveMessage =
       }
     default:
       // All calls go here, because we need to handle SPProcessCrashService calls as well
       return this.spObserver._receiveMessageAPI(aMessage);
       break;
   }
 };
 
+ChromePowers.prototype.quit = function() {
+  // We come in here as SpecialPowers.quit, but SpecialPowers is really ChromePowers.
+  // For some reason this.<func> resolves to TestRunner, so using SpecialPowers
+  // allows us to use the ChromePowers object which we defined below.
+  SpecialPowers._sendSyncMessage("SpecialPowers.Quit", {});
+};
+
 ChromePowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) {
   aCallback();
 };
 
 // Expose everything but internal APIs (starting with underscores) to
 // web content.  We cannot use Object.keys to view SpecialPowers.prototype since
 // we are using the functions from SpecialPowersAPI.prototype
 ChromePowers.prototype.__exposedProps__ = {};
--- a/testing/mochitest/tests/SimpleTest/Makefile.in
+++ b/testing/mochitest/tests/SimpleTest/Makefile.in
@@ -39,17 +39,16 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = testing/mochitest/tests/SimpleTest
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/rules.mk
 _SIMPLETEST_FILES =	MozillaLogger.js \
 			LogController.js \
-			quit.js \
 			SimpleTest.js \
 			test.css \
 			TestRunner.js \
 			setup.js \
 			EventUtils.js \
 			ChromeUtils.js \
 			WindowSnapshot.js \
 			PluginUtils.js \
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -29,24 +29,16 @@ if (parent) {
     }
 }
 
 // Workaround test_focus.xul where we open a window which opens another window which includes SimpleTest.js
 if (window.SpecialPowers == undefined && window.opener && window.opener.SpecialPowers !== undefined) {
     window.SpecialPowers = window.opener.SpecialPowers;
 }
 
-// Running in e10s build and need to use IPC?
-var ipcMode = false;
-if (parentRunner) {
-    ipcMode = parentRunner.ipcMode;
-} else if (typeof SpecialPowers != 'undefined') {
-    ipcMode = SpecialPowers.hasContentProcesses();
-}
-
 /* Helper functions pulled out of various MochiKit modules */
 if (typeof(repr) == 'undefined') {
     function repr(o) {
         if (typeof(o) == "undefined") {
             return "undefined";
         } else if (o === null) {
             return "null";
         }
--- a/testing/mochitest/tests/SimpleTest/TestRunner.js
+++ b/testing/mochitest/tests/SimpleTest/TestRunner.js
@@ -19,20 +19,16 @@ function contentDispatchEvent(type, data
   var element = document.createEvent("datacontainerevent");
   element.initEvent("contentEvent", true, false);
   element.setData("sync", sync);
   element.setData("type", type);
   element.setData("data", JSON.stringify(data));
   document.dispatchEvent(element);
 }
 
-function contentSyncEvent(type, data) {
-  contentDispatchEvent(type, data, 1);
-}
-
 function contentAsyncEvent(type, data) {
   contentDispatchEvent(type, data, 0);
 }
 
 /* Helper Function */
 function extend(obj, /* optional */skip) {        
     // Extend an array with an array-like object starting
     // from the skip index
@@ -78,17 +74,16 @@ TestRunner.logEnabled = false;
 TestRunner._currentTest = 0;
 TestRunner.currentTestURL = "";
 TestRunner.originalTestURL = "";
 TestRunner._urls = [];
 
 TestRunner.timeout = 5 * 60 * 1000; // 5 minutes.
 TestRunner.maxTimeouts = 4; // halt testing after too many timeouts
 
-TestRunner.ipcMode = SpecialPowers.hasContentProcesses();
 TestRunner._expectingProcessCrash = false;
 
 /**
  * Make sure the tests don't hang indefinitely.
 **/
 TestRunner._numTimeouts = 0;
 TestRunner._currentTestStartTime = new Date().valueOf();
 TestRunner._timeoutFactor = 1;
@@ -177,19 +172,17 @@ TestRunner._toggle = function(el) {
 TestRunner._makeIframe = function (url, retry) {
     var iframe = $('testframe');
     if (url != "about:blank" &&
         (("hasFocus" in document && !document.hasFocus()) ||
          ("activeElement" in document && document.activeElement != iframe))) {
         // typically calling ourselves from setTimeout is sufficient
         // but we'll try focus() just in case that's needed
 
-        if (TestRunner.ipcMode) {
-          contentAsyncEvent("Focus");
-        }
+        contentAsyncEvent("Focus");
         window.focus();
         iframe.focus();
         if (retry < 3) {
             window.setTimeout('TestRunner._makeIframe("'+url+'", '+(retry+1)+')', 1000);
             return;
         }
 
         TestRunner.log("Error: Unable to restore focus, expect failures and timeouts.");
deleted file mode 100644
--- a/testing/mochitest/tests/SimpleTest/quit.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Automated Testing Code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Bob Clary <bob@bclary.com>
- *   Jeff Walden <jwalden+code@mit.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
-  From mozilla/toolkit/content
-  These files did not have a license
-*/
-
-//Simple test to see if we are running in e10s IPC
-var ipcMode = false;
-if (typeof(TestRunner) != "undefined") {
-  ipcMode = TestRunner.ipcMode;
-}
-
-function quitHook()
-{
-  var xhr = new XMLHttpRequest();
-  xhr.open("GET", "http://" + location.host + "/server/shutdown", true);
-  xhr.onreadystatechange = function (event)
-    {
-      if (xhr.readyState == 4)
-        goQuitApplication();
-    };
-  xhr.send(null);
-}
-
-function canQuitApplication()
-{
-  var os = Components.classes["@mozilla.org/observer-service;1"]
-    .getService(Components.interfaces.nsIObserverService);
-  if (!os) 
-  {
-    return true;
-  }
-  
-  try 
-  {
-    var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
-      .createInstance(Components.interfaces.nsISupportsPRBool);
-    os.notifyObservers(cancelQuit, "quit-application-requested", null);
-    
-    // Something aborted the quit process. 
-    if (cancelQuit.data)
-    {
-      return false;
-    }
-  }
-  catch (ex) 
-  {
-  }
-  return true;
-}
-
-function goQuitApplication()
-{
-  if (ipcMode) {
-    contentAsyncEvent("QuitApplication");
-    return;
-  }
-
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-
-  if (!canQuitApplication()) {
-    return false;
-  }
-  
-  var appService = Components.classes['@mozilla.org/toolkit/app-startup;1']
-                             .getService(Components.interfaces.nsIAppStartup);
-  appService.quit(Components.interfaces.nsIAppStartup.eForceQuit);
-  return true;
-}
--- a/testing/mochitest/tests/SimpleTest/setup.js
+++ b/testing/mochitest/tests/SimpleTest/setup.js
@@ -108,19 +108,19 @@ if (params.timeout) {
 var fileLevel =  params.fileLevel || null;
 var consoleLevel = params.consoleLevel || null;
 
 // loop tells us how many times to run the tests
 if (params.repeat) {
   TestRunner.repeat = params.repeat;
 } 
 
-// closeWhenDone tells us to call quit.js when complete
+// closeWhenDone tells us to close the browser when complete
 if (params.closeWhenDone) {
-  TestRunner.onComplete = goQuitApplication;
+  TestRunner.onComplete = SpecialPowers.quit;
 }
 
 // logFile to write our results
 if (params.logFile) {
   var spl = new SpecialPowersLogger(params.logFile);
   TestRunner.logger.addListener("mozLogger", fileLevel + "", spl.getLogCallback());
 }
 
--- a/testing/mochitest/tests/index.html
+++ b/testing/mochitest/tests/index.html
@@ -1,15 +1,14 @@
 <html>
 <head>
     <!-- This harness does not work locally in Safari -->
     <script type="text/javascript" src="../MochiKit/MochiKit.js"></script>
     <script type="text/javascript" src="SimpleTest/TestRunner.js"></script>
     <script type="text/javascript" src="SimpleTest/MozillaLogger.js"></script>
-    <script type="text/javascript" src="SimpleTest/quit.js"></script>
     <!--<link rel="stylesheet" type="text/css" href="/static/main.css" />-->
 </head>
 <body>
 <p><a href="#" id="runtests">Click To Run Tests</a></p>
 <!--<div id="mt_maketemplate">Make Template for Bug <input type="text" /></div>-->
 <script type="text/javascript">
 
 TestRunner.logEnabled = true;
@@ -17,19 +16,19 @@ TestRunner.logger = new Logger();
 
 // Check the query string for arguments
 var params = parseQueryString(location.search.substring(1), true);
 
 // log levels for console and logfile
 var fileLevel =  params.fileLevel || null;
 var consoleLevel = params.consoleLevel || null;
 
-// closeWhenDone tells us to call quit.js when complete
+// closeWhenDone tells us to close the browser when complete
 if (params.closeWhenDone) {
-  TestRunner.onComplete = goQuitApplication;
+  TestRunner.onComplete = SpecialPowers.quit;
 }
 
 // logFile to write our results
 if (params.logFile) {
   var spl = SpecialPowersLogger(params.logFile);
   TestRunner.logger.addListener("mozLogger", fileLevel + "", spl.getLogCallback());
 }