Backed out 5 changesets (bug 1280947) for mn bustage a=backout FIREFOX_49_0b9_BUILD1 FIREFOX_49_0b9_RELEASE
authorWes Kocher <wkocher@mozilla.com>
Thu, 01 Sep 2016 14:15:22 -0700
changeset 342567 e3cc699ccef2abb7075c39e7b9a081718eb9c159
parent 342566 462e604cb5d474ddce189a27eeb0a29242696eee
child 342568 56d41c5fb950330a64caa9b55381a8699f46f6b1
push id1183
push userraliiev@mozilla.com
push dateMon, 05 Sep 2016 20:01:49 +0000
treeherdermozilla-release@3148731bed45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1280947
milestone49.0
backs out64412641007c0bbe5734041dfc5fee6b1edc3447
e7599a44f0aecb5e7d72eccd0dbb4f111813cc72
91d56ae239b27ea52b685f10bf40f6e9cfa0f1c7
7e91010b61c975b53ffcc780030690647bc8014f
b85804c6905abc66358bac505bbc180758790e76
Backed out 5 changesets (bug 1280947) for mn bustage a=backout Backed out changeset 64412641007c (bug 1280947) Backed out changeset e7599a44f0ae (bug 1280947) Backed out changeset 91d56ae239b2 (bug 1280947) Backed out changeset 7e91010b61c9 (bug 1280947) Backed out changeset b85804c6905a (bug 1280947)
testing/marionette/addon.js
testing/marionette/client/marionette_driver/marionette.py
testing/marionette/driver.js
testing/marionette/event.js
testing/marionette/harness/marionette/tests/unit/test_certificates.py
testing/marionette/harness/marionette/tests/unit/test_file_upload.py
testing/marionette/interaction.js
testing/marionette/listener.js
deleted file mode 100644
--- a/testing/marionette/addon.js
+++ /dev/null
@@ -1,93 +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/. */
-
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/AddonManager.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-
-Cu.import("chrome://marionette/content/error.js");
-
-this.EXPORTED_SYMBOLS = ["addon"];
-
-this.addon = {};
-
-/**
- * Installs Firefox addon.
- *
- * If the addon is restartless, it can be used right away. Otherwise a
- * restart is needed.
- *
- * Temporary addons will automatically be unisntalled on shutdown and
- * do not need to be signed, though they must be restartless.
- *
- * @param {string} path
- *     Full path to the extension package archive to be installed.
- * @param {boolean=} temporary
- *     Install the add-on temporarily if true.
- *
- * @return {Promise.<string>}
- *     Addon ID string of the newly installed addon.
- *
- * @throws {AddonError}
- *     if installation fails
- */
-addon.install = function(path, temporary = false) {
-  return new Promise((resolve, reject) => {
-    let listener = {
-      onInstallEnded: function(install, addon) {
-        resolve(addon.id);
-      },
-
-      onInstallFailed: function(install) {
-        reject(new AddonError(install.error));
-      },
-
-      onInstalled: function(addon) {
-        AddonManager.removeAddonListener(listener);
-        resolve(addon.id);
-      }
-    };
-
-    let file = new FileUtils.File(path);
-
-    // temporary addons
-    if (temp) {
-      AddonManager.addAddonListener(listener);
-      AddonManager.installTemporaryAddon(file);
-    }
-
-    // addons that require restart
-    else {
-      AddonManager.getInstallForFile(file, function(aInstall) {
-        if (aInstall.error != 0) {
-          reject(new AddonError(aInstall.error));
-        }
-        aInstall.addListener(listener);
-        aInstall.install();
-      });
-    }
-  });
-};
-
-/**
- * Uninstall a Firefox addon.
- *
- * If the addon is restartless, it will be uninstalled right
- * away. Otherwise a restart is necessary.
- *
- * @param {string} id
- *     Addon ID to uninstall.
- *
- * @return {Promise}
- */
-addon.uninstall = function(id) {
-  return new Promise(resolve => {
-    AddonManager.getAddonByID(arguments[0], function(addon) {
-      addon.uninstall();
-    });
-  });
-};
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -763,33 +763,33 @@ class Marionette(object):
         script = """
         let value = {
           'url': document.nodePrincipal.URI.spec,
           'appId': document.nodePrincipal.appId,
           'isInIsolatedMozBrowserElement': document.nodePrincipal.isInIsolatedMozBrowserElement,
           'type': arguments[0]
         };
         return value;"""
-        with self.using_context("content"):
-            value = self.execute_script(script, script_args=(perm,), sandbox="system")
+        with self.using_context('content'):
+            value = self.execute_script(script, script_args=[perm], sandbox='system')
 
-        with self.using_context("chrome"):
+        with self.using_context('chrome'):
             permission = self.execute_script("""
                 Components.utils.import("resource://gre/modules/Services.jsm");
                 let perm = arguments[0];
                 let secMan = Services.scriptSecurityManager;
                 let attrs = {appId: perm.appId,
                             inIsolatedMozBrowser: perm.isInIsolatedMozBrowserElement};
                 let principal = secMan.createCodebasePrincipal(
                                 Services.io.newURI(perm.url, null, null),
                                 attrs);
                 let testPerm = Services.perms.testPermissionFromPrincipal(
                                principal, perm.type);
                 return testPerm;
-                """, script_args=(value,))
+                """, script_args=[value])
         return permission
 
     def push_permission(self, perm, allow):
         script = """
         let allow = arguments[0];
         if (typeof(allow) == "boolean") {
             if (allow) {
               allow = Components.interfaces.nsIPermissionManager.ALLOW_ACTION;
@@ -819,42 +819,42 @@ class Marionette(object):
           'url': document.nodePrincipal.URI.spec,
           'appId': document.nodePrincipal.appId,
           'isInIsolatedMozBrowserElement': document.nodePrincipal.isInIsolatedMozBrowserElement,
           'type': perm_type,
           'action': allow
         };
         return value;
         """
-        with self.using_context("content"):
-            perm = self.execute_script(script, script_args=(allow, perm,), sandbox="system")
+        with self.using_context('content'):
+            perm = self.execute_script(script, script_args=[allow, perm], sandbox='system')
 
-        current_perm = self.get_permission(perm["type"])
-        if current_perm == perm["action"]:
-            with self.using_context("content"):
+        current_perm = self.get_permission(perm['type'])
+        if current_perm == perm['action']:
+            with self.using_context('content'):
                 self.execute_script("""
                     Components.utils.import("resource://gre/modules/Services.jsm");
                     Services.obs.removeObserver(window.wrappedJSObject.permObserver,
                                                 "perm-changed");
-                    """, sandbox="system")
+                    """, sandbox='system')
             return
 
-        with self.using_context("chrome"):
+        with self.using_context('chrome'):
             self.execute_script("""
                 Components.utils.import("resource://gre/modules/Services.jsm");
                 let perm = arguments[0];
                 let secMan = Services.scriptSecurityManager;
                 let attrs = {appId: perm.appId,
                              inIsolatedMozBrowser: perm.isInIsolatedMozBrowserElement};
                 let principal = secMan.createCodebasePrincipal(Services.io.newURI(perm.url,
                                                                                   null, null),
                                                                                   attrs);
                 Services.perms.addFromPrincipal(principal, perm.type, perm.action);
                 return true;
-                """, script_args=(perm,))
+                """, script_args=[perm])
 
         with self.using_context("content"):
             self.execute_async_script("""
                 let start = new Date();
                 let end = new Date(start.valueOf() + 5000);
                 let wait = function() {
                   let now = new Date();
                   if (window.wrappedJSObject.permChanged || end >= now) {
@@ -897,81 +897,81 @@ class Marionette(object):
         Usage example::
 
             marionette.get_pref("browser.tabs.warnOnClose")
         """
         with self.using_context(self.CONTEXT_CONTENT):
             pref_value = self.execute_script("""
                 Components.utils.import("resource://gre/modules/Preferences.jsm");
                 return Preferences.get(arguments[0], null);
-                """, script_args=(pref,), sandbox="system")
+                """, script_args=[pref], sandbox="system")
             return pref_value
 
     def clear_pref(self, pref):
         with self.using_context(self.CONTEXT_CHROME):
             self.execute_script("""
                Components.utils.import("resource://gre/modules/Preferences.jsm");
                Preferences.reset(arguments[0]);
-               """, script_args=(pref,))
+               """, script_args=[pref])
 
     def set_pref(self, pref, value):
         with self.using_context(self.CONTEXT_CHROME):
             if value is None:
                 self.clear_pref(pref)
                 return
 
             self.execute_script("""
                 Components.utils.import("resource://gre/modules/Preferences.jsm");
                 Preferences.set(arguments[0], arguments[1]);
-                """, script_args=(pref, value,))
+                """, script_args=[pref, value])
 
     def set_prefs(self, prefs):
-        """Sets preferences.
+        '''Sets preferences.
 
         If the value of the preference to be set is None, reset the preference
         to its default value. If no default value exists, the preference will
         cease to exist.
 
-        :param prefs: A dict containing one or more preferences and
-            their values to be set.
+        :param prefs: A dict containing one or more preferences and their values
+        to be set.
 
         Usage example::
 
-            marionette.set_prefs({"browser.tabs.warnOnClose": True})
+          marionette.set_prefs({'browser.tabs.warnOnClose': True})
 
-        """
+        '''
         for pref, value in prefs.items():
             self.set_pref(pref, value)
 
     @contextmanager
     def using_prefs(self, prefs):
-        """Sets preferences for code being executed in a `with` block,
+        '''Sets preferences for code being executed in a `with` block,
         and restores them on exit.
 
         :param prefs: A dict containing one or more preferences and their values
         to be set.
 
         Usage example::
 
-            with marionette.using_prefs({"browser.tabs.warnOnClose": True}):
-                # ... do stuff ...
+          with marionette.using_prefs({'browser.tabs.warnOnClose': True}):
+              # ... do stuff ...
 
-        """
+        '''
         original_prefs = {p: self.get_pref(p) for p in prefs}
         self.set_prefs(prefs)
 
         try:
             yield
         finally:
             self.set_prefs(original_prefs)
 
     def enforce_gecko_prefs(self, prefs):
-        """Checks if the running instance has the given prefs. If not,
-        it will kill the currently running instance, and spawn a new
-        instance with the requested preferences.
+        """
+        Checks if the running instance has the given prefs. If not, it will kill the
+        currently running instance, and spawn a new instance with the requested preferences.
 
         : param prefs: A dictionary whose keys are preference names.
         """
         if not self.instance:
             raise errors.MarionetteException("enforce_gecko_prefs can only be called "
                                              "on gecko instances launched by Marionette")
         pref_exists = True
         self.set_context(self.CONTEXT_CHROME)
@@ -1447,80 +1447,82 @@ class Marionette(object):
     def go_forward(self):
         """Causes the browser to perform a forward navigation."""
         self._send_message("goForward")
 
     def refresh(self):
         """Causes the browser to perform to refresh the current page."""
         self._send_message("refresh")
 
-    def _to_json(self, args):
-        if isinstance(args, list) or isinstance(args, tuple):
+    def wrapArguments(self, args):
+        if isinstance(args, list):
             wrapped = []
             for arg in args:
-                wrapped.append(self._to_json(arg))
+                wrapped.append(self.wrapArguments(arg))
         elif isinstance(args, dict):
             wrapped = {}
             for arg in args:
-                wrapped[arg] = self._to_json(args[arg])
+                wrapped[arg] = self.wrapArguments(args[arg])
         elif type(args) == HTMLElement:
             wrapped = {W3C_WEBELEMENT_KEY: args.id,
                        WEBELEMENT_KEY: args.id}
         elif (isinstance(args, bool) or isinstance(args, basestring) or
               isinstance(args, int) or isinstance(args, float) or args is None):
             wrapped = args
         return wrapped
 
-    def _from_json(self, value):
+    def unwrapValue(self, value):
         if isinstance(value, list):
             unwrapped = []
             for item in value:
-                unwrapped.append(self._from_json(item))
+                unwrapped.append(self.unwrapValue(item))
         elif isinstance(value, dict):
             unwrapped = {}
             for key in value:
                 if key == W3C_WEBELEMENT_KEY:
                     unwrapped = HTMLElement(self, value[key])
                     break
                 elif key == WEBELEMENT_KEY:
                     unwrapped = HTMLElement(self, value[key])
                     break
                 else:
-                    unwrapped[key] = self._from_json(value[key])
+                    unwrapped[key] = self.unwrapValue(value[key])
         else:
             unwrapped = value
         return unwrapped
 
-    def execute_js_script(self, script, script_args=(), async=True,
+    def execute_js_script(self, script, script_args=None, async=True,
                           new_sandbox=True, script_timeout=None,
                           inactivity_timeout=None, filename=None,
                           sandbox='default'):
-        args = self._to_json(script_args)
+        if script_args is None:
+            script_args = []
+        args = self.wrapArguments(script_args)
         body = {"script": script,
                 "args": args,
                 "async": async,
                 "newSandbox": new_sandbox,
                 "scriptTimeout": script_timeout,
                 "inactivityTimeout": inactivity_timeout,
                 "filename": filename,
                 "line": None}
         rv = self._send_message("executeJSScript", body, key="value")
-        return self._from_json(rv)
+        return self.unwrapValue(rv)
 
-    def execute_script(self, script, script_args=(), new_sandbox=True,
+    def execute_script(self, script, script_args=None, new_sandbox=True,
                        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: An interable of arguments to pass to the script.
+        :param script_args: A list of arguments to pass to the script.
         :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.
@@ -1533,20 +1535,20 @@ class Marionette(object):
             assert result == 1
 
         You can use the `script_args` parameter to pass arguments to the
         script:
 
         ::
 
             result = marionette.execute_script("return arguments[0] + arguments[1];",
-                                               script_args=(2, 3,))
+                                               script_args=[2, 3])
             assert result == 5
             some_element = marionette.find_element(By.ID, "someElement")
-            sid = marionette.execute_script("return arguments[0].id;", script_args=(some_element,))
+            sid = marionette.execute_script("return arguments[0].id;", script_args=[some_element])
             assert some_element.get_attribute("id") == sid
 
         Scripts wishing to access non-standard properties of the window
         object must use window.wrappedJSObject:
 
         ::
 
             result = marionette.execute_script('''
@@ -1563,41 +1565,43 @@ class Marionette(object):
 
         ::
 
             marionette.execute_script("global.test1 = 'foo';")
             result = self.marionette.execute_script("return global.test1;", new_sandbox=False)
             assert result == "foo"
 
         """
-        args = self._to_json(script_args)
+        if script_args is None:
+            script_args = []
+        args = self.wrapArguments(script_args)
         stack = traceback.extract_stack()
         frame = stack[-2:-1][0]  # grab the second-to-last frame
         body = {"script": script,
                 "args": args,
                 "newSandbox": new_sandbox,
                 "sandbox": sandbox,
                 "scriptTimeout": script_timeout,
                 "line": int(frame[1]),
                 "filename": os.path.basename(frame[0])}
         rv = self._send_message("executeScript", body, key="value")
-        return self._from_json(rv)
+        return self.unwrapValue(rv)
 
-    def execute_async_script(self, script, script_args=(), new_sandbox=True,
+    def execute_async_script(self, script, script_args=None, new_sandbox=True,
                              sandbox="default", script_timeout=None,
                              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: An interable of arguments to pass to the script.
+        :param script_args: A list of arguments to pass to the script.
         :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
@@ -1611,29 +1615,31 @@ class Marionette(object):
             result = self.marionette.execute_async_script('''
               // this script waits 5 seconds, and then returns the number 1
               setTimeout(function() {
                 marionetteScriptFinished(1);
               }, 5000);
             ''')
             assert result == 1
         """
-        args = self._to_json(script_args)
+        if script_args is None:
+            script_args = []
+        args = self.wrapArguments(script_args)
         stack = traceback.extract_stack()
         frame = stack[-2:-1][0]  # grab the second-to-last frame
         body = {"script": script,
                 "args": args,
                 "newSandbox": new_sandbox,
                 "sandbox": sandbox,
                 "scriptTimeout": script_timeout,
                 "line": int(frame[1]),
                 "filename": os.path.basename(frame[0]),
                 "debug_script": debug_script}
         rv = self._send_message("executeAsyncScript", body, key="value")
-        return self._from_json(rv)
+        return self.unwrapValue(rv)
 
     def find_element(self, method, target, id=None):
         """Returns an HTMLElement instances that matches the specified
         method and target in the current context.
 
         An HTMLElement instance may be used to call other methods on the
         element, such as click().  If no element is immediately found, the
         attempt to locate an element will be repeated for up to the amount of
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2009,17 +2009,46 @@ GeckoDriver.prototype.sendKeysToElement 
     case Context.CHROME:
       let win = this.getCurrentWindow();
       let el = this.curBrowser.seenEls.get(id, {frame: win});
       yield interaction.sendKeysToElement(
           el, value, true, this.sessionCapabilities.raisesAccessibilityExceptions);
       break;
 
     case Context.CONTENT:
+      let err;
+      let listener = function(msg) {
+        this.mm.removeMessageListener("Marionette:setElementValue", listener);
+
+        let val = msg.data.value;
+        let el = msg.objects.element;
+        let win = this.getCurrentWindow();
+
+        if (el.type == "file") {
+          Cu.importGlobalProperties(["File"]);
+          let fs = Array.prototype.slice.call(el.files);
+          let file;
+          try {
+            file = new File(val);
+          } catch (e) {
+            err = new InvalidArgumentError(`File not found: ${val}`);
+          }
+          fs.push(file);
+          el.mozSetFileArray(fs);
+        } else {
+          el.value = val;
+        }
+      }.bind(this);
+
+      this.mm.addMessageListener("Marionette:setElementValue", listener);
       yield this.listener.sendKeysToElement({id: id, value: value});
+      this.mm.removeMessageListener("Marionette:setElementValue", listener);
+      if (err) {
+        throw err;
+      }
       break;
   }
 };
 
 /** Sets the test name.  The test name is used for logging purposes. */
 GeckoDriver.prototype.setTestName = function*(cmd, resp) {
   let val = cmd.parameters.value;
   this.testName = val;
--- a/testing/marionette/event.js
+++ b/testing/marionette/event.js
@@ -1301,34 +1301,34 @@ event.focus = function(el, opts = {}) {
   let win = doc.defaultView;
 
   let ev = new win.FocusEvent(el);
   ev.initEvent("focus", opts.canBubble, true);
   el.dispatchEvent(ev);
 };
 
 event.mouseover = function(el, modifiers = {}, opts = {}) {
-  return event.sendEvent("mouseover", el, modifiers, opts);
+  return event.sendEvent({type: "mouseover"}, el, modifiers, opts);
 };
 
 event.mousemove = function(el, modifiers = {}, opts = {}) {
-  return event.sendEvent("mousemove", el, modifiers, opts);
+  return event.sendEvent({type: "mousemove"}, el, modifiers, opts);
 };
 
 event.mousedown = function(el, modifiers = {}, opts = {}) {
-  return event.sendEvent("mousedown", el, modifiers, opts);
+  return event.sendEvent({type: "mousedown"}, el, modifiers, opts);
 };
 
 event.mouseup = function(el, modifiers = {}, opts = {}) {
-  return event.sendEvent("mouseup", el, modifiers, opts);
+  return event.sendEvent({type: "mouseup"}, el, modifiers, opts);
 };
 
 event.click = function(el, modifiers = {}, opts = {}) {
-  return event.sendEvent("click", el, modifiers, opts);
+  return event.sendEvent({type: "click"}, el, modifiers, opts);
 };
 
 event.change = function(el, modifiers = {}, opts = {}) {
-  return event.sendEvent("change", el, modifiers, opts);
+  return event.sendEvent({type: "change"}, el, modifiers, opts);
 };
 
 event.input = function(el, modifiers = {}, opts = {}) {
-  return event.sendEvent("input", el, modifiers, opts);
+  return event.sendEvent({type: "input"}, el, modifiers, opts);
 };
deleted file mode 100644
--- a/testing/marionette/harness/marionette/tests/unit/test_certificates.py
+++ /dev/null
@@ -1,31 +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/.
-
-from marionette import MarionetteTestCase
-from marionette_driver.errors import UnknownException
-
-
-class TestCertificates(MarionetteTestCase):
-    def test_block_insecure_sites(self):
-        self.marionette.delete_session()
-        self.marionette.start_session()
-
-        self.marionette.navigate(self.fixtures.where_is("test.html", on="http"))
-        self.assertIn("http://", self.marionette.get_url())
-        with self.assertRaises(UnknownException):
-            self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
-
-    def test_accept_all_insecure(self):
-        self.marionette.delete_session()
-        self.marionette.start_session({"desiredCapability": {"acceptSslCerts": ["*"]}})
-        self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
-        self.assertIn("https://", self.marionette.url)
-
-    """
-    def test_accept_some_insecure(self):
-        self.marionette.delete_session()
-        self.marionette.start_session({"requiredCapabilities": {"acceptSslCerts": ["127.0.0.1"]}})
-        self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
-        self.assertIn("https://", self.marionette.url)
-    """
\ No newline at end of file
--- a/testing/marionette/harness/marionette/tests/unit/test_file_upload.py
+++ b/testing/marionette/harness/marionette/tests/unit/test_file_upload.py
@@ -101,32 +101,16 @@ class TestFileUpload(MarionetteTestCase)
             f.write("camembert")
             f.flush()
             self.input.send_keys(f.name)
             self.submit.click()
 
         Wait(self.marionette).until(lambda m: m.get_url() != url)
         self.assertIn("multipart/form-data", self.body.text)
 
-    def test_change_event(self):
-        self.marionette.navigate(single)
-        self.marionette.execute_script("""
-            window.changeEvs = [];
-            let el = arguments[arguments.length - 1];
-            el.addEventListener("change", ev => window.changeEvs.push(ev));
-            console.log(window.changeEvs.length);
-            """, script_args=(self.input,), sandbox=None)
-
-        with tempfile() as f:
-            self.input.send_keys(f.name)
-
-        nevs = self.marionette.execute_script(
-            "return window.changeEvs.length", sandbox=None)
-        self.assertEqual(1, nevs)
-
     def find_inputs(self):
         return self.marionette.find_elements(By.TAG_NAME, "input")
 
     @property
     def input(self):
         return self.find_inputs()[0]
 
     @property
--- a/testing/marionette/interaction.js
+++ b/testing/marionette/interaction.js
@@ -217,43 +217,16 @@ interaction.selectOption = function(el) 
   el.selected = !el.selected;
 
   event.change(parent);
   event.mouseup(parent);
   event.click(parent);
 };
 
 /**
- * Appends |path| to an <input type=file>'s file list.
- *
- * @param {HTMLInputElement} el
- *     An <input type=file> element.
- * @param {File} file
- *     File object to assign to |el|.
- */
-interaction.uploadFile = function(el, file) {
-  let fs = Array.prototype.slice.call(el.files);
-  fs.push(file);
-
-  // <input type=file> opens OS widget dialogue
-  // which means the mousedown/focus/mouseup/click events
-  // occur before the change event
-  event.mouseover(el);
-  event.mousemove(el);
-  event.mousedown(el);
-  event.focus(el);
-  event.mouseup(el);
-  event.click(el);
-
-  el.mozSetFileArray(fs);
-
-  event.change(el);
-};
-
-/**
  * Locate the <select> element that encapsulate an <option> element.
  *
  * @param {HTMLOptionElement} optionEl
  *     Option element.
  *
  * @return {HTMLSelectElement}
  *     Select element wrapping |optionEl|.
  *
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -587,31 +587,30 @@ function setTestName(msg) {
   sendOk(msg.json.command_id);
 }
 
 /**
  * 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) {
+  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;
   }
-
-  interaction.uploadFile(fileInputElement, msg.json.file);
+  let fs = Array.prototype.slice.call(fileInputElement.files);
+  fs.push(msg.json.file);
+  fileInputElement.mozSetFileArray(fs);
   fileInputElement = null;
-
   sendOk(msg.json.command_id);
 }
 
 /**
  * This function creates a touch event given a touch type and a touch
  */
 function emitTouchEvent(type, touch) {
   if (!wasInterrupted()) {