Backout cc15c275b1e3 (Bug 1149618) on a CLOSED TREE for suspected debug emulator bustage, a=bustage
authorJonathan Griffin <jgriffin@mozilla.com>
Tue, 19 May 2015 19:35:38 -0700
changeset 244605 1e983ca9801fdb719e5e6a3a3868befa858af183
parent 244604 3950e0f5253283f22b60b1925cd6fc322835b443
child 244606 446ce38d00050fca97b8b10a6073a01d751de346
push id59996
push userjgriffin@mozilla.com
push dateWed, 20 May 2015 02:36:36 +0000
treeherdermozilla-inbound@1e983ca9801f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbustage
bugs1149618
milestone41.0a1
backs outcc15c275b1e35c67d7cfc1afd7323fd9cf8aa0ac
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
Backout cc15c275b1e3 (Bug 1149618) on a CLOSED TREE for suspected debug emulator bustage, a=bustage
build/mobile/b2gautomation.py
dom/system/gonk/tests/marionette/test_ril_code_quality.py
testing/marionette/client/marionette/b2g_update_test.py
testing/marionette/client/marionette/marionette_test.py
testing/marionette/client/marionette/tests/unit/test_getactiveframe_oop.py
testing/marionette/client/marionette/tests/unit/test_import_script.py
testing/marionette/client/marionette/tests/unit/test_profile_management.py
testing/marionette/client/marionette/tests/unit/test_specialpowers.py
testing/marionette/client/marionette/tests/unit/test_switch_remote_frame.py
testing/marionette/client/marionette/tests/unit/unit-tests.ini
testing/marionette/driver.js
testing/marionette/driver/marionette_driver/marionette.py
testing/marionette/driver/marionette_driver/selection.py
testing/marionette/frame-manager.js
testing/marionette/listener.js
testing/marionette/server.js
testing/mochitest/b2g_start_script.js
testing/mochitest/runtestsb2g.py
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -271,34 +271,19 @@ 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);
-
-            if (!testUtils.hasOwnProperty("specialPowersObserver")) {
-              let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
-                .getService(Components.interfaces.mozIJSSubScriptLoader);
-              loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js",
-                testUtils);
-              testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
-              testUtils.specialPowersObserver.init();
-              testUtils.specialPowersObserver._loadFrameScript();
-            }
-            """)
-
-        if not self.context_chrome:
+        if self.context_chrome:
+            self.marionette.set_context(self.marionette.CONTEXT_CHROME)
+        else:
             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()
--- a/dom/system/gonk/tests/marionette/test_ril_code_quality.py
+++ b/dom/system/gonk/tests/marionette/test_ril_code_quality.py
@@ -104,18 +104,18 @@ class ResourceUriFileReader:
         'RadioInterfaceLayer.js': 'components/RadioInterfaceLayer.js',
         'ril_worker.js':          'modules/ril_worker.js',
         'ril_consts.js':          'modules/ril_consts.js',
         'systemlibs.js':          'modules/systemlibs.js',
         'worker_buf.js':          'modules/workers/worker_buf.js',
     }
 
     CODE_OPEN_CHANNEL_BY_URI = '''
-    var Cc = Components.classes;
-    var Ci = Components.interfaces;
+    var Cc = SpecialPowers.Cc;
+    var Ci = SpecialPowers.Ci;
     var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
     var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
     global.uri = '%(uri)s';
     global.channel = ios.newChannel2(global.uri,
                                      null,
                                      null,
                                      null,      // aLoadingNode
                                      secMan.getSystemPrincipal(),
@@ -124,18 +124,18 @@ class ResourceUriFileReader:
                                      Ci.nsIContentPolicy.TYPE_OTHER);
     '''
 
     CODE_GET_SPEC = '''
     return global.channel.URI.spec;
     '''
 
     CODE_READ_CONTENT = '''
-    var Cc = Components.classes;
-    var Ci = Components.interfaces;
+    var Cc = SpecialPowers.Cc;
+    var Ci = SpecialPowers.Ci;
 
     var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
     var inputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
 
     var jaruri = global.channel.URI.QueryInterface(Ci.nsIJARURI);
     var file = jaruri.JARFile.QueryInterface(Ci.nsIFileURL).file;
     var entry = jaruri.JAREntry;
     zipReader.open(file);
@@ -150,19 +150,17 @@ class ResourceUriFileReader:
     def get_uri(cls, filename):
         """Convert filename to URI in system."""
         if filename.startswith(cls.URI_PREFIX):
             return filename
         else:
             return cls.URI_PREFIX + cls.URI_PATH[filename]
 
     def __init__(self, marionette):
-        self.runjs = lambda x: marionette.execute_script(x,
-                                                         new_sandbox=False,
-                                                         sandbox='system')
+        self.runjs = lambda x: marionette.execute_script(x, new_sandbox=False)
 
     def read_file(self, filename):
         """Read file and return the contents as string."""
         content = self._read_uri(self.get_uri(filename))
         content = content.replace('"use strict";', '')
         return StringUtility.remove_non_ascii(content)
 
     def _read_uri(self, uri):
@@ -207,19 +205,17 @@ class JSHintEngine:
     '''
 
     def __init__(self, marionette, script, config):
         # Remove single line comment in config.
         config = '\n'.join([line.partition('//')[0]
                             for line in config.splitlines()])
 
         # Set global (JSHINT, options, global) in js environment.
-        self.runjs = lambda x: marionette.execute_script(x,
-                                                         new_sandbox=False,
-                                                         sandbox='system')
+        self.runjs = lambda x: marionette.execute_script(x, new_sandbox=False)
         self.runjs(self.CODE_INIT_JSHINT %
                    {'script': script, 'config_string': repr(config)})
 
     def run(self, code, filename=''):
         """Excute JShint check for the given code."""
         check_pass = self.runjs(self.CODE_RUN_JSHINT % {'code': repr(code)})
         errors = self.runjs(self.CODE_GET_JSHINT_ERROR)
         return check_pass, self._get_error_messages(errors, filename)
--- a/testing/marionette/client/marionette/b2g_update_test.py
+++ b/testing/marionette/client/marionette/b2g_update_test.py
@@ -233,17 +233,18 @@ class B2GUpdateTestCase(MarionetteTestCa
         status = 'EXEC'
         if stage:
             status += '-' + stage.upper()
             data += '\nrunUpdateTest("%s");' % stage
 
         self.print_status(status, os.path.basename(path))
 
         results = self.marionette.execute_async_script(data,
-                                                       script_args=[self.testvars])
+                                                       script_args=[self.testvars],
+                                                       special_powers=True)
         self.handle_results(path, stage, results)
 
     def handle_results(self, path, stage, results):
         passed = results['passed']
         failed = results['failed']
 
         fails = StringIO()
         stage_msg = ' %s' % stage if stage else ''
--- a/testing/marionette/client/marionette/marionette_test.py
+++ b/testing/marionette/client/marionette/marionette_test.py
@@ -497,34 +497,16 @@ setReq.onerror = function() {
         if not result:
             raise Exception('Failed to close Test Container app')
 
         Wait(self.marionette, timeout=10, interval=0.2).until(element_not_present(
             'css selector',
             'iframe[src*="app://test-container.gaiamobile.org/index.html"]'
         ))
 
-    def setup_SpecialPowers_observer(self):
-        self.marionette.set_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.js",
-                testUtils);
-              testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
-              testUtils.specialPowersObserver.init();
-              testUtils.specialPowersObserver._loadFrameScript();
-            }
-            """)
-
     def run_js_test(self, filename, marionette=None):
         '''
         Run a JavaScript test file and collect its set of assertions
         into the current test's results.
 
         :param filename: The path to the JavaScript test file to execute.
                          May be relative to the current script.
         :param marionette: The Marionette object in which to execute the test.
@@ -550,33 +532,16 @@ setReq.onerror = function() {
             head = open(os.path.join(os.path.dirname(filename), head_js), 'r')
             js = head.read() + js;
 
         context = JSTest.context_re.search(js)
         if context:
             context = context.group(3)
         else:
             context = 'content'
-
-        if 'SpecialPowers' in js:
-            self.setup_SpecialPowers_observer()
-
-            if context == 'content':
-                js = "var SpecialPowers = window.wrappedJSObject.SpecialPowers;\n" + js
-            else:
-                marionette.execute_script("""
-                if (typeof(SpecialPowers) == 'undefined') {
-                  let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
-                    .getService(Components.interfaces.mozIJSSubScriptLoader);
-                  loader.loadSubScript("chrome://specialpowers/content/specialpowersAPI.js");
-                  loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js");
-                  loader.loadSubScript("chrome://specialpowers/content/ChromePowers.js");
-                }
-                """)
-
         marionette.set_context(context)
 
         if context != 'chrome':
             marionette.navigate('data:text/html,<html>test page</html>')
 
         timeout = JSTest.timeout_re.search(js)
         if timeout:
             timeout = timeout.group(3)
@@ -585,16 +550,17 @@ setReq.onerror = function() {
         inactivity_timeout = JSTest.inactivity_timeout_re.search(js)
         if inactivity_timeout:
             inactivity_timeout = inactivity_timeout.group(3)
 
         try:
             results = marionette.execute_js_script(
                 js,
                 args,
+                special_powers=True,
                 inactivity_timeout=inactivity_timeout,
                 filename=os.path.basename(filename)
             )
 
             self.assertTrue(not 'timeout' in filename,
                             'expected timeout not triggered')
 
             if 'fail' in filename:
--- a/testing/marionette/client/marionette/tests/unit/test_getactiveframe_oop.py
+++ b/testing/marionette/client/marionette/tests/unit/test_getactiveframe_oop.py
@@ -1,86 +1,82 @@
 # 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/.
 
 from marionette import MarionetteTestCase
-from marionette_driver.by import By
 
 
 class TestGetActiveFrameOOP(MarionetteTestCase):
     def setUp(self):
         super(TestGetActiveFrameOOP, self).setUp()
-        with self.marionette.using_context('chrome'):
-            self.oop_by_default = self.marionette.execute_script("""
-                try {
-                  return Services.prefs.getBoolPref('dom.ipc.browser_frames.oop_by_default');
-                }
-                catch(e) {}
-                """)
-            self.mozBrowserFramesEnabled = self.marionette.execute_script("""
-                try {
-                  return Services.prefs.getBoolPref('dom.mozBrowserFramesEnabled');
-                }
-                catch(e) {}
-                """)
-            self.marionette.execute_script("""
-                Services.prefs.setBoolPref('dom.ipc.browser_frames.oop_by_default', true);
-                """)
-            self.marionette.execute_script("""
-                Services.prefs.setBoolPref('dom.mozBrowserFramesEnabled', true);
-                """)
+        self.oop_by_default = self.marionette.execute_script("""
+            try {
+              return SpecialPowers.getBoolPref('dom.ipc.browser_frames.oop_by_default');
+            }
+            catch(e) {}
+            """)
+        self.mozBrowserFramesEnabled = self.marionette.execute_script("""
+            try {
+              return SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
+            }
+            catch(e) {}
+            """)
+        self.marionette.execute_script("""
+            SpecialPowers.setBoolPref('dom.ipc.browser_frames.oop_by_default', true);
+            """)
+        self.marionette.execute_script("""
+            SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
+            """)
 
     def test_active_frame_oop(self):
         self.marionette.navigate(self.marionette.absolute_url("test.html"))
         self.marionette.push_permission('browser', True)
 
         # Create first OOP frame
         self.marionette.execute_script("""
             let iframe1 = document.createElement("iframe");
+            SpecialPowers.wrap(iframe1).mozbrowser = true;
+            SpecialPowers.wrap(iframe1).remote = true;
             iframe1.id = "remote_iframe1";
-            iframe1.setAttribute('remote', true);
-            iframe1.setAttribute('mozbrowser', true);
             iframe1.style.height = "100px";
             iframe1.style.width = "100%%";
             iframe1.src = "%s";
             document.body.appendChild(iframe1);
             """ % self.marionette.absolute_url("test_oop_1.html"))
 
         # Currently no active frame
         self.assertEqual(self.marionette.get_active_frame(), None)
         self.assertTrue("test.html" in self.marionette.get_url())
 
         # Switch to iframe1, get active frame
-        frame = self.marionette.find_element(By.ID, 'remote_iframe1')
-        self.marionette.switch_to_frame(frame)
+        self.marionette.switch_to_frame('remote_iframe1')
         active_frame1 = self.marionette.get_active_frame()
         self.assertNotEqual(active_frame1.id, None)
 
         # Switch to top-level then back to active frame, verify correct frame
         self.marionette.switch_to_frame()
         self.marionette.switch_to_frame(active_frame1)
         self.assertTrue("test_oop_1.html" in self.marionette.execute_script("return document.wrappedJSObject.location.href"))
 
         # Create another OOP frame
         self.marionette.switch_to_frame()
         self.marionette.execute_script("""
             let iframe2 = document.createElement("iframe");
-            iframe2.setAttribute('mozbrowser', true);
-            iframe2.setAttribute('remote', true);
+            SpecialPowers.wrap(iframe2).mozbrowser = true;
+            SpecialPowers.wrap(iframe2).remote = true;
             iframe2.id = "remote_iframe2";
             iframe2.style.height = "100px";
             iframe2.style.width = "100%%";
             iframe2.src = "%s";
             document.body.appendChild(iframe2);
             """ % self.marionette.absolute_url("test_oop_2.html"))
 
         # Switch to iframe2, get active frame
-        frame2 = self.marionette.find_element(By.ID, 'remote_iframe2')
-        self.marionette.switch_to_frame(frame2)
+        self.marionette.switch_to_frame('remote_iframe2')
         active_frame2 = self.marionette.get_active_frame()
         self.assertNotEqual(active_frame2.id, None)
 
         # Switch to top-level then back to active frame 1, verify correct frame
         self.marionette.switch_to_frame()
         self.marionette.switch_to_frame(active_frame1)
         self.assertTrue("test_oop_1.html" in self.marionette.execute_script("return document.wrappedJSObject.location.href"))
 
@@ -91,25 +87,24 @@ class TestGetActiveFrameOOP(MarionetteTe
 
         # NOTE: For some reason the emulator, the contents of the OOP iframes are not
         # actually rendered, even though the page_source is correct. When this test runs
         # on a b2g device, the contents do appear
         # print self.marionette.get_url()
         # print self.marionette.page_source
 
     def tearDown(self):
-        with self.marionette.using_context('chrome'):
-            if self.oop_by_default is None:
-                self.marionette.execute_script("""
-                    Services.prefs.clearUserPref('dom.ipc.browser_frames.oop_by_default');
-                    """)
-            else:
-                self.marionette.execute_script("""
-                    Services.prefs.setBoolPref('dom.ipc.browser_frames.oop_by_default', %s);
-                    """ % 'true' if self.oop_by_default else 'false')
-            if self.mozBrowserFramesEnabled is None:
-                self.marionette.execute_script("""
-                    Services.prefs.clearUserPref('dom.mozBrowserFramesEnabled');
-                    """)
-            else:
-                self.marionette.execute_script("""
-                    Services.prefs.setBoolPref('dom.mozBrowserFramesEnabled', %s);
-                    """ % 'true' if self.mozBrowserFramesEnabled else 'false')
+        if self.oop_by_default is None:
+            self.marionette.execute_script("""
+                SpecialPowers.clearUserPref('dom.ipc.browser_frames.oop_by_default');
+                """)
+        else:
+            self.marionette.execute_script("""
+                SpecialPowers.setBoolPref('dom.ipc.browser_frames.oop_by_default', %s);
+                """ % 'true' if self.oop_by_default else 'false')
+        if self.mozBrowserFramesEnabled is None:
+            self.marionette.execute_script("""
+                SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
+                """)
+        else:
+            self.marionette.execute_script("""
+                SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', %s);
+                """ % 'true' if self.mozBrowserFramesEnabled else 'false')
--- a/testing/marionette/client/marionette/tests/unit/test_import_script.py
+++ b/testing/marionette/client/marionette/tests/unit/test_import_script.py
@@ -12,27 +12,27 @@ class TestImportScript(MarionetteTestCas
 
     def clear_other_context(self):
         self.marionette.set_context("chrome")
         self.marionette.clear_imported_scripts()
         self.marionette.set_context("content")
 
     def check_file_exists(self):
         return self.marionette.execute_script("""
-          let FileUtils = Components.utils.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+          let FileUtils = SpecialPowers.Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
           let importedScripts = FileUtils.getFile('TmpD', ['marionetteContentScripts']);
           return importedScripts.exists();
-        """, sandbox='system')
+        """, special_powers=True)
 
     def get_file_size(self):
         return self.marionette.execute_script("""
-          let FileUtils = Components.utils.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+          let FileUtils = SpecialPowers.Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
           let importedScripts = FileUtils.getFile('TmpD', ['marionetteContentScripts']);
           return importedScripts.fileSize;
-        """, sandbox='system')
+        """, special_powers=True)
 
     def test_import_script(self):
         js = os.path.abspath(os.path.join(__file__, os.path.pardir, "importscript.js"))
         self.marionette.import_script(js)
         self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
         self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
 
     def test_import_script_twice(self):
--- a/testing/marionette/client/marionette/tests/unit/test_profile_management.py
+++ b/testing/marionette/client/marionette/tests/unit/test_profile_management.py
@@ -5,59 +5,54 @@
 import os
 from marionette_driver.errors import JavascriptException
 from marionette import MarionetteTestCase
 
 class TestLog(MarionetteTestCase):
     def setUp(self):
         MarionetteTestCase.setUp(self)
         self.marionette.enforce_gecko_prefs({"marionette.test.bool": True, "marionette.test.string": "testing", "marionette.test.int": 3})
-        self.marionette.set_context('chrome')
 
     def test_preferences_are_set(self):
-        bool_value = self.marionette.execute_script("return Services.prefs.getBoolPref('marionette.test.bool');")
-        string_value = self.marionette.execute_script("return Services.prefs.getCharPref('marionette.test.string');")
-        int_value = self.marionette.execute_script("return Services.prefs.getIntPref('marionette.test.int');")
+        bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")
+        string_value = self.marionette.execute_script("return SpecialPowers.getCharPref('marionette.test.string');")
+        int_value = self.marionette.execute_script("return SpecialPowers.getIntPref('marionette.test.int');")
         self.assertTrue(bool_value)
         self.assertEqual(string_value, "testing")
         self.assertEqual(int_value, 3)
 
     def test_change_preset(self):
-        bool_value = self.marionette.execute_script("return Services.prefs.getBoolPref('marionette.test.bool');")
+        bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")
         self.assertTrue(bool_value)
         self.marionette.enforce_gecko_prefs({"marionette.test.bool": False})
-        self.marionette.set_context('chrome')
-        bool_value = self.marionette.execute_script("return Services.prefs.getBoolPref('marionette.test.bool');")
+        bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")
         self.assertFalse(bool_value)
 
     def test_clean_profile(self):
         self.marionette.restart(clean=True)
-        self.marionette.set_context('chrome')
-        with self.assertRaisesRegexp(JavascriptException, "NS_ERROR_UNEXPECTED"):
-            bool_value = self.marionette.execute_script("return Services.prefs.getBoolPref('marionette.test.bool');")
+        with self.assertRaisesRegexp(JavascriptException, "Error getting pref"):
+            bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")
 
     def test_can_restart_the_browser(self):
         self.marionette.enforce_gecko_prefs({"marionette.test.restart": True})
         self.marionette.restart()
-        self.marionette.set_context('chrome')
-        bool_value = self.marionette.execute_script("return Services.prefs.getBoolPref('marionette.test.restart');")
+        bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.restart');")
         self.assertTrue(bool_value)
 
     def test_in_app_restart_the_browser(self):
-        self.marionette.execute_script("Services.prefs.setBoolPref('marionette.test.restart', true);")
+        self.marionette.execute_script("SpecialPowers.setBoolPref('marionette.test.restart', true);")
 
         # A "soft" restart initiated inside the application should keep track of this pref.
         self.marionette.restart(in_app=True)
-        self.marionette.set_context('chrome')
         bool_value = self.marionette.execute_script("""
-          return Services.prefs.getBoolPref('marionette.test.restart');
+          return SpecialPowers.getBoolPref('marionette.test.restart');
         """)
         self.assertTrue(bool_value)
 
         bool_value = self.marionette.execute_script("""
-          Services.prefs.setBoolPref('marionette.test.restart', false);
-          return Services.prefs.getBoolPref('marionette.test.restart');
+          SpecialPowers.setBoolPref('marionette.test.restart', false);
+          return SpecialPowers.getBoolPref('marionette.test.restart');
         """)
         self.assertFalse(bool_value)
 
         # A "hard" restart is still possible (i.e., our instance is still able
         # to kill the browser).
         self.marionette.restart()
new file mode 100644
--- /dev/null
+++ b/testing/marionette/client/marionette/tests/unit/test_specialpowers.py
@@ -0,0 +1,35 @@
+# 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/.
+
+from marionette import MarionetteTestCase
+
+
+class TestSpecialPowersContent(MarionetteTestCase):
+
+    testpref = "testing.marionette.contentcharpref"
+    testvalue = "blabla"
+
+    def test_prefs(self):
+        result = self.marionette.execute_script("""
+        SpecialPowers.setCharPref("%(pref)s", "%(value)s");
+        return SpecialPowers.getCharPref("%(pref)s")
+        """ % {'pref': self.testpref, 'value': self.testvalue}, special_powers=True);
+        self.assertEqual(result, self.testvalue)
+
+    def test_prefs_after_navigate(self):
+        test_html = self.marionette.absolute_url("test.html")
+        self.marionette.navigate(test_html)
+        self.test_prefs()
+
+class TestSpecialPowersChrome(TestSpecialPowersContent):
+
+    testpref = "testing.marionette.chromecharpref"
+    testvalue = "blabla"
+
+    def setUp(self):
+        super(TestSpecialPowersChrome, self).setUp()
+        self.marionette.set_context("chrome")
+
+    def test_prefs_after_navigate(self):
+        pass
--- a/testing/marionette/client/marionette/tests/unit/test_switch_remote_frame.py
+++ b/testing/marionette/client/marionette/tests/unit/test_switch_remote_frame.py
@@ -3,128 +3,132 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from marionette import MarionetteTestCase
 
 
 class TestSwitchRemoteFrame(MarionetteTestCase):
     def setUp(self):
         super(TestSwitchRemoteFrame, self).setUp()
+        self.oop_by_default = self.marionette.execute_script("""
+            try {
+              return SpecialPowers.getBoolPref('dom.ipc.browser_frames.oop_by_default');
+            }
+            catch(e) {}
+            """)
+        self.mozBrowserFramesEnabled = self.marionette.execute_script("""
+            try {
+              return SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
+            }
+            catch(e) {}
+            """)
+        self.marionette.execute_async_script(
+            'SpecialPowers.pushPrefEnv({"set": [["dom.ipc.browser_frames.oop_by_default", true], ["dom.mozBrowserFramesEnabled", true]]}, marionetteScriptFinished);')
+
         with self.marionette.using_context('chrome'):
-            self.oop_by_default = self.marionette.execute_script("""
-                try {
-                  return Services.prefs.getBoolPref('dom.ipc.browser_frames.oop_by_default');
-                }
-                catch(e) {}
-                """)
-            self.mozBrowserFramesEnabled = self.marionette.execute_script("""
-                try {
-                  return Services.prefs.getBoolPref('dom.mozBrowserFramesEnabled');
-                }
-                catch(e) {}
-                """)
-            self.marionette.execute_script("""
-                Services.prefs.setBoolPref("dom.ipc.browser_frames.oop_by_default", true);
-                Services.prefs.setBoolPref("dom.mozBrowserFramesEnabled", true);
-                """)
-
             self.multi_process_browser = self.marionette.execute_script("""
                 try {
                   return Services.appinfo.browserTabsRemoteAutostart;
                 } catch (e) {
                   return false;
                 }""")
 
-    def is_main_process(self):
-        return self.marionette.execute_script("""
-            return Components.classes["@mozilla.org/xre/app-info;1"].
-                getService(Components.interfaces.nsIXULRuntime).
-                processType == Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-        """, sandbox='system')
-
     def test_remote_frame(self):
         self.marionette.navigate(self.marionette.absolute_url("test.html"))
         self.marionette.push_permission('browser', True)
         self.marionette.execute_script("""
             let iframe = document.createElement("iframe");
-            iframe.setAttribute('mozbrowser', true);
-            iframe.setAttribute('remote', true);
+            SpecialPowers.wrap(iframe).mozbrowser = true;
+            SpecialPowers.wrap(iframe).remote = true;
             iframe.id = "remote_iframe";
             iframe.style.height = "100px";
             iframe.style.width = "100%%";
             iframe.src = "%s";
             document.body.appendChild(iframe);
             """ % self.marionette.absolute_url("test.html"))
         remote_iframe = self.marionette.find_element("id", "remote_iframe")
         self.marionette.switch_to_frame(remote_iframe)
-        main_process = self.is_main_process()
+        main_process = self.marionette.execute_script("""
+            return SpecialPowers.isMainProcess();
+            """)
         self.assertFalse(main_process)
 
     def test_remote_frame_revisit(self):
         # test if we can revisit a remote frame (this takes a different codepath)
         self.marionette.navigate(self.marionette.absolute_url("test.html"))
         self.marionette.push_permission('browser', True)
         self.marionette.execute_script("""
             let iframe = document.createElement("iframe");
-            iframe.setAttribute('mozbrowser', true);
-            iframe.setAttribute('remote', true);
+            SpecialPowers.wrap(iframe).mozbrowser = true;
+            SpecialPowers.wrap(iframe).remote = true;
             iframe.id = "remote_iframe";
             iframe.style.height = "100px";
             iframe.style.width = "100%%";
             iframe.src = "%s";
             document.body.appendChild(iframe);
             """ % self.marionette.absolute_url("test.html"))
         self.marionette.switch_to_frame(self.marionette.find_element("id",
                                                                      "remote_iframe"))
-        main_process = self.is_main_process()
+        main_process = self.marionette.execute_script("""
+            return SpecialPowers.isMainProcess();
+            """)
         self.assertFalse(main_process)
         self.marionette.switch_to_frame()
-        main_process = self.is_main_process()
+        main_process = self.marionette.execute_script("""
+            return SpecialPowers.isMainProcess();
+            """)
         should_be_main_process = not self.multi_process_browser
         self.assertEqual(main_process, should_be_main_process)
         self.marionette.switch_to_frame(self.marionette.find_element("id",
                                                                      "remote_iframe"))
-        main_process = self.is_main_process()
+        main_process = self.marionette.execute_script("""
+            return SpecialPowers.isMainProcess();
+            """)
         self.assertFalse(main_process)
 
     def test_we_can_switch_to_a_remote_frame_by_index(self):
         # test if we can revisit a remote frame (this takes a different codepath)
         self.marionette.navigate(self.marionette.absolute_url("test.html"))
         self.marionette.push_permission('browser', True)
         self.marionette.execute_script("""
             let iframe = document.createElement("iframe");
-            iframe.setAttribute('mozbrowser', true);
-            iframe.setAttribute('remote', true);
+            SpecialPowers.wrap(iframe).mozbrowser = true;
+            SpecialPowers.wrap(iframe).remote = true;
             iframe.id = "remote_iframe";
             iframe.style.height = "100px";
             iframe.style.width = "100%%";
             iframe.src = "%s";
             document.body.appendChild(iframe);
             """ % self.marionette.absolute_url("test.html"))
         self.marionette.switch_to_frame(0)
-        main_process = self.is_main_process()
+        main_process = self.marionette.execute_script("""
+            return SpecialPowers.isMainProcess();
+            """)
         self.assertFalse(main_process)
         self.marionette.switch_to_frame()
-        main_process = self.is_main_process()
+        main_process = self.marionette.execute_script("""
+            return SpecialPowers.isMainProcess();
+            """)
         should_be_main_process = not self.multi_process_browser
         self.assertEqual(main_process, should_be_main_process)
         self.marionette.switch_to_frame(0)
-        main_process = self.is_main_process()
+        main_process = self.marionette.execute_script("""
+            return SpecialPowers.isMainProcess();
+            """)
         self.assertFalse(main_process)
 
     def tearDown(self):
-        with self.marionette.using_context('chrome'):
-            if self.oop_by_default is None:
-                self.marionette.execute_script("""
-                    Services.prefs.clearUserPref('dom.ipc.browser_frames.oop_by_default');
-                    """)
-            else:
-                self.marionette.execute_async_script(
-                    "Services.prefs.setBoolPref('dom.ipc.browser_frames.oop_by_default', %s);" %
-                    ('true' if self.oop_by_default else 'false'))
-            if self.mozBrowserFramesEnabled is None:
-                self.marionette.execute_script("""
-                    Services.prefs.clearUserPref('dom.mozBrowserFramesEnabled');
-                    """)
-            else:
-                self.marionette.execute_async_script(
-                    "Services.prefs.setBoolPref('dom.mozBrowserFramesEnabled', %s);" %
-                    ('true' if self.mozBrowserFramesEnabled else 'false'))
+        if self.oop_by_default is None:
+            self.marionette.execute_script("""
+                SpecialPowers.clearUserPref('dom.ipc.browser_frames.oop_by_default');
+                """)
+        else:
+             self.marionette.execute_async_script(
+            'SpecialPowers.pushPrefEnv({"set": [["dom.ipc.browser_frames.oop_by_default", %s]]}, marionetteScriptFinished);' %
+            ('true' if self.oop_by_default else 'false'))
+        if self.mozBrowserFramesEnabled is None:
+            self.marionette.execute_script("""
+                SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
+                """)
+        else:
+            self.marionette.execute_async_script(
+            'SpecialPowers.pushPrefEnv({"set": [["dom.mozBrowserFramesEnabled", %s]]}, marionetteScriptFinished);' %
+            ('true' if self.mozBrowserFramesEnabled else 'false'))
--- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini
@@ -89,16 +89,17 @@ skip-if = os == "win" # Bug 1025040
 disabled = "Bug 1060060"
 b2g = true
 browser = false
 
 [test_simpletest_pass.js]
 [test_simpletest_sanity.py]
 [test_simpletest_chrome.js]
 [test_simpletest_timeout.js]
+[test_specialpowers.py]
 [test_anonymous_content.py]
 b2g = false
 [test_switch_frame.py]
 b2g = false
 skip-if = os == "win" # Bug 1078237
 [test_switch_frame_chrome.py]
 b2g = false
 [test_switch_remote_frame.py]
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -40,23 +40,25 @@ loader.loadSubScript("chrome://marionett
 loader.loadSubScript("chrome://marionette/content/sendkeys.js", utils);
 loader.loadSubScript("chrome://marionette/content/frame-manager.js");
 
 this.EXPORTED_SYMBOLS = ["GeckoDriver", "Context"];
 
 const FRAME_SCRIPT = "chrome://marionette/content/listener.js";
 const BROWSER_STARTUP_FINISHED = "browser-delayed-startup-finished";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+const SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
 const CLICK_TO_START_PREF = "marionette.debugging.clicktostart";
 const CONTENT_LISTENER_PREF = "marionette.contentListener";
 
 const logger = Log.repository.getLogger("Marionette");
 const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
 const globalMessageManager = Cc["@mozilla.org/globalmessagemanager;1"]
     .getService(Ci.nsIMessageBroadcaster);
+let specialpowers = {};
 
 // This is used to prevent newSession from returning before the telephony
 // API's are ready; see bug 792647.  This assumes that marionette-server.js
 // will be loaded before the 'system-message-listener-ready' message
 // is fired.  If this stops being true, this approach will have to change.
 let systemMessageListenerReady = false;
 Services.obs.addObserver(function() {
   systemMessageListenerReady = true;
@@ -123,16 +125,17 @@ this.GeckoDriver = function(appName, dev
   this.mainContentFrameId = null;
   this.importedScripts = FileUtils.getFile("TmpD", ["marionetteChromeScripts"]);
   this.importedScriptHashes = {};
   this.importedScriptHashes[Context.CONTENT] = [];
   this.importedScriptHashes[Context.CHROME] = [];
   this.currentFrameElement = null;
   this.testName = null;
   this.mozBrowserClose = null;
+  this.enabled_security_pref = false;
   this.sandboxes = {};
   // frame ID of the current remote frame, used for mozbrowserclose events
   this.oopFrameId = null;
   this.observing = null;
   this._browserIds = new WeakMap();
   this.actions = new ActionChain(utils);
 
   this.sessionCapabilities = {
@@ -502,16 +505,35 @@ GeckoDriver.prototype.newSession = funct
   this.sessionId = cmd.parameters.sessionId ||
       cmd.parameters.session_id ||
       uuidGen.generateUUID().toString();
 
   this.newSessionCommandId = cmd.id;
   this.setSessionCapabilities(cmd.parameters.capabilities);
   this.scriptTimeout = 10000;
 
+  // SpecialPowers requires insecure automation-only features that we
+  // put behind a pref
+  let sec = false;
+  try {
+    sec = Services.prefs.getBoolPref(SECURITY_PREF);
+  } catch (e) {}
+  if (!sec) {
+    this.enabled_security_pref = true;
+    Services.prefs.setBoolPref(SECURITY_PREF, true);
+  }
+
+  if (!specialpowers.hasOwnProperty("specialPowersObserver")) {
+    loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js",
+        specialpowers);
+    specialpowers.specialPowersObserver = new specialpowers.SpecialPowersObserver();
+    specialpowers.specialPowersObserver.init();
+    specialpowers.specialPowersObserver._loadFrameScript();
+  }
+
   let registerBrowsers = this.registerPromise();
   let browserListening = this.listeningPromise();
 
   let waitForWindow = function() {
     let win = this.getCurrentWindow();
     if (!win) {
       // if the window isn't even created, just poll wait for it
       let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
@@ -678,24 +700,25 @@ GeckoDriver.prototype.getContext = funct
 /**
  * Returns a chrome sandbox that can be used by the execute and
  * executeWithCallback functions.
  *
  * @param {nsIDOMWindow} win
  *     Window in which we will execute code.
  * @param {Marionette} mn
  *     Marionette test instance.
- * @param {string} sandboxName
- *     The name for the sandbox.  If 'system', create the sandbox
- *     with elevated privileges.
+ * @param {Object} args
+ *     Arguments given by client.
+ * @param {boolean} sp
+ *     True to enable special powers in the sandbox, false not to.
  *
  * @return {nsIXPCComponents_utils_Sandbox}
  *     Returns the sandbox.
  */
-GeckoDriver.prototype.createExecuteSandbox = function(win, mn, sandboxName) {
+GeckoDriver.prototype.createExecuteSandbox = function(win, mn, sp, sandboxName) {
   let principal = win;
   if (sandboxName == 'system') {
     principal = Cc["@mozilla.org/systemprincipal;1"].
                 createInstance(Ci.nsIPrincipal);
   }
   let sb = new Cu.Sandbox(principal,
       {sandboxPrototype: win, wantXrays: false, sandboxName: ""});
   sb.global = sb;
@@ -707,16 +730,25 @@ GeckoDriver.prototype.createExecuteSandb
       sb[fn] = mn[fn].bind(mn);
     } else {
       sb[fn] = mn[fn];
     }
   });
 
   sb.isSystemMessageListenerReady = () => systemMessageListenerReady;
 
+  if (sp) {
+    let pow = [
+      "chrome://specialpowers/content/specialpowersAPI.js",
+      "chrome://specialpowers/content/SpecialPowersObserverAPI.js",
+      "chrome://specialpowers/content/ChromePowers.js",
+    ];
+    pow.map(s => loader.loadSubScript(s, sb));
+  }
+
   this.sandboxes[sandboxName] = sb;
 };
 
 /**
  * Apply arguments sent from the client to the current (possibly reused)
  * execution sandbox.
  */
 GeckoDriver.prototype.applyArgumentsToSandbox = function(win, sb, args) {
@@ -784,16 +816,17 @@ GeckoDriver.prototype.executeScriptInSan
  * body.
  */
 GeckoDriver.prototype.execute = function(cmd, resp, directInject) {
   let {inactivityTimeout,
        scriptTimeout,
        script,
        newSandbox,
        args,
+       specialPowers,
        filename,
        line} = cmd.parameters;
   let sandboxName = cmd.parameters.sandbox || 'default';
 
   if (!scriptTimeout) {
     scriptTimeout = this.scriptTimeout;
   }
   if (typeof newSandbox == "undefined") {
@@ -801,16 +834,17 @@ GeckoDriver.prototype.execute = function
   }
 
   if (this.context == Context.CONTENT) {
     resp.value = yield this.listener.executeScript({
       script: script,
       args: args,
       newSandbox: newSandbox,
       timeout: scriptTimeout,
+      specialPowers: specialPowers,
       filename: filename,
       line: line,
       sandboxName: sandboxName
     });
     return;
   }
 
   // handle the inactivity timeout
@@ -841,16 +875,17 @@ GeckoDriver.prototype.execute = function
         "chrome",
         this.marionetteLog,
         scriptTimeout,
         this.heartbeatCallback,
         this.testName);
     this.createExecuteSandbox(
         win,
         marionette,
+        specialPowers,
         sandboxName);
     if (!this.sandboxes[sandboxName]) {
       return;
     }
   }
   this.applyArgumentsToSandbox(win, this.sandboxes[sandboxName], args);
 
   try {
@@ -917,16 +952,17 @@ GeckoDriver.prototype.executeJSScript = 
       resp.value = yield this.listener.executeJSScript({
         script: cmd.parameters.script,
         args: cmd.parameters.args,
         newSandbox: cmd.parameters.newSandbox,
         async: cmd.parameters.async,
         timeout: cmd.parameters.scriptTimeout ?
             cmd.parameters.scriptTimeout : this.scriptTimeout,
         inactivityTimeout: cmd.parameters.inactivityTimeout,
+        specialPowers: cmd.parameters.specialPowers,
         filename: cmd.parameters.filename,
         line: cmd.parameters.line,
         sandboxName: cmd.parameters.sandbox || 'default',
       });
       break;
  }
 };
 
@@ -946,16 +982,17 @@ GeckoDriver.prototype.executeJSScript = 
  * function body.
  */
 GeckoDriver.prototype.executeWithCallback = function(cmd, resp, directInject) {
   let {script,
       args,
       newSandbox,
       inactivityTimeout,
       scriptTimeout,
+      specialPowers,
       filename,
       line} = cmd.parameters;
   let sandboxName = cmd.parameters.sandbox || 'default';
 
   if (!scriptTimeout) {
     scriptTimeout = this.scriptTimeout;
   }
   if (typeof newSandbox == "undefined") {
@@ -965,16 +1002,17 @@ GeckoDriver.prototype.executeWithCallbac
   if (this.context == Context.CONTENT) {
     resp.value = yield this.listener.executeAsyncScript({
       script: script,
       args: args,
       id: cmd.id,
       newSandbox: newSandbox,
       timeout: scriptTimeout,
       inactivityTimeout: inactivityTimeout,
+      specialPowers: specialPowers,
       filename: filename,
       line: line,
       sandboxName: sandboxName,
     });
     return;
   }
 
   // handle the inactivity timeout
@@ -1042,17 +1080,18 @@ GeckoDriver.prototype.executeWithCallbac
       let marionette = new Marionette(
           this,
           win,
           "chrome",
           this.marionetteLog,
           scriptTimeout,
           this.heartbeatCallback,
           this.testName);
-      this.createExecuteSandbox(win, marionette, sandboxName);
+      this.createExecuteSandbox(win, marionette,
+                                specialPowers, sandboxName);
     }
     if (!this.sandboxes[sandboxName]) {
       return;
     }
 
     this.sandboxes[sandboxName].command_id = cmd.id;
     this.sandboxes[sandboxName].runEmulatorCmd = (cmd, cb) => {
       let ecb = new EmulatorCallback();
@@ -2395,16 +2434,17 @@ GeckoDriver.prototype.sessionTearDown = 
       }
     }
 
     let winEn = this.getWinEnumerator();
     while (winEn.hasMoreElements()) {
       winEn.getNext().messageManager.removeDelayedFrameScript(FRAME_SCRIPT);
     }
 
+    this.curBrowser.frameManager.removeSpecialPowers();
     this.curBrowser.frameManager.removeMessageManagerListeners(
         globalMessageManager);
   }
 
   this.switchToGlobalMessageManager();
 
   // reset frame to the top-most frame
   this.curFrame = null;
@@ -2834,33 +2874,16 @@ GeckoDriver.prototype.receiveMessage = f
       let cookieToDelete = message.json.value;
       cookieManager.remove(
           cookieToDelete.host,
           cookieToDelete.name,
           cookieToDelete.path,
           false);
       return true;
 
-    case "Marionette:getFiles":
-      // Generates file objects to send back to the content script
-      // for handling file uploads.
-      let val = message.json.value;
-      let command_id = message.json.command_id;
-      Cu.importGlobalProperties(["File"]);
-      try {
-        let file = new File(val);
-        this.sendAsync("receiveFiles",
-                       {file: file, command_id: command_id});
-      } catch (e) {
-        let err = `File not found: ${val}`;
-        this.sendAsync("receiveFiles",
-                       {error: err, command_id: command_id});
-      }
-      break;
-
     case "Marionette:emitTouchEvent":
       globalMessageManager.broadcastAsyncMessage(
           "MarionetteMainListener:emitTouchEvent", message.json);
       break;
 
     case "Marionette:register":
       let wid = message.json.value;
       let be = message.target;
--- a/testing/marionette/driver/marionette_driver/marionette.py
+++ b/testing/marionette/driver/marionette_driver/marionette.py
@@ -1396,45 +1396,51 @@ class Marionette(object):
                 else:
                     unwrapped[key] = self.unwrapValue(value[key])
         else:
             unwrapped = value
 
         return unwrapped
 
     def execute_js_script(self, script, script_args=None, async=True,
-                          new_sandbox=True, script_timeout=None,
-                          inactivity_timeout=None, filename=None,
-                          sandbox='default'):
+                          new_sandbox=True, special_powers=False,
+                          script_timeout=None, inactivity_timeout=None,
+                          filename=None, sandbox='default'):
         if script_args is None:
             script_args = []
         args = self.wrapArguments(script_args)
         response = self._send_message('executeJSScript',
                                       'value',
                                       script=script,
                                       args=args,
                                       async=async,
                                       newSandbox=new_sandbox,
+                                      specialPowers=special_powers,
                                       scriptTimeout=script_timeout,
                                       inactivityTimeout=inactivity_timeout,
                                       filename=filename,
                                       line=None)
         return self.unwrapValue(response)
 
     def execute_script(self, script, script_args=None, new_sandbox=True,
-                       sandbox='default', script_timeout=None):
+                       special_powers=False, sandbox='default', script_timeout=None):
         '''
         Executes a synchronous JavaScript script, and returns the result (or None if the script does return a value).
 
         The script is executed in the context set by the most recent
         set_context() call, or to the CONTEXT_CONTENT context if set_context()
         has not been called.
 
         :param script: A string containing the JavaScript to execute.
         :param script_args: A list of arguments to pass to the script.
+        :param special_powers: Whether or not you want access to SpecialPowers
+         in your script. Set to False by default because it shouldn't really
+         be used, since you already have access to chrome-level commands if you
+         set context to chrome and do an execute_script. This method was added
+         only to help us run existing Mochitests.
         :param sandbox: A tag referring to the sandbox you wish to use; if
          you specify a new tag, a new sandbox will be created.  If you use the
          special tag 'system', the sandbox will be created using the system
          principal which has elevated privileges.
         :param new_sandbox: If False, preserve global variables from the last
          execute_*script call. This is True by default, in which case no
          globals are preserved.
 
@@ -1487,33 +1493,39 @@ class Marionette(object):
         stack = traceback.extract_stack()
         frame = stack[-2:-1][0] # grab the second-to-last frame
         response = self._send_message('executeScript',
                                       'value',
                                       script=script,
                                       args=args,
                                       newSandbox=new_sandbox,
                                       sandbox=sandbox,
+                                      specialPowers=special_powers,
                                       scriptTimeout=script_timeout,
                                       line=int(frame[1]),
                                       filename=os.path.basename(frame[0]))
         return self.unwrapValue(response)
 
     def execute_async_script(self, script, script_args=None, new_sandbox=True,
                              sandbox='default', script_timeout=None,
-                             debug_script=False):
+                             special_powers=False, debug_script=False):
         '''
         Executes an asynchronous JavaScript script, and returns the result (or None if the script does return a value).
 
         The script is executed in the context set by the most recent
         set_context() call, or to the CONTEXT_CONTENT context if set_context()
         has not been called.
 
         :param script: A string containing the JavaScript to execute.
         :param script_args: A list of arguments to pass to the script.
+        :param special_powers: Whether or not you want access to SpecialPowers
+         in your script. Set to False by default because it shouldn't really
+         be used, since you already have access to chrome-level commands if you
+         set context to chrome and do an execute_script. This method was added
+         only to help us run existing Mochitests.
         :param sandbox: A tag referring to the sandbox you wish to use; if
          you specify a new tag, a new sandbox will be created.  If you use the
          special tag 'system', the sandbox will be created using the system
          principal which has elevated privileges.
         :param new_sandbox: If False, preserve global variables from the last
          execute_*script call. This is True by default, in which case no
          globals are preserved.
         :param debug_script: Capture javascript exceptions when in
@@ -1538,16 +1550,17 @@ class Marionette(object):
         stack = traceback.extract_stack()
         frame = stack[-2:-1][0] # grab the second-to-last frame
         response = self._send_message('executeAsyncScript',
                                       'value',
                                       script=script,
                                       args=args,
                                       newSandbox=new_sandbox,
                                       sandbox=sandbox,
+                                      specialPowers=special_powers,
                                       scriptTimeout=script_timeout,
                                       line=int(frame[1]),
                                       filename=os.path.basename(frame[0]),
                                       debug_script=debug_script)
         return self.unwrapValue(response)
 
     def find_element(self, method, target, id=None):
         '''
--- a/testing/marionette/driver/marionette_driver/selection.py
+++ b/testing/marionette/driver/marionette_driver/selection.py
@@ -32,30 +32,30 @@ class SelectionManager(object):
 
         Note: "element" must be provided as the first argument to
         execute_script().
 
         '''
         if self._input_or_textarea():
             # We must unwrap sel so that DOMRect could be returned to Python
             # side.
-            return '''var sel = arguments[0].editor.selection;'''
+            return '''var sel = SpecialPowers.wrap(arguments[0]).editor.selection;
+                   sel = SpecialPowers.unwrap(sel);'''
         else:
             return '''var sel = window.getSelection();'''
 
     def move_caret_by_offset(self, offset, backward=False):
         '''Move caret in the element by character offset.'''
         cmd = self.js_selection_cmd() +\
             '''sel.modify("move", arguments[1], "character");'''
         direction = 'backward' if backward else 'forward'
 
         for i in range(offset):
             self.element.marionette.execute_script(
-                cmd, script_args=[self.element, direction],
-                sandbox='system')
+                cmd, script_args=[self.element, direction])
 
     def move_caret_to_front(self):
         '''Move caret in the element to the front of the content.'''
         if self._input_or_textarea():
             cmd = '''arguments[0].setSelectionRange(0, 0);'''
         else:
             cmd = '''var sel = window.getSelection();
                   sel.collapse(arguments[0].firstChild, 0);'''
@@ -78,27 +78,23 @@ class SelectionManager(object):
 
         If the element is either <input> or <textarea>, return the DOMRectList of
         the range at given idx of the selection within the element. Otherwise,
         return the DOMRectList of the of the range at given idx of current selection.
 
         '''
         cmd = self.js_selection_cmd() +\
             '''return sel.getRangeAt(%d).getClientRects();''' % idx
-        return self.element.marionette.execute_script(cmd,
-                                                      script_args=[self.element],
-                                                      sandbox='system')
+        return self.element.marionette.execute_script(cmd, script_args=[self.element])
 
     def range_count(self):
         '''Get selection's range count'''
         cmd = self.js_selection_cmd() +\
             '''return sel.rangeCount;'''
-        return self.element.marionette.execute_script(cmd,
-                                                      script_args=[self.element],
-                                                      sandbox='system')
+        return self.element.marionette.execute_script(cmd, script_args=[self.element])
 
     def _selection_location_helper(self, location_type):
         '''Return the start and end location of the selection in the element.
 
         Return a tuple containing two pairs of (x, y) coordinates of the start
         and end locations in the element. The coordinates are relative to the
         top left-hand corner of the element. Both ltr and rtl directions are
         considered.
@@ -199,11 +195,9 @@ class SelectionManager(object):
         else:
             return self.element.text
 
     @property
     def selected_content(self):
         '''Return the selected portion of the content in the element.'''
         cmd = self.js_selection_cmd() +\
             '''return sel.toString();'''
-        return self.element.marionette.execute_script(cmd,
-                                                      script_args=[self.element],
-                                                      sandbox='system')
+        return self.element.marionette.execute_script(cmd, script_args=[self.element])
--- a/testing/marionette/frame-manager.js
+++ b/testing/marionette/frame-manager.js
@@ -8,16 +8,17 @@ this.EXPORTED_SYMBOLS = ["FrameManager"]
 
 let FRAME_SCRIPT = "chrome://marionette/content/listener.js";
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
                .getService(Ci.mozIJSSubScriptLoader);
+let specialpowers = {};
 
 //list of OOP frames that has the frame script loaded
 let remoteFrames = [];
 
 /**
  * An object representing a frame that Marionette has loaded a
  * frame script in.
  */
@@ -114,16 +115,21 @@ FrameManager.prototype = {
   /**
    * Switch to OOP frame.  We're handling this here
    * so we can maintain a list of remote frames.
    */
   switchToFrame: function FM_switchToFrame(winId, frameId) {
     let oopFrame = this.getOopFrame(winId, frameId);
     let mm = this.getFrameMM(winId, frameId);
 
+    if (!specialpowers.hasOwnProperty("specialPowersObserver")) {
+      loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js",
+          specialpowers);
+    }
+
     // See if this frame already has our frame script loaded in it;
     // if so, just wake it up.
     for (let i = 0; i < remoteFrames.length; i++) {
       let frame = remoteFrames[i];
       let frameMessageManager = frame.messageManager.get();
       try {
         frameMessageManager.sendAsyncMessage("aliveCheck", {});
       } catch (e) {
@@ -131,32 +137,40 @@ FrameManager.prototype = {
           remoteFrames.splice(i, 1);
           continue;
         }
       }
       if (frameMessageManager == mm) {
         this.currentRemoteFrame = frame;
         this.addMessageManagerListeners(mm);
 
+        if (!frame.specialPowersObserver) {
+          frame.specialPowersObserver = new specialpowers.SpecialPowersObserver();
+          frame.specialPowersObserver.init(mm);
+        }
+
         mm.sendAsyncMessage("Marionette:restart");
         return oopFrame.id;
       }
     }
 
     // If we get here, then we need to load the frame script in this frame,
     // and set the frame's ChromeMessageSender as the active message manager
     // the server will listen to.
     this.addMessageManagerListeners(mm);
     let aFrame = new MarionetteRemoteFrame(winId, frameId);
     aFrame.messageManager = Cu.getWeakReference(mm);
     remoteFrames.push(aFrame);
     this.currentRemoteFrame = aFrame;
 
     mm.loadFrameScript(FRAME_SCRIPT, true, true);
 
+    aFrame.specialPowersObserver = new specialpowers.SpecialPowersObserver();
+    aFrame.specialPowersObserver.init(mm);
+
     return oopFrame.id;
   },
 
   /*
    * This function handles switching back to the frame that was interrupted by the modal dialog.
    * This function gets called by the interrupted frame once the dialog is dismissed and the frame resumes its process
    */
   switchToModalOrigin: function FM_switchToModalOrigin() {
@@ -164,16 +178,30 @@ FrameManager.prototype = {
     if (this.previousRemoteFrame != null) {
       this.currentRemoteFrame = this.previousRemoteFrame;
       this.addMessageManagerListeners(this.currentRemoteFrame.messageManager.get());
     }
     this.handledModal = false;
   },
 
   /**
+   * This function removes any SpecialPowersObservers from OOP frames.
+   */
+  removeSpecialPowers: function FM_removeSpecialPowers() {
+    for (let i = 0; i < remoteFrames.length; i++) {
+      let frame = remoteFrames[i];
+
+      if (frame.specialPowersObserver) {
+        frame.specialPowersObserver.uninit();
+        frame.specialPowersObserver = null;
+      }
+    }
+  },
+
+  /**
    * Adds message listeners to the server, 
    * listening for messages from content frame scripts.
    * It also adds a MarionetteFrame:getInterruptedState
    * message listener to the FrameManager,
    * so the frame manager's state can be checked by the frame.
    *
    * @param {nsIMessageListenerManager} mm
    *     The message manager object, typically
@@ -187,17 +215,16 @@ FrameManager.prototype = {
     mm.addWeakMessageListener("Marionette:shareData", this.server);
     mm.addWeakMessageListener("Marionette:switchToModalOrigin", this.server);
     mm.addWeakMessageListener("Marionette:switchedToFrame", this.server);
     mm.addWeakMessageListener("Marionette:addCookie", this.server);
     mm.addWeakMessageListener("Marionette:getVisibleCookies", this.server);
     mm.addWeakMessageListener("Marionette:deleteCookie", this.server);
     mm.addWeakMessageListener("Marionette:register", this.server);
     mm.addWeakMessageListener("Marionette:listenersAttached", this.server);
-    mm.addWeakMessageListener("Marionette:getFiles", this.server);
     mm.addWeakMessageListener("MarionetteFrame:handleModal", this);
     mm.addWeakMessageListener("MarionetteFrame:getCurrentFrameId", this);
     mm.addWeakMessageListener("MarionetteFrame:getInterruptedState", this);
   },
 
   /**
    * Removes listeners for messages from content frame scripts.
    * We do not remove the MarionetteFrame:getInterruptedState
@@ -216,13 +243,12 @@ FrameManager.prototype = {
     mm.removeWeakMessageListener("Marionette:runEmulatorCmd", this.server);
     mm.removeWeakMessageListener("Marionette:runEmulatorShell", this.server);
     mm.removeWeakMessageListener("Marionette:switchedToFrame", this.server);
     mm.removeWeakMessageListener("Marionette:addCookie", this.server);
     mm.removeWeakMessageListener("Marionette:getVisibleCookies", this.server);
     mm.removeWeakMessageListener("Marionette:deleteCookie", this.server);
     mm.removeWeakMessageListener("Marionette:listenersAttached", this.server);
     mm.removeWeakMessageListener("Marionette:register", this.server);
-    mm.removeWeakMessageListener("Marionette:getFiles", this.server);
     mm.removeWeakMessageListener("MarionetteFrame:handleModal", this);
     mm.removeWeakMessageListener("MarionetteFrame:getCurrentFrameId", this);
   }
 };
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -22,36 +22,35 @@ Cu.import("resource://gre/modules/XPCOMU
 let utils = {};
 utils.window = content;
 // Load Event/ChromeUtils for use with JS scripts:
 loader.loadSubScript("chrome://marionette/content/EventUtils.js", utils);
 loader.loadSubScript("chrome://marionette/content/ChromeUtils.js", utils);
 loader.loadSubScript("chrome://marionette/content/atoms.js", utils);
 loader.loadSubScript("chrome://marionette/content/sendkeys.js", utils);
 
+loader.loadSubScript("chrome://specialpowers/content/specialpowersAPI.js");
+loader.loadSubScript("chrome://specialpowers/content/specialpowers.js");
+
 let marionetteLogObj = new MarionetteLogObj();
 
 let isB2G = false;
 
 let marionetteTestName;
 let winUtil = content.QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIDOMWindowUtils);
 let listenerId = null; // unique ID of this listener
 let curFrame = content;
 let isRemoteBrowser = () => curFrame.contentWindow !== null;
 let previousFrame = null;
 let elementManager = new ElementManager([]);
 let accessibility = new Accessibility();
 let actions = new ActionChain(utils, checkForInterrupted);
 let importedScripts = null;
 
-// Contains the last file input element that was the target of
-// sendKeysToElement.
-let fileInputElement;
-
 // A dict of sandboxes used this session
 let sandboxes = {};
 // The name of the current sandbox
 let sandboxName = 'default';
 
 // the unload handler
 let onunload;
 
@@ -192,17 +191,16 @@ let getElementTextFn = dispatch(getEleme
 let getElementTagNameFn = dispatch(getElementTagName);
 let getElementRectFn = dispatch(getElementRect);
 let isElementEnabledFn = dispatch(isElementEnabled);
 
 /**
  * Start all message listeners
  */
 function startListeners() {
-  addMessageListenerId("Marionette:receiveFiles", receiveFiles);
   addMessageListenerId("Marionette:newSession", newSession);
   addMessageListenerId("Marionette:executeScript", executeScript);
   addMessageListenerId("Marionette:executeAsyncScript", executeAsyncScript);
   addMessageListenerId("Marionette:executeJSScript", executeJSScript);
   addMessageListenerId("Marionette:singleTap", singleTap);
   addMessageListenerId("Marionette:actionChain", actionChain);
   addMessageListenerId("Marionette:multiAction", multiAction);
   addMessageListenerId("Marionette:get", get);
@@ -297,17 +295,16 @@ function restart(msg) {
   }
   registerSelf();
 }
 
 /**
  * Removes all listeners
  */
 function deleteSession(msg) {
-  removeMessageListenerId("Marionette:receiveFiles", receiveFiles);
   removeMessageListenerId("Marionette:newSession", newSession);
   removeMessageListenerId("Marionette:executeScript", executeScript);
   removeMessageListenerId("Marionette:executeAsyncScript", executeAsyncScript);
   removeMessageListenerId("Marionette:executeJSScript", executeJSScript);
   removeMessageListenerId("Marionette:singleTap", singleTap);
   removeMessageListenerId("Marionette:actionChain", actionChain);
   removeMessageListenerId("Marionette:multiAction", multiAction);
   removeMessageListenerId("Marionette:get", get);
@@ -485,16 +482,24 @@ function createExecuteContentSandbox(win
   mn.exports.forEach(fn => {
     if (typeof mn[fn] == "function") {
       sandbox[fn] = mn[fn].bind(mn);
     } else {
       sandbox[fn] = mn[fn];
     }
   });
 
+  let specialPowersFn;
+  if (typeof win.wrappedJSObject.SpecialPowers != "undefined") {
+    specialPowersFn = () => win.wrappedJSObject.SpecialPowers;
+  } else {
+    specialPowersFn = () => new SpecialPowers(win);
+  }
+  XPCOMUtils.defineLazyGetter(sandbox, "SpecialPowers", specialPowersFn);
+
   sandbox.asyncComplete = (obj, id) => {
     if (id == asyncTestCommandId) {
       curFrame.removeEventListener("unload", onunload, false);
       curFrame.clearTimeout(asyncTestTimeoutId);
 
       if (inactivityTimeoutId != null) {
         curFrame.clearTimeout(inactivityTimeoutId);
       }
@@ -641,38 +646,16 @@ function setTestName(msg) {
 /**
  * Execute async script
  */
 function executeAsyncScript(msg) {
   executeWithCallback(msg);
 }
 
 /**
- * Receive file objects from chrome in order to complete a
- * sendKeysToElement action on a file input element.
- */
-function receiveFiles(msg) {
-  if ('error' in msg.json) {
-    let err = new InvalidArgumentError(msg.json.error);
-    sendError(err, msg.json.command_id);
-    return;
-  }
-  if (!fileInputElement) {
-    let err = new InvalidElementStateError("receiveFiles called with no valid fileInputElement");
-    sendError(err, msg.json.command_id);
-    return;
-  }
-  let fs = Array.prototype.slice.call(fileInputElement.files);
-  fs.push(msg.json.file);
-  fileInputElement.mozSetFileArray(fs);
-  fileInputElement = null;
-  sendOk(msg.json.command_id);
-}
-
-/**
  * Execute pure JS test. Handles both async and sync cases.
  */
 function executeJSScript(msg) {
   if (msg.json.async) {
     executeWithCallback(msg, msg.json.async);
   }
   else {
     executeScript(msg, true);
@@ -1549,22 +1532,41 @@ function isElementSelected(msg) {
  */
 function sendKeysToElement(msg) {
   let command_id = msg.json.command_id;
   let val = msg.json.value;
 
   let el = elementManager.getKnownElement(msg.json.id, curFrame);
   if (el.type == "file") {
     let p = val.join("");
-    fileInputElement = el;
-    // In e10s, we can only construct File objects in the parent process,
-    // so pass the filename to driver.js, which in turn passes them back
-    // to this frame script in receiveFiles.
-    sendSyncMessage("Marionette:getFiles",
-                    {value: p, command_id: command_id});
+
+    // for some reason using mozSetFileArray doesn't work with e10s
+    // enabled (probably a bug), but a workaround is to elevate the element's
+    // privileges with SpecialPowers
+    //
+    // this extra branch can be removed when the e10s bug 1149998 is fixed
+    if (isRemoteBrowser()) {
+      let fs = Array.prototype.slice.call(el.files);
+      let file;
+      try {
+        file = new File(p);
+      } catch (e) {
+        let err = new InvalidArgumentError(`File not found: ${val}`);
+        sendError(err, command_id);
+        return;
+      }
+      fs.push(file);
+
+      let wel = new SpecialPowers(utils.window).wrap(el);
+      wel.mozSetFileArray(fs);
+    } else {
+      sendSyncMessage("Marionette:setElementValue", {value: p}, {element: el});
+    }
+
+    sendOk(command_id);
   } else {
     utils.sendKeysToElement(curFrame, el, val, sendOk, sendError, command_id);
   }
 }
 
 /**
  * Get the element's top left-hand corner point.
  */
--- a/testing/marionette/server.js
+++ b/testing/marionette/server.js
@@ -24,16 +24,17 @@ loader.loadSubScript("resource://gre/mod
 let events = {};
 loader.loadSubScript("chrome://marionette/content/EventUtils.js", events);
 loader.loadSubScript("chrome://marionette/content/ChromeUtils.js", events);
 loader.loadSubScript("chrome://marionette/content/frame-manager.js");
 
 const logger = Log.repository.getLogger("Marionette");
 
 this.EXPORTED_SYMBOLS = ["MarionetteServer"];
+const SPECIAL_POWERS_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
 const CONTENT_LISTENER_PREF = "marionette.contentListener";
 
 /**
  * Bootstraps Marionette and handles incoming client connections.
  *
  * Once started, it opens a TCP socket sporting the debugger transport
  * protocol on the provided port.  For every new client a Dispatcher is
  * created.
--- a/testing/mochitest/b2g_start_script.js
+++ b/testing/mochitest/b2g_start_script.js
@@ -24,20 +24,16 @@ let homescreen = document.getElementById
 let container = homescreen.contentWindow.document.getElementById('test-container');
 
 // Disable udpate timers which cause failure in b2g permisson prompt tests.
 if (cm) {
   cm.deleteCategoryEntry("update-timer", "WebappsUpdateTimer", false);
   cm.deleteCategoryEntry("update-timer", "nsUpdateService", false);
 }
 
-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);
-
 function openWindow(aEvent) {
   var popupIframe = aEvent.detail.frameElement;
   popupIframe.id = 'popupiframe';
 
   // This is to size the iframe to what is requested in the window.open call,
   // e.g. window.open("", "", "width=600,height=600");
   if (aEvent.detail.features.indexOf('width') != -1) {
     let width = aEvent.detail.features.substr(aEvent.detail.features.indexOf('width')+6);
@@ -96,21 +92,16 @@ if (outOfProcess) {
       window.wrappedJSObject.SpecialPowers.addPermission("allowXULXBL", true, window.document);
     });
   }
   mm.loadFrameScript("data:,(" + encodeURI(contentScript.toSource()) + ")();", true);
 }
 
 if (chrome) {
   let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
-  if (typeof(SpecialPowers) == 'undefined') {
-    loader.loadSubScript("chrome://specialpowers/content/specialpowersAPI.js");
-    loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js");
-    loader.loadSubScript("chrome://specialpowers/content/ChromePowers.js");
-  }
   loader.loadSubScript("chrome://mochikit/content/browser-test.js");
   b2gStart();
 }
 
 if (onDevice) {
   var cpuLock = Cc["@mozilla.org/power/powermanagerservice;1"]
                       .getService(Ci.nsIPowerManagerService)
                       .newWakeLock("cpu");
--- a/testing/mochitest/runtestsb2g.py
+++ b/testing/mochitest/runtestsb2g.py
@@ -215,32 +215,16 @@ class B2GMochitest(MochitestUtilsMixin):
             # won't be offline on a real device, so we only do this for
             # emulators.
             self.marionette.execute_script("""
                 Components.utils.import("resource://gre/modules/Services.jsm");
                 Services.io.manageOfflineStatus = false;
                 Services.io.offline = false;
                 """)
 
-            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.js",
-                    testUtils);
-                  testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
-                  testUtils.specialPowersObserver.init();
-                  testUtils.specialPowersObserver._loadFrameScript();
-                }
-                """)
-
             if options.chrome:
                 self.app_ctx.dm.removeDir(self.remote_chrome_test_dir)
                 self.app_ctx.dm.mkDir(self.remote_chrome_test_dir)
                 local = super(B2GMochitest, self).getChromeTestDir(options)
                 local = os.path.join(local, "chrome")
                 remote = self.remote_chrome_test_dir
                 self.log.info(
                     "pushing %s to %s on device..." %