Bug 1245092 - Install reftest and specialpowers extensions at runtime via AddonManager.installTemporaryAddon, r?jgriffin draft
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Wed, 09 Mar 2016 14:38:13 -0500
changeset 339226 11e8b6e5e895c3c140180725c889d10ba9552102
parent 339110 dd1abe874252e507b825a0a4e1063b0e13578288
child 515938 19e353e599d4db404c8af0634169c8bf698a1d93
push id12671
push userahalberstadt@mozilla.com
push dateThu, 10 Mar 2016 20:10:23 +0000
reviewersjgriffin
bugs1245092
milestone48.0a1
Bug 1245092 - Install reftest and specialpowers extensions at runtime via AddonManager.installTemporaryAddon, r?jgriffin MozReview-Commit-ID: 5HSa3nFVTeF
build/mobile/b2gautomation.py
build/mobile/remoteautomation.py
layout/tools/reftest/Makefile.in
layout/tools/reftest/b2g_start_script.js
layout/tools/reftest/bootstrap.js
layout/tools/reftest/install.rdf
layout/tools/reftest/jar.mn
layout/tools/reftest/moz.build
layout/tools/reftest/reftest-cmdline.js
layout/tools/reftest/reftest-cmdline.manifest
layout/tools/reftest/reftest-preferences.js
layout/tools/reftest/reftest.js
layout/tools/reftest/reftest.jsm
layout/tools/reftest/reftest.xul
layout/tools/reftest/reftestcommandline.py
layout/tools/reftest/remotereftest.py
layout/tools/reftest/runreftest.py
layout/tools/reftest/runreftestb2g.py
testing/mozharness/configs/android/android_panda_releng.py
testing/mozharness/configs/android/androidarm.py
testing/mozharness/configs/android/androidarm_4_3.py
testing/mozharness/configs/android/androidx86.py
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -33,23 +33,22 @@ class StdOutProc(ProcessHandlerMixin):
     def handle_output(self, line):
         self.queue.put_nowait(line)
 
 
 class B2GRemoteAutomation(Automation):
     _devicemanager = None
 
     def __init__(self, deviceManager, appName='', remoteLog=None,
-                 marionette=None, context_chrome=True):
+                 marionette=None):
         self._devicemanager = deviceManager
         self._appName = appName
         self._remoteProfile = None
         self._remoteLog = remoteLog
         self.marionette = marionette
-        self.context_chrome = context_chrome
         self._is_emulator = False
         self.test_script = None
         self.test_script_args = None
 
         # Default our product to b2g
         self._product = "b2g"
         self.lastTestSeen = "b2gautomation.py"
         # Default log finish to mochitest standard
@@ -351,46 +350,43 @@ class B2GRemoteAutomation(Automation):
         else:
             time.sleep(5)
 
         # start a marionette session
         session = self.marionette.start_session()
         if 'b2g' not in session:
             raise Exception("bad session value %s returned by start_session" % session)
 
-        self.marionette.set_context(self.marionette.CONTEXT_CHROME)
-        self.marionette.execute_script("""
-            let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
-            Components.utils.import("resource://gre/modules/Services.jsm");
-            Services.prefs.setBoolPref(SECURITY_PREF, true);
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.marionette.execute_script("""
+                let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
+                Components.utils.import("resource://gre/modules/Services.jsm");
+                Services.prefs.setBoolPref(SECURITY_PREF, true);
 
-            if (!testUtils.hasOwnProperty("specialPowersObserver")) {
-              let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
-                .getService(Components.interfaces.mozIJSSubScriptLoader);
-              loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm",
-                testUtils);
-              testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
-              testUtils.specialPowersObserver.init();
-            }
-            """)
+                if (!testUtils.hasOwnProperty("specialPowersObserver")) {
+                  let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+                    .getService(Components.interfaces.mozIJSSubScriptLoader);
+                  loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm",
+                    testUtils);
+                  testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
+                  testUtils.specialPowersObserver.init();
+                }
+                """)
 
-        if not self.context_chrome:
-            self.marionette.set_context(self.marionette.CONTEXT_CONTENT)
-
-        # run the script that starts the tests
-        if self.test_script:
-            if os.path.isfile(self.test_script):
-                script = open(self.test_script, 'r')
-                self.marionette.execute_script(script.read(), script_args=self.test_script_args)
-                script.close()
-            elif isinstance(self.test_script, basestring):
-                self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
-        else:
-            # assumes the tests are started on startup automatically
-            pass
+            # run the script that starts the tests
+            if self.test_script:
+                if os.path.isfile(self.test_script):
+                    script = open(self.test_script, 'r')
+                    self.marionette.execute_script(script.read(), script_args=self.test_script_args)
+                    script.close()
+                elif isinstance(self.test_script, basestring):
+                    self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
+            else:
+                # assumes the tests are started on startup automatically
+                pass
 
         return instance
 
     # be careful here as this inner class doesn't have access to outer class members
     class B2GInstance(object):
         """Represents a B2G instance running on a device, and exposes
            some process-like methods/properties that are expected by the
            automation.
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -334,28 +334,28 @@ class RemoteAutomation(Automation):
                 testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", newLogContent)
                 if testStartFilenames:
                     self.lastTestSeen = testStartFilenames[-1]
                 print newLogContent
                 return True
 
             self.logBuffer += newLogContent
             lines = self.logBuffer.split('\n')
+            lines = [l for l in lines if l]
 
             if lines:
                 # We only keep the last (unfinished) line in the buffer
                 self.logBuffer = lines[-1]
                 del lines[-1]
 
             if not lines:
                 return False
 
             for line in lines:
                 # This passes the line to the logger (to be logged or buffered)
-                # and returns a list of structured messages (dict)
                 parsed_messages = self.messageLogger.write(line)
                 for message in parsed_messages:
                     if isinstance(message, dict) and message.get('action') == 'test_start':
                         self.lastTestSeen = message['test']
             return True
 
         @property
         def getLastTestSeen(self):
--- a/layout/tools/reftest/Makefile.in
+++ b/layout/tools/reftest/Makefile.in
@@ -1,36 +1,32 @@
 # vim: set shiftwidth=8 tabstop=8 autoindent noexpandtab copyindent:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # 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/.
 
 _DEST_DIR = $(DEPTH)/_tests/reftest
 
 _HARNESS_FILES = \
+  $(srcdir)/b2g_start_script.js \
   $(srcdir)/runreftest.py \
   $(srcdir)/reftestcommandline.py \
+  $(srcdir)/reftest-preferences.js \
   $(srcdir)/remotereftest.py \
   $(srcdir)/runreftestb2g.py \
   $(srcdir)/runreftestmulet.py \
   $(srcdir)/gaia_lock_screen.js \
   $(srcdir)/output.py \
   automation.py \
   $(topsrcdir)/build/mobile/b2gautomation.py \
   $(topsrcdir)/build/mobile/remoteautomation.py \
   $(topsrcdir)/testing/mochitest/server.js \
   $(topsrcdir)/build/pgo/server-locations.txt \
   $(NULL)
 
-_HARNESS_PP_FILES = \
-  b2g_start_script.js \
-  $(NULL)
-_HARNESS_PP_FILES_PATH = $(_DEST_DIR)
-PP_TARGETS += _HARNESS_PP_FILES
-
 include $(topsrcdir)/config/rules.mk
 
 # We're installing to _tests/reftest
 TARGET_DEPTH = ../..
 include $(topsrcdir)/build/automation-build.mk
 
 $(_DEST_DIR):
 	$(NSINSTALL) -D $@
--- a/layout/tools/reftest/b2g_start_script.js
+++ b/layout/tools/reftest/b2g_start_script.js
@@ -1,20 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
-function setDefaultPrefs() {
-    // This code sets the preferences for extension-based reftest.
-    var prefs = Cc["@mozilla.org/preferences-service;1"].
-                getService(Ci.nsIPrefService);
-    var branch = prefs.getDefaultBranch("");
-
-#include reftest-preferences.js
-}
+const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
 
 function setPermissions() {
   if (__marionetteParams.length < 2) {
     return;
   }
 
   let serverAddr = __marionetteParams[0];
   let serverPort = __marionetteParams[1];
@@ -22,31 +15,29 @@ function setPermissions() {
               .getService(Ci.nsIPermissionManager);
   let ioService = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);
   let uri = ioService.newURI("http://" + serverAddr + ":" + serverPort, null, null);
   perms.add(uri, "allowXULXBL", Ci.nsIPermissionManager.ALLOW_ACTION);
 }
 
 var cm = Cc["@mozilla.org/categorymanager;1"]
-           .getService(Components.interfaces.nsICategoryManager);
+           .getService(Ci.nsICategoryManager);
 
 // Disable update timers that cause b2g failures.
 if (cm) {
   cm.deleteCategoryEntry("update-timer", "WebappsUpdateTimer", false);
   cm.deleteCategoryEntry("update-timer", "nsUpdateService", false);
 }
 
 // Load into any existing windows
 var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
             .getService(Ci.nsIWindowMediator);
 var win = wm.getMostRecentWindow('');
 
-// Set preferences and permissions
-setDefaultPrefs();
 setPermissions();
 
 // Loading this into the global namespace causes intermittent failures.
 // See bug 882888 for more details.
 var reftest = {};
 Cu.import("chrome://reftest/content/reftest.jsm", reftest);
 
 // Prevent display off during testing.
--- a/layout/tools/reftest/bootstrap.js
+++ b/layout/tools/reftest/bootstrap.js
@@ -1,73 +1,78 @@
-Components.utils.import("resource://gre/modules/FileUtils.jsm");        
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+const { utils: Cu, interfaces: Ci, classes: Cc, manager: Cm } = Components;
+
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
-function loadIntoWindow(window) {}
-function unloadFromWindow(window) {}
+var WindowListener = {
+  onOpenWindow: function(win) {
+    Services.wm.removeListener(WindowListener);
+
+    win = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    win.addEventListener("load", function listener() {
+      win.removeEventListener("load", listener, false);
+
+      // Load into any existing windows.
+      let windows = Services.wm.getEnumerator("navigator:browser");
+      while (windows.hasMoreElements()) {
+        win = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
+        break;
+      }
 
-function setDefaultPrefs() {
-    // This code sets the preferences for extension-based reftest.
-    var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-                getService(Components.interfaces.nsIPrefService);
-    var branch = prefs.getDefaultBranch("");
+      Cu.import("chrome://reftest/content/reftest.jsm");
+      win.addEventListener("pageshow", function listener() {
+        win.removeEventListener("pageshow", listener);
+        // Add setTimeout here because windows.innerWidth/Height are not set yet.
+        win.setTimeout(function() {OnRefTestLoad(win);}, 0);
+      });
+    }, false);
+  }
+};
+
+function startup(data, reason) {
+  // b2g is bootstrapped by b2g_start_script.js
+  if (Services.appinfo.widgetToolkit == "gonk") {
+    return;
+  }
 
-#include reftest-preferences.js
+  if (Services.appinfo.OS == "Android") {
+    Cm.addBootstrappedManifestLocation(data.installPath);
+    Services.wm.addListener(WindowListener);
+    return;
+  }
+
+  let ios = Cc["@mozilla.org/network/io-service;1"]
+            .getService(Ci.nsIIOService2);
+  ios.manageOfflineStatus = false;
+  ios.offline = false;
+
+  let wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]
+                .getService(Ci.nsIWindowWatcher);
+  let dummy = wwatch.openWindow(null, "about:blank", "dummy",
+                                "chrome,dialog=no,left=800,height=200,width=200,all",null);
+  dummy.onload = function() {
+    dummy.focus();
+    wwatch.openWindow(null, "chrome://reftest/content/reftest.xul", "_blank",
+                      "chrome,dialog=no,all", {});
+  };
 }
 
-var windowListener = {
-    onOpenWindow: function(aWindow) {
-        let domWindow = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowInternal || Components.interfaces.nsIDOMWindow);
-        domWindow.addEventListener("load", function() {
-            domWindow.removeEventListener("load", arguments.callee, false);
-
-            let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
+function shutdown(data, reason) {
+  if (Services.appinfo.widgetToolkit == "gonk") {
+    return;
+  }
 
-            // Load into any existing windows
-            let enumerator = wm.getEnumerator("navigator:browser");
-            while (enumerator.hasMoreElements()) {
-                let win = enumerator.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
-                setDefaultPrefs();
-                Components.utils.import("chrome://reftest/content/reftest.jsm");
-                win.addEventListener("pageshow", function() {
-                    win.removeEventListener("pageshow", arguments.callee); 
-                    // We add a setTimeout here because windows.innerWidth/Height are not set yet;
-                    win.setTimeout(function () {OnRefTestLoad(win);}, 0);
-                });
-                break;
-            }
-        }, false);
-   },
-   onCloseWindow: function(aWindow){ },
-   onWindowTitleChange: function(){ },
-};
-
-function startup(aData, aReason) {
-    let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
-             getService (Components.interfaces.nsIWindowMediator);
-
-    Components.manager.addBootstrappedManifestLocation(aData.installPath);
-
-    // Load into any new windows
-    wm.addListener(windowListener);
+  if (Services.appinfo.OS == "Android") {
+    Services.wm.removeListener(WindowListener);
+    Cm.removedBootstrappedManifestLocation(data.installPath);
+    OnRefTestUnload();
+    Cu.unload("chrome://reftest/content/reftest.jsm");
+  }
 }
 
-function shutdown(aData, aReason) {
-    // When the application is shutting down we normally don't have to clean up any UI changes
-    if (aReason == APP_SHUTDOWN)
-        return;
 
-    let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
-             getService(Components.interfaces.nsIWindowMediator);
-
-    // Stop watching for new windows
-    wm.removeListener(windowListener);
-
-    // Unload from any existing windows
-    let enumerator = wm.getEnumerator("navigator:browser");
-    while (enumerator.hasMoreElements()) {
-        let win = enumerator.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
-        unloadFromWindow(win);
-    }
-}
-
-function install(aData, aReason) { }
-function uninstall(aData, aReason) { }
-
+function install(data, reason) {}
+function uninstall(data, reason) {}
--- a/layout/tools/reftest/install.rdf
+++ b/layout/tools/reftest/install.rdf
@@ -1,19 +1,17 @@
 <?xml version="1.0"?>
 
 <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:em="http://www.mozilla.org/2004/em-rdf#">
   <Description about="urn:mozilla:install-manifest">
     <em:id>reftest@mozilla.org</em:id>
-#ifdef BOOTSTRAP
+    <em:version>1.0</em:version>
     <em:type>2</em:type>
     <em:bootstrap>true</em:bootstrap>
-#endif
-    <em:version>1.0</em:version>
     <em:targetApplication>
       <Description>
         <em:id>toolkit@mozilla.org</em:id>
 #expand        <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
 #expand        <em:maxVersion>__MOZILLA_VERSION_U__</em:maxVersion>
       </Description>
     </em:targetApplication>
     <!-- Front End MetaData -->
--- a/layout/tools/reftest/jar.mn
+++ b/layout/tools/reftest/jar.mn
@@ -1,11 +1,7 @@
 reftest.jar:
 % content reftest %content/
 *  content/reftest-content.js (reftest-content.js)
   content/httpd.jsm (../../../netwerk/test/httpserver/httpd.js)
   content/StructuredLog.jsm (../../../testing/modules/StructuredLog.jsm)
-#ifdef BOOTSTRAP
-*  content/reftest.jsm (reftest.js)
-#else
-*  content/reftest.js (reftest.js)
+*  content/reftest.jsm (reftest.jsm)
   content/reftest.xul (reftest.xul)
-#endif
--- a/layout/tools/reftest/moz.build
+++ b/layout/tools/reftest/moz.build
@@ -2,30 +2,13 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # 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/.
 
 with Files('**'):
     BUG_COMPONENT = ('Testing', 'Reftest')
 
-if CONFIG['MOZ_BUILD_APP'] in ('b2g', 'b2g/dev', 'mobile/android'):
-    DEFINES['BOOTSTRAP'] = True
-    if CONFIG['MOZ_BUILD_APP'] in ('b2g', 'b2g/dev'):
-        DEFINES['REFTEST_B2G'] = True
-else:
-    EXTRA_PP_COMPONENTS += [
-        'reftest-cmdline.js',
-    ]
-    EXTRA_COMPONENTS += [
-        'reftest-cmdline.manifest',
-    ]
-
+XPI_NAME = 'reftest'
+USE_EXTENSION_MANIFEST = True
 JAR_MANIFESTS += ['jar.mn']
-
-USE_EXTENSION_MANIFEST = True
-
-XPI_NAME = 'reftest'
-
 FINAL_TARGET_PP_FILES += ['install.rdf']
-
-if CONFIG['MOZ_BUILD_APP'] == 'mobile/android':
-    FINAL_TARGET_PP_FILES += ['bootstrap.js']
+FINAL_TARGET_FILES += ['bootstrap.js']
deleted file mode 100644
--- a/layout/tools/reftest/reftest-cmdline.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const nsISupports                    = Components.interfaces.nsISupports;
-  
-const nsICommandLine                 = Components.interfaces.nsICommandLine;
-const nsICommandLineHandler          = Components.interfaces.nsICommandLineHandler;
-const nsISupportsString              = Components.interfaces.nsISupportsString;
-const nsIWindowWatcher               = Components.interfaces.nsIWindowWatcher;
-
-function RefTestCmdLineHandler() {}
-RefTestCmdLineHandler.prototype =
-{
-  classID: Components.ID('{32530271-8c1b-4b7d-a812-218e42c6bb23}'),
-
-  /* nsISupports */
-  QueryInterface: XPCOMUtils.generateQI([nsICommandLineHandler]),
-
-  /* nsICommandLineHandler */
-  handle : function handler_handle(cmdLine) {
-    /* Ignore the platform's online/offline status while running reftests. */
-    var ios = Components.classes["@mozilla.org/network/io-service;1"]
-              .getService(Components.interfaces.nsIIOService2);
-    ios.manageOfflineStatus = false;
-    ios.offline = false;
-
-    /**
-     * Manipulate preferences by adding to the *default* branch.  Adding
-     * to the default branch means the changes we make won't get written
-     * back to user preferences.
-     *
-     * We want to do this here rather than in reftest.js because it's
-     * important to force sRGB as an output profile for color management
-     * before we load a window.
-     */
-    var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-                getService(Components.interfaces.nsIPrefService);
-    var branch = prefs.getDefaultBranch("");
-
-#include reftest-preferences.js
-
-    var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                           .getService(nsIWindowWatcher);
-
-    function loadReftests() {
-      wwatch.openWindow(null, "chrome://reftest/content/reftest.xul", "_blank",
-                        "chrome,dialog=no,all", {});
-    }
-
-    var remote = false;
-    try {
-      remote = prefs.getBoolPref("reftest.remote");
-    } catch (ex) {
-    }
-
-    // If we are running on a remote machine, assume that we can't open another
-    // window for transferring focus to when tests don't require focus.
-    if (remote) {
-      loadReftests();
-    }
-    else {
-      // This dummy window exists solely for enforcing proper focus discipline.
-      var dummy = wwatch.openWindow(null, "about:blank", "dummy",
-                                    "chrome,dialog=no,left=800,height=200,width=200,all", null);
-      dummy.onload = function dummyOnload() {
-        dummy.focus();
-        loadReftests();
-      }
-    }
-
-    cmdLine.preventDefault = true;
-  },
-
-  helpInfo : "  --reftest <file>   Run layout acceptance tests on given manifest.\n"
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RefTestCmdLineHandler]);
deleted file mode 100644
--- a/layout/tools/reftest/reftest-cmdline.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {32530271-8c1b-4b7d-a812-218e42c6bb23} reftest-cmdline.js
-contract @mozilla.org/commandlinehandler/general-startup;1?type=reftest {32530271-8c1b-4b7d-a812-218e42c6bb23}
-category command-line-handler m-reftest @mozilla.org/commandlinehandler/general-startup;1?type=reftest
--- a/layout/tools/reftest/reftest-preferences.js
+++ b/layout/tools/reftest/reftest-preferences.js
@@ -1,70 +1,112 @@
-    // For mochitests, we're more interested in testing the behavior of in-
-    // content XBL bindings, so we set this pref to true. In reftests, we're
-    // more interested in testing the behavior of XBL as it works in chrome,
-    // so we want this pref to be false.
-    branch.setBoolPref("dom.use_xbl_scopes_for_remote_xul", false);
-    branch.setIntPref("gfx.color_management.mode", 2);
-    branch.setBoolPref("gfx.color_management.force_srgb", true);
-    branch.setBoolPref("browser.dom.window.dump.enabled", true);
-    branch.setIntPref("ui.caretBlinkTime", -1);
-    branch.setBoolPref("dom.send_after_paint_to_content", true);
-    // no slow script dialogs
-    branch.setIntPref("dom.max_script_run_time", 0);
-    branch.setIntPref("dom.max_chrome_script_run_time", 0);
-    branch.setIntPref("hangmonitor.timeout", 0);
-    // Ensure autoplay is enabled for all platforms.
-    branch.setBoolPref("media.autoplay.enabled", true);
-    // Disable updates
-    branch.setBoolPref("app.update.enabled", false);
-    // Disable addon updates and prefetching so we don't leak them
-    branch.setBoolPref("extensions.update.enabled", false);
-    branch.setBoolPref("extensions.getAddons.cache.enabled", false);
-    // Disable blocklist updates so we don't have them reported as leaks
-    branch.setBoolPref("extensions.blocklist.enabled", false);
-    // Make url-classifier updates so rare that they won't affect tests
-    branch.setIntPref("urlclassifier.updateinterval", 172800);
-    // Disable downscale-during-decode, since it makes reftests more difficult.
-    branch.setBoolPref("image.downscale-during-decode.enabled", false);
-    // Disable the single-color optimization, since it can cause intermittent
-    // oranges and it causes many of our tests to test a different code path
-    // than the one that normal images on the web use.
-    branch.setBoolPref("image.single-color-optimization.enabled", false);
-    // Checking whether two files are the same is slow on Windows.
-    // Setting this pref makes tests run much faster there.
-    branch.setBoolPref("security.fileuri.strict_origin_policy", false);
-    // Disable the thumbnailing service
-    branch.setBoolPref("browser.pagethumbnails.capturing_disabled", true);
-    // Since our tests are 800px wide, set the assume-designed-for width of all
-    // pages to be 800px (instead of the default of 980px). This ensures that
-    // in our 800px window we don't zoom out by default to try to fit the
-    // assumed 980px content.
-    branch.setIntPref("browser.viewport.desktopWidth", 800);
-    // Disable the fade out (over time) of overlay scrollbars, since we
-    // can't guarantee taking both reftest snapshots at the same point
-    // during the fade.
-    branch.setBoolPref("layout.testing.overlay-scrollbars.always-visible", true);
-    // Disable interruptible reflow since (1) it's normally not going to
-    // happen, but (2) it might happen if we somehow end up with both
-    // pending user events and clock skew.  So to avoid having to change
-    // MakeProgress to deal with waiting for interruptible reflows to
-    // complete for a rare edge case, we just disable interruptible
-    // reflow so that that rare edge case doesn't lead to reftest
-    // failures.
-    branch.setBoolPref("layout.interruptible-reflow.enabled", false);
+// For mochitests, we're more interested in testing the behavior of in-
+// content XBL bindings, so we set this pref to true. In reftests, we're
+// more interested in testing the behavior of XBL as it works in chrome,
+// so we want this pref to be false.
+user_pref("dom.use_xbl_scopes_for_remote_xul", false);
+user_pref("gfx.color_management.mode", 2);
+user_pref("gfx.color_management.force_srgb", true);
+user_pref("browser.dom.window.dump.enabled", true);
+user_pref("ui.caretBlinkTime", -1);
+user_pref("dom.send_after_paint_to_content", true);
+// no slow script dialogs
+user_pref("dom.max_script_run_time", 0);
+user_pref("dom.max_chrome_script_run_time", 0);
+user_pref("hangmonitor.timeout", 0);
+// Ensure autoplay is enabled for all platforms.
+user_pref("media.autoplay.enabled", true);
+// Disable updates
+user_pref("app.update.enabled", false);
+user_pref("app.update.staging.enabled", false);
+user_pref("app.update.url.android", "");
+// Disable addon updates and prefetching so we don't leak them
+user_pref("extensions.update.enabled", false);
+user_pref("extensions.systemAddon.update.url", "http://localhost/dummy-system-addons.xml");
+user_pref("extensions.getAddons.cache.enabled", false);
+// Disable blocklist updates so we don't have them reported as leaks
+user_pref("extensions.blocklist.enabled", false);
+// Make url-classifier updates so rare that they won't affect tests
+user_pref("urlclassifier.updateinterval", 172800);
+// Disable downscale-during-decode, since it makes reftests more difficult.
+user_pref("image.downscale-during-decode.enabled", false);
+// Disable the single-color optimization, since it can cause intermittent
+// oranges and it causes many of our tests to test a different code path
+// than the one that normal images on the web use.
+user_pref("image.single-color-optimization.enabled", false);
+// Checking whether two files are the same is slow on Windows.
+// Setting this pref makes tests run much faster there.
+user_pref("security.fileuri.strict_origin_policy", false);
+// Disable the thumbnailing service
+user_pref("browser.pagethumbnails.capturing_disabled", true);
+// Since our tests are 800px wide, set the assume-designed-for width of all
+// pages to be 800px (instead of the default of 980px). This ensures that
+// in our 800px window we don't zoom out by default to try to fit the
+// assumed 980px content.
+user_pref("browser.viewport.desktopWidth", 800);
+// Disable the fade out (over time) of overlay scrollbars, since we
+// can't guarantee taking both reftest snapshots at the same point
+// during the fade.
+user_pref("layout.testing.overlay-scrollbars.always-visible", true);
+// Disable interruptible reflow since (1) it's normally not going to
+// happen, but (2) it might happen if we somehow end up with both
+// pending user events and clock skew.  So to avoid having to change
+// MakeProgress to deal with waiting for interruptible reflows to
+// complete for a rare edge case, we just disable interruptible
+// reflow so that that rare edge case doesn't lead to reftest
+// failures.
+user_pref("layout.interruptible-reflow.enabled", false);
 
-    // Tell the search service we are running in the US.  This also has the
-    // desired side-effect of preventing our geoip lookup.
-    branch.setBoolPref("browser.search.isUS", true);
-    branch.setCharPref("browser.search.countryCode", "US");
-    // Prevent the geoSpecificDefaults XHR by emptying the URL.
-    branch.setCharPref("browser.search.geoSpecificDefaults.url", "");
+// Tell the search service we are running in the US.  This also has the
+// desired side-effect of preventing our geoip lookup.
+user_pref("browser.search.isUS", true);
+user_pref("browser.search.countryCode", "US");
+user_pref("browser.search.geoSpecificDefaults", false);
+
+// Make sure SelfSupport doesn't hit the network.
+user_pref("browser.selfsupport.url", "https://localhost/selfsupport-dummy/");
+
+// use about:blank, not browser.startup.homepage
+user_pref("browser.startup.page", 0);
+
+// Allow XUL and XBL files to be opened from file:// URIs
+user_pref("dom.allow_XUL_XBL_for_file", true);
+
+// Allow view-source URIs to be opened from URIs that share
+// their protocol with the inner URI of the view-source URI
+user_pref("security.view-source.reachable-from-inner-protocol", true);
 
-    // Make sure SelfSupport doesn't hit the network.
-    branch.setCharPref("browser.selfsupport.url", "https://%(server)s/selfsupport-dummy/");
+// Ensure that telemetry is disabled, so we don't connect to the telemetry
+// server in the middle of the tests.
+user_pref("toolkit.telemetry.enabled", false);
+user_pref("toolkit.telemetry.unified", false);
+// Likewise for safebrowsing.
+user_pref("browser.safebrowsing.enabled", false);
+user_pref("browser.safebrowsing.malware.enabled", false);
+// Likewise for tracking protection.
+user_pref("privacy.trackingprotection.enabled", false);
+user_pref("privacy.trackingprotection.pbmode.enabled", false);
+// And for snippets.
+user_pref("browser.snippets.enabled", false);
+user_pref("browser.snippets.syncPromo.enabled", false);
+user_pref("browser.snippets.firstrunHomepage.enabled", false);
+// And for useragent updates.
+user_pref("general.useragent.updates.enabled", false);
+// And for webapp updates.  Yes, it is supposed to be an integer.
+user_pref("browser.webapps.checkForUpdates", 0);
+// And for about:newtab content fetch and pings.
+user_pref("browser.newtabpage.directory.source", "data:application/json,{\"reftest\":1}");
+user_pref("browser.newtabpage.directory.ping", "");
+// Only allow add-ons from the profile and app and allow foreign
+// injection
+user_pref("extensions.enabledScopes", 5);
+user_pref("extensions.autoDisableScopes", 0);
+// Allow unsigned add-ons
+user_pref("xpinstall.signatures.required", false);
 
-    // Allow XUL and XBL files to be opened from file:// URIs
-    branch.setBoolPref("dom.allow_XUL_XBL_for_file", true);
+// Don't use auto-enabled e10s
+user_pref("browser.tabs.remote.autostart.1", false);
+user_pref("browser.tabs.remote.autostart.2", false);
 
-    // Allow view-source URIs to be opened from URIs that share
-    // their protocol with the inner URI of the view-source URI
-    branch.setBoolPref("security.view-source.reachable-from-inner-protocol", true);
+user_pref("startup.homepage_welcome_url", "");
+user_pref("startup.homepage_override_url", "");
+
+user_pref("media.gmp-manager.url.override", "http://localhost/dummy-gmp-manager.xml");
rename from layout/tools/reftest/reftest.js
rename to layout/tools/reftest/reftest.jsm
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.jsm
@@ -1,18 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- /
 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
-#if BOOTSTRAP
-this.EXPORTED_SYMBOLS = ["OnRefTestLoad"];
-#endif
-
+this.EXPORTED_SYMBOLS = ["OnRefTestLoad", "OnRefTestUnload"];
 
 var CC = Components.classes;
 const CI = Components.interfaces;
 const CR = Components.results;
 const CU = Components.utils;
 
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -175,39 +172,43 @@ function HasUnexpectedResult()
            gTestResults.FailedLoad > 0 ||
            gTestResults.UnexpectedFail > 0 ||
            gTestResults.UnexpectedPass > 0 ||
            gTestResults.AssertionUnexpected > 0 ||
            gTestResults.AssertionUnexpectedFixed > 0;
 }
 
 // By default we just log to stdout
-var gDumpFn = dump;
+var gLogFile = null;
 var gDumpRawLog = function(record) {
   // Dump JSON representation of data on a single line
-  var line = JSON.stringify(record);
-  gDumpFn("\n" + line + "\n");
+  var line = "\n" + JSON.stringify(record) + "\n";
+  dump(line);
+
+  if (gLogFile) {
+    gLogFile.write(line, line.length);
+  }
 }
 var logger = new StructuredLogger('reftest', gDumpRawLog);
 
 function TestBuffer(str)
 {
-    logger.debug(str);
-    gTestLog.push(str);
+  logger.debug(str);
+  gTestLog.push(str);
 }
 
 function FlushTestBuffer()
 {
-    // In debug mode, we've dumped all these messages already.
-    if (gLogLevel !== 'debug') {
-        for (var i = 0; i < gTestLog.length; ++i) {
-            logger.info("Saved log: " + gTestLog[i]);
-        }
+  // In debug mode, we've dumped all these messages already.
+  if (gLogLevel !== 'debug') {
+    for (var i = 0; i < gTestLog.length; ++i) {
+      logger.info("Saved log: " + gTestLog[i]);
     }
-    gTestLog = [];
+  }
+  gTestLog = [];
 }
 
 function AllocateCanvas()
 {
     if (gRecycledCanvases.length > 0)
         return gRecycledCanvases.shift();
 
     var canvas = gContainingWindow.document.createElementNS(XHTML_NS, "canvas");
@@ -300,29 +301,30 @@ this.OnRefTestLoad = function OnRefTestL
     }
     gBrowser.setAttribute("id", "browser");
     gBrowser.setAttribute("type", "content-primary");
     gBrowser.setAttribute("remote", gBrowserIsRemote ? "true" : "false");
     // Make sure the browser element is exactly 800x1000, no matter
     // what size our window is
     gBrowser.setAttribute("style", "padding: 0px; margin: 0px; border:none; min-width: 800px; min-height: 1000px; max-width: 800px; max-height: 1000px");
 
-#ifdef BOOTSTRAP
-#ifdef REFTEST_B2G
-    var doc = gContainingWindow.document.getElementsByTagName("html")[0];
-#else
-    var doc = gContainingWindow.document.getElementById('main-window');
-#endif
-    while (doc.hasChildNodes()) {
-      doc.removeChild(doc.firstChild);
+    if (Services.appinfo.OS == "Android") {
+      let doc;
+      if (Services.appinfo.widgetToolkit == "gonk") {
+        doc = gContainingWindow.document.getElementsByTagName("html")[0];
+      } else {
+        doc = gContainingWindow.document.getElementById('main-window');
+      }
+      while (doc.hasChildNodes()) {
+        doc.removeChild(doc.firstChild);
+      }
+      doc.appendChild(gBrowser);
+    } else {
+      document.getElementById("reftest-window").appendChild(gBrowser);
     }
-    doc.appendChild(gBrowser);
-#else
-    document.getElementById("reftest-window").appendChild(gBrowser);
-#endif
 
     // reftests should have the test plugins enabled, not click-to-play
     let plugin1 = getTestPlugin("Test Plug-in");
     let plugin2 = getTestPlugin("Second Test Plug-in");
     if (plugin1 && plugin2) {
       gTestPluginEnabledStates = [plugin1.enabledState, plugin2.enabledState];
       plugin1.enabledState = CI.nsIPluginTag.STATE_ENABLED;
       plugin2.enabledState = CI.nsIPluginTag.STATE_ENABLED;
@@ -357,37 +359,18 @@ function InitAndStartRefTests()
     } catch(e) {
         gLoadTimeout = 5 * 60 * 1000; //5 minutes as per bug 479518
     }
 
     /* Get the logfile for android tests */
     try {
         var logFile = prefs.getCharPref("reftest.logFile");
         if (logFile) {
-            try {
-                var f = FileUtils.File(logFile);
-                var mfl = FileUtils.openFileOutputStream(f, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE);
-                // Set to mirror to stdout as well as the file
-                gDumpFn = function (msg) {
-#ifdef BOOTSTRAP
-#ifdef REFTEST_B2G
-                    dump(msg);
-#else
-                    //NOTE: on android-xul, we have a libc crash if we do a dump with %7s in the string
-#endif
-#else
-                    dump(msg);
-#endif
-                    mfl.write(msg, msg.length);
-                };
-            }
-            catch(e) {
-                // If there is a problem, just use stdout
-                gDumpFn = dump;
-            }
+            var f = FileUtils.File(logFile);
+            gLogFile = FileUtils.openFileOutputStream(f, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE);
         }
     } catch(e) {}
 
     try {
         gRemote = prefs.getBoolPref("reftest.remote");
     } catch(e) {
         gRemote = false;
     }
@@ -1377,18 +1360,18 @@ function StartCurrentURI(aState)
         gURLs[0].maxAsserts == 0) {
         // Pretend the document loaded --- RecordResult will notice
         // there's already a canvas for this URL
         gContainingWindow.setTimeout(RecordResult, 0);
     } else {
         var currentTest = gTotalTests - gURLs.length;
         // Log this to preserve the same overall log format,
         // should be removed if the format is updated
-        gDumpFn("REFTEST TEST-LOAD | " + gCurrentURL + " | " + currentTest + " / " + gTotalTests +
-                " (" + Math.floor(100 * (currentTest / gTotalTests)) + "%)\n");
+        dump("REFTEST TEST-LOAD | " + gCurrentURL + " | " + currentTest + " / " + gTotalTests +
+             " (" + Math.floor(100 * (currentTest / gTotalTests)) + "%)\n");
         TestBuffer("START " + gCurrentURL);
         var type = gURLs[0].type
         if (TYPE_SCRIPT == type) {
             SendLoadScriptTest(gCurrentURL, gLoadTimeout);
         } else {
             SendLoadTest(type, gCurrentURL, gLoadTimeout);
         }
     }
@@ -1830,29 +1813,29 @@ function DoAssertionCheck(numAsserts)
         var expectedAssertions = "expected " + minAsserts;
         if (minAsserts != maxAsserts) {
             expectedAssertions += " to " + maxAsserts;
         }
         expectedAssertions += " assertions";
 
         if (numAsserts < minAsserts) {
             ++gTestResults.AssertionUnexpectedFixed;
-            gDumpFn("REFTEST TEST-UNEXPECTED-PASS | " + gURLs[0].prettyPath +
-                    " | assertion count" + numAsserts + " is less than " +
+            dump("REFTEST TEST-UNEXPECTED-PASS | " + gURLs[0].prettyPath +
+                 " | assertion count" + numAsserts + " is less than " +
                     expectedAssertions + "\n");
         } else if (numAsserts > maxAsserts) {
             ++gTestResults.AssertionUnexpected;
-            gDumpFn("REFTEST TEST-UNEXPECTED-FAIL | " + gURLs[0].prettyPath +
-                    " | assertion count " + numAsserts + " is more than " +
+            dump("REFTEST TEST-UNEXPECTED-FAIL | " + gURLs[0].prettyPath +
+                 " | assertion count " + numAsserts + " is more than " +
                     expectedAssertions + "\n");
         } else if (numAsserts != 0) {
             ++gTestResults.AssertionKnown;
-            gDumpFn("REFTEST TEST-KNOWN-FAIL | " + gURLs[0].prettyPath +
-                    "assertion count " + numAsserts + " matches " +
-                    expectedAssertions + "\n");
+            dump("REFTEST TEST-KNOWN-FAIL | " + gURLs[0].prettyPath +
+                 "assertion count " + numAsserts + " matches " +
+                 expectedAssertions + "\n");
         }
     }
 
     if (gURLs[0].chaosMode) {
         gWindowUtils.leaveChaosMode();
     }
 
     // And start the next test.
--- a/layout/tools/reftest/reftest.xul
+++ b/layout/tools/reftest/reftest.xul
@@ -4,11 +4,11 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="reftest-window"
         hidechrome="true"
         onload="OnRefTestLoad();"
         onunload="OnRefTestUnload();"
         style="background:white; overflow:hidden"
         >
-    <script type="application/ecmascript" src="reftest.js" />
+    <script type="application/ecmascript" src="reftest.jsm" />
     <!-- The reftest browser element is dynamically created, here -->
 </window>
--- a/layout/tools/reftest/reftestcommandline.py
+++ b/layout/tools/reftest/reftestcommandline.py
@@ -125,16 +125,20 @@ class ReftestArgumentsParser(argparse.Ar
                           action="append",
                           dest="extensionsToInstall",
                           default=[],
                           help="install the specified extension in the testing profile. "
                           "The extension file's name should be <id>.xpi where <id> is "
                           "the extension's id as indicated in its install.rdf. "
                           "An optional path can be specified too.")
 
+        self.add_argument("--marionette",
+                          default=None,
+                          help="host:port to use when connecting to Marionette")
+
         self.add_argument("--setenv",
                           action="append",
                           type=str,
                           default=[],
                           dest="environment",
                           metavar="NAME=VALUE",
                           help="sets the given variable in the application's "
                           "environment")
@@ -383,22 +387,16 @@ class B2GArgumentParser(ReftestArguments
                           help="Optional command-line arg to pass to the browser")
 
         self.add_argument("--b2gpath",
                           action="store",
                           type=str,
                           dest="b2gPath",
                           help="path to B2G repo or qemu dir")
 
-        self.add_argument("--marionette",
-                          action="store",
-                          type=str,
-                          dest="marionette",
-                          help="host:port to use when connecting to Marionette")
-
         self.add_argument("--emulator",
                           action="store",
                           type=str,
                           dest="emulator",
                           help="Architecture of emulator to use: x86 or arm")
 
         self.add_argument("--emulator-res",
                           action="store",
@@ -651,22 +649,16 @@ class RemoteArgumentsParser(ReftestArgum
 
         self.add_argument("--pidfile",
                           action="store",
                           type=str,
                           dest="pidFile",
                           default="",
                           help="name of the pidfile to generate")
 
-        self.add_argument("--bootstrap",
-                          action="store_true",
-                          dest="bootstrap",
-                          default=False,
-                          help="test with a bootstrap addon required for native Fennec")
-
         self.add_argument("--dm_trans",
                           action="store",
                           type=str,
                           dest="dm_trans",
                           default="sut",
                           help="the transport to use to communicate with device: [adb|sut]; default=sut")
 
         self.add_argument("--remoteTestRoot",
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -121,16 +121,17 @@ class ReftestServer:
 
                 rtncode = self._process.poll()
                 if (rtncode == None):
                     self._process.terminate()
             except:
                 self._process.kill()
 
 class RemoteReftest(RefTest):
+    use_marionette = False
     remoteApp = ''
     resolver_cls = RemoteReftestResolver
 
     def __init__(self, automation, devicemanager, options, scriptDir):
         RefTest.__init__(self)
         self.automation = automation
         self._devicemanager = devicemanager
         self.scriptDir = scriptDir
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -28,16 +28,22 @@ import mozinfo
 import mozleak
 import mozlog
 import mozprocess
 import mozprofile
 import mozrunner
 from mozrunner.utils import get_stack_fixer_function, test_environment
 from mozscreenshot import printstatus, dump_screen
 
+try:
+    from marionette import Marionette
+    from marionette_driver.addons import Addons
+except ImportError:
+    Marionette=None
+
 from output import OutputHandler, ReftestFormatter
 import reftestcommandline
 
 here = os.path.abspath(os.path.dirname(__file__))
 
 try:
     from mozbuild.base import MozbuildObject
     build_obj = MozbuildObject.from_environment(cwd=here)
@@ -60,29 +66,29 @@ summaryLines = [('Successful', [('pass',
                                     ('skipped', 'skipped'),
                                     ('slow', 'slow')])]
 
 # Python's print is not threadsafe.
 printLock = threading.Lock()
 
 
 class ReftestThread(threading.Thread):
-    def __init__(self, cmdlineArgs):
+    def __init__(self, cmdargs):
         threading.Thread.__init__(self)
-        self.cmdlineArgs = cmdlineArgs
+        self.cmdargs = cmdargs
         self.summaryMatches = {}
         self.retcode = -1
         for text, _ in summaryLines:
             self.summaryMatches[text] = None
 
     def run(self):
         with printLock:
-            print "Starting thread with", self.cmdlineArgs
+            print "Starting thread with", self.cmdargs
             sys.stdout.flush()
-        process = subprocess.Popen(self.cmdlineArgs, stdout=subprocess.PIPE)
+        process = subprocess.Popen(self.cmdargs, stdout=subprocess.PIPE)
         for chunk in self.chunkForMergedOutput(process.stdout):
             with printLock:
                 print chunk,
                 sys.stdout.flush()
         self.retcode = process.wait()
 
     def chunkForMergedOutput(self, logsource):
         """Gather lines together that should be printed as one atomic unit.
@@ -186,17 +192,19 @@ class ReftestResolver(object):
 
         for key in manifests.iterkeys():
             if None in manifests[key]:
                 manifests[key] = None
             else:
                 manifests[key] = "|".join(list(manifests[key]))
         return manifests
 
+
 class RefTest(object):
+    use_marionette = True
     oldcwd = os.getcwd()
     resolver_cls = ReftestResolver
 
     def __init__(self):
         self.update_mozinfo()
         self.lastTestSeen = 'reftest'
         self.haveDumpedScreen = False
         self.resolver = self.resolver_cls()
@@ -236,25 +244,26 @@ class RefTest(object):
     def createReftestProfile(self, options, manifests, server='localhost', port=0,
                              profile_to_clone=None):
         """Sets up a profile for reftest.
 
         :param options: Object containing command line options
         :param manifests: Dictionary of the form {manifest_path: [filters]}
         :param server: Server name to use for http tests
         :param profile_to_clone: Path to a profile to use as the basis for the
-                                 test profile"""
+                                 test profile
+        """
 
         locations = mozprofile.permissions.ServerLocations()
         locations.add_host(server, scheme='http', port=port)
         locations.add_host(server, scheme='https', port=port)
 
         # Set preferences for communication between our command line arguments
         # and the reftest harness.  Preferences that are required for reftest
-        # to work should instead be set in reftest-cmdline.js .
+        # to work should instead be set in reftest-preferences.js .
         prefs = {}
         prefs['reftest.timeout'] = options.timeout * 1000
         if options.totalChunks:
             prefs['reftest.totalChunks'] = options.totalChunks
         if options.thisChunk:
             prefs['reftest.thisChunk'] = options.thisChunk
         if options.logFile:
             prefs['reftest.logFile'] = options.logFile
@@ -265,68 +274,48 @@ class RefTest(object):
         if options.repeat:
             prefs['reftest.repeat'] = options.repeat
         if options.runUntilFailure:
             prefs['reftest.runUntilFailure'] = True
         prefs['reftest.focusFilterMode'] = options.focusFilterMode
         prefs['reftest.logLevel'] = options.log_tbpl_level or 'info'
         prefs['reftest.manifests'] = json.dumps(manifests)
 
-        # Ensure that telemetry is disabled, so we don't connect to the telemetry
-        # server in the middle of the tests.
-        prefs['toolkit.telemetry.enabled'] = False
-        prefs['toolkit.telemetry.unified'] = False
-        # Likewise for safebrowsing.
-        prefs['browser.safebrowsing.enabled'] = False
-        prefs['browser.safebrowsing.malware.enabled'] = False
-        # Likewise for tracking protection.
-        prefs['privacy.trackingprotection.enabled'] = False
-        prefs['privacy.trackingprotection.pbmode.enabled'] = False
-        # And for snippets.
-        prefs['browser.snippets.enabled'] = False
-        prefs['browser.snippets.syncPromo.enabled'] = False
-        prefs['browser.snippets.firstrunHomepage.enabled'] = False
-        # And for useragent updates.
-        prefs['general.useragent.updates.enabled'] = False
-        # And for webapp updates.  Yes, it is supposed to be an integer.
-        prefs['browser.webapps.checkForUpdates'] = 0
-        # And for about:newtab content fetch and pings.
-        prefs['browser.newtabpage.directory.source'] = 'data:application/json,{"reftest":1}'
-        prefs['browser.newtabpage.directory.ping'] = ''
-        # Only allow add-ons from the profile and app and allow foreign
-        # injection
-        prefs["extensions.enabledScopes"] = 5
-        prefs["extensions.autoDisableScopes"] = 0
-        # Allow unsigned add-ons
-        prefs['xpinstall.signatures.required'] = False
-
-        # Don't use auto-enabled e10s
-        prefs['browser.tabs.remote.autostart.1'] = False
-        prefs['browser.tabs.remote.autostart.2'] = False
         if options.e10s:
             prefs['browser.tabs.remote.autostart'] = True
             prefs['extensions.e10sBlocksEnabling'] = False
 
+        if options.marionette:
+            port = options.marionette.split(':')[1]
+            prefs['marionette.defaultPrefs.port'] = int(port)
+
+        preference_file = os.path.join(here, 'reftest-preferences.js')
+        prefs.update(mozprofile.Preferences.read_prefs(preference_file))
+
         for v in options.extraPrefs:
             thispref = v.split('=')
             if len(thispref) < 2:
                 print "Error: syntax error in --setpref=" + v
                 sys.exit(1)
-            prefs[thispref[0]] = mozprofile.Preferences.cast(
-                thispref[1].strip())
+            prefs[thispref[0]] = thispref[1].strip()
 
-        # install the reftest extension bits into the profile
-        addons = [options.reftestExtensionPath]
+        addons = []
+        if not self.use_marionette:
+            addons.append(options.reftestExtensionPath)
 
         if options.specialPowersExtensionPath is not None:
-            addons.append(options.specialPowersExtensionPath)
+            if not self.use_marionette:
+                addons.append(options.specialPowersExtensionPath)
             # SpecialPowers requires insecure automation-only features that we
             # put behind a pref.
             prefs['security.turn_off_all_security_so_that_viruses_can_take_over_this_computer'] = True
 
+        for pref in prefs:
+            prefs[pref] = mozprofile.Preferences.cast(prefs[pref])
+
         # Install distributed extensions, if application has any.
         distExtDir = os.path.join(options.app[:options.app.rfind(os.sep)],
                                   "distribution", "extensions")
         if os.path.isdir(distExtDir):
             for f in os.listdir(distExtDir):
                 addons.append(os.path.join(distExtDir, f))
 
         # Install custom extensions.
@@ -400,33 +389,34 @@ class RefTest(object):
                                             processOutputLine=_psKill)
         process.run()
         process.wait()
 
     def cleanup(self, profileDir):
         if profileDir:
             shutil.rmtree(profileDir, True)
 
-    def runTests(self, tests, options, cmdlineArgs=None):
+    def runTests(self, tests, options, cmdargs=None):
+        cmdargs = cmdargs or []
         self._populate_logger(options)
 
         # Despite our efforts to clean up servers started by this script, in practice
         # we still see infrequent cases where a process is orphaned and interferes
         # with future tests, typically because the old server is keeping the port in use.
         # Try to avoid those failures by checking for and killing orphan servers before
         # trying to start new ones.
         self.killNamedOrphans('ssltunnel')
         self.killNamedOrphans('xpcshell')
 
         manifests = self.resolver.resolveManifests(options, tests)
         if options.filter:
             manifests[""] = options.filter
 
-        if not hasattr(options, "runTestsInParallel") or not options.runTestsInParallel:
-            return self.runSerialTests(manifests, options, cmdlineArgs)
+        if not getattr(options, 'runTestsInParallel', False):
+            return self.runSerialTests(manifests, options, cmdargs)
 
         cpuCount = multiprocessing.cpu_count()
 
         # We have the directive, technology, and machine to run multiple test instances.
         # Experimentation says that reftests are not overly CPU-intensive, so we can run
         # multiple jobs per CPU core.
         #
         # Our Windows machines in automation seem to get upset when we run a lot of
@@ -434,23 +424,30 @@ class RefTest(object):
         if sys.platform == 'win32':
             jobsWithoutFocus = cpuCount
         else:
             jobsWithoutFocus = 2 * cpuCount
 
         totalJobs = jobsWithoutFocus + 1
         perProcessArgs = [sys.argv[:] for i in range(0, totalJobs)]
 
+        host = 'localhost'
+        port = 2828
+        if options.marionette:
+            host, port = options.marionette.split(':')
+
         # First job is only needs-focus tests.  Remaining jobs are
         # non-needs-focus and chunked.
         perProcessArgs[0].insert(-1, "--focus-filter-mode=needs-focus")
         for (chunkNumber, jobArgs) in enumerate(perProcessArgs[1:], start=1):
             jobArgs[-1:-1] = ["--focus-filter-mode=non-needs-focus",
                               "--total-chunks=%d" % jobsWithoutFocus,
-                              "--this-chunk=%d" % chunkNumber]
+                              "--this-chunk=%d" % chunkNumber,
+                              "--marionette=%s:%d" % (host, port)]
+            port += 1
 
         for jobArgs in perProcessArgs:
             try:
                 jobArgs.remove("--run-tests-in-parallel")
             except:
                 pass
             jobArgs[0:0] = [sys.executable, "-u"]
 
@@ -593,16 +590,34 @@ class RefTest(object):
                             cmdargs=cmdargs,
                             env=env,
                             process_args=kp_kwargs)
         runner.start(debug_args=debug_args,
                      interactive=interactive,
                      outputTimeout=timeout)
         proc = runner.process_handler
 
+        if self.use_marionette:
+            marionette_args = { 'symbols_path': options.symbolsPath }
+            if options.marionette:
+                host, port = options.marionette.split(':')
+                marionette_args['host'] = host
+                marionette_args['port'] = int(port)
+
+            marionette = Marionette(**marionette_args)
+            marionette.start_session()
+
+            addons = Addons(marionette)
+            if options.specialPowersExtensionPath:
+                addons.install(options.specialPowersExtensionPath, temp=True)
+
+            addons.install(options.reftestExtensionPath, temp=True)
+
+            marionette.delete_session()
+
         status = runner.wait()
         runner.process_handler = None
 
         if status:
             msg = "TEST-UNEXPECTED-FAIL | %s | application terminated with exit code %s" % \
                 (self.lastTestSeen, status)
             # use process_output so message is logged verbatim
             self.log.process_output(None, msg)
@@ -612,35 +627,39 @@ class RefTest(object):
         crashed = mozcrash.log_crashes(self.log, os.path.join(profile.profile, 'minidumps'),
                                        symbolsPath, test=self.lastTestSeen)
 
         runner.cleanup()
         if not status and crashed:
             status = 1
         return status
 
-    def runSerialTests(self, manifests, options, cmdlineArgs=None):
+    def runSerialTests(self, manifests, options, cmdargs=None):
         debuggerInfo = None
         if options.debugger:
             debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs,
                                                       options.debuggerInteractive)
 
         profileDir = None
         try:
-            if cmdlineArgs is None:
-                cmdlineArgs = []
+            if cmdargs is None:
+                cmdargs = []
+
+            if self.use_marionette:
+                cmdargs.append('-marionette')
+
             profile = self.createReftestProfile(options, manifests)
             profileDir = profile.profile  # name makes more sense
 
             # browser environment
             browserEnv = self.buildBrowserEnv(options, profileDir)
 
             status = self.runApp(profile,
                                  binary=options.app,
-                                 cmdargs=cmdlineArgs,
+                                 cmdargs=cmdargs,
                                  # give the JS harness 30 seconds to deal with
                                  # its own timeouts
                                  env=browserEnv,
                                  timeout=options.timeout + 30.0,
                                  symbolsPath=options.symbolsPath,
                                  options=options,
                                  debuggerInfo=debuggerInfo)
             mozleak.process_leak_log(self.leakLogFile,
--- a/layout/tools/reftest/runreftestb2g.py
+++ b/layout/tools/reftest/runreftestb2g.py
@@ -47,16 +47,17 @@ class ProfileConfigParser(ConfigParser.R
                 if (value is not None) or (self._optcre == self.OPTCRE):
                     key = "=".join((key, str(value).replace('\n', '\n\t')))
                 fp.write("%s\n" % (key))
             fp.write("\n")
 
 class B2GRemoteReftest(RefTest):
 
     _devicemanager = None
+    use_marionette = False
     localProfile = None
     remoteApp = ''
     profile = None
     resolver_cls = RemoteReftestResolver
 
     def __init__(self, automation, devicemanager, options, scriptDir):
         RefTest.__init__(self)
         self.automation = automation
@@ -320,17 +321,17 @@ class B2GRemoteReftest(RefTest):
                                         debuggerInfo=debuggerInfo,
                                         symbolsPath=symbolsPath,
                                         timeout=timeout,
                                         outputHandler=outputHandler)
         return status
 
 
 def run_remote_reftests(parser, options):
-    auto = B2GRemoteAutomation(None, "fennec", context_chrome=True)
+    auto = B2GRemoteAutomation(None, "fennec")
 
     # create our Marionette instance
     kwargs = {}
     if options.emulator:
         kwargs['emulator'] = options.emulator
         auto.setEmulator(True)
         if options.noWindow:
             kwargs['noWindow'] = True
--- a/testing/mozharness/configs/android/android_panda_releng.py
+++ b/testing/mozharness/configs/android/android_panda_releng.py
@@ -88,17 +88,16 @@ config = {
         },
         "crashtest": {
             "options": [
                 "--deviceIP=%(device_ip)s",
                 "--xre-path=../hostutils/xre",
                 "--utility-path=../hostutils/bin",
                 "--app=%(app_name)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--symbols-path=%(symbols_path)s",
                 "--suite=crashtest",
             ],
             "tests": ["reftest/tests/testing/crashtest/crashtests.list",],
             "run_filename": "remotereftest.py",
             "testsdir": "reftest"
@@ -122,17 +121,16 @@ config = {
         },
         "jsreftest": {
             "options": [
                 "--deviceIP=%(device_ip)s",
                 "--xre-path=../hostutils/xre",
                 "--utility-path=../hostutils/bin",
                 "--app=%(app_name)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--extra-profile-file=jsreftest/tests/user.js",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--symbols-path=%(symbols_path)s",
                 "--suite=jstestbrowser",
             ],
             "tests": ["jsreftest/tests/jstests.list",],
             "run_filename": "remotereftest.py",
@@ -160,17 +158,16 @@ config = {
         },
         "reftest": {
             "options": [
                 "--deviceIP=%(device_ip)s",
                 "--xre-path=../hostutils/xre",
                 "--utility-path=../hostutils/bin",
                 "--app=%(app_name)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--symbols-path=%(symbols_path)s",
                 "--extra-profile-file=reftest/fonts",
                 "--suite=reftest",
                 "--log-raw=%(raw_log_file)s",
                 "--log-errorsummary=%(error_summary_file)s",
             ],
--- a/testing/mozharness/configs/android/androidarm.py
+++ b/testing/mozharness/configs/android/androidarm.py
@@ -124,17 +124,16 @@ config = {
             ],
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--deviceIP=%(device_ip)s",
                 "--devicePort=%(device_port)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
@@ -149,17 +148,16 @@ config = {
             "tests": ["tests/layout/reftests/reftest.list"],
         },
         "crashtest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--deviceIP=%(device_ip)s",
                 "--devicePort=%(device_port)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
@@ -171,17 +169,16 @@ config = {
             "tests": ["tests/testing/crashtest/crashtests.list"],
         },
         "jsreftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--deviceIP=%(device_ip)s",
                 "--devicePort=%(device_port)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
--- a/testing/mozharness/configs/android/androidarm_4_3.py
+++ b/testing/mozharness/configs/android/androidarm_4_3.py
@@ -125,17 +125,16 @@ config = {
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "--total-chunks=16",
@@ -148,17 +147,16 @@ config = {
         },
         "reftest-debug": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "--total-chunks=48",
@@ -168,17 +166,16 @@ config = {
         },
         "crashtest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
                 "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
@@ -189,17 +186,16 @@ config = {
         },
         "crashtest-debug": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
                 "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
@@ -209,17 +205,16 @@ config = {
         },
         "jsreftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "--total-chunks=6",
                 "--extra-profile-file=jsreftest/tests/user.js",
                 "--suite=jstestbrowser",
             ],
@@ -227,17 +222,16 @@ config = {
         },
         "jsreftest-debug": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "../jsreftest/tests/jstests.list",
                 "--total-chunks=20",
                 "--extra-profile-file=jsreftest/tests/user.js",
             ],
--- a/testing/mozharness/configs/android/androidx86.py
+++ b/testing/mozharness/configs/android/androidx86.py
@@ -87,17 +87,16 @@ config = {
                         "--log-errorsummary=%(error_summary_file)s",
                         "--screenshot-on-fail",
                     ],
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "options": ["--app=%(app)s",
                         "--ignore-window-size",
-                        "--bootstrap",
                         "--remote-webserver=%(remote_webserver)s",
                         "--xre-path=%(xre_path)s",
                         "--utility-path=%(utility_path)s",
                         "--http-port=%(http_port)s",
                         "--ssl-port=%(ssl_port)s",
                         "--httpd-path", "%(modules_dir)s",
                         "--symbols-path=%(symbols_path)s",
                     ],