Backed out changeset 952f0a7824ad (bug 1335539)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 21 Feb 2017 10:30:06 +0100
changeset 372982 e0f8fed311048a4028d8078ca84f2e4fa5c1c403
parent 372981 edfe5b5d3b8b6288b7908e22a3abf1b04d00eff2
child 372983 e3c55cc9ffa36a578224bbcdd0c4b2c8a886908a
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1335539
milestone54.0a1
backs out952f0a7824ad897dd0f76318b567341e7d8ad46d
Backed out changeset 952f0a7824ad (bug 1335539)
browser/base/content/test/general/browser_extension_permissions.js
browser/base/content/test/general/browser_save_link-perwindowpb.js
browser/base/content/test/general/browser_save_link_when_window_navigates.js
browser/base/content/test/general/browser_save_private_link_perwindowpb.js
browser/base/content/test/general/browser_save_video.js
browser/base/content/test/general/browser_save_video_frame.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
devtools/client/aboutdebugging/test/browser_addons_install.js
devtools/client/aboutdebugging/test/head.js
devtools/client/webide/test/test_simulators.html
dom/base/nsDOMWindowUtils.cpp
dom/base/test/mochitest.ini
dom/base/test/test_bug793311.html
dom/file/FileBlobImpl.h
dom/file/FileCreatorHelper.cpp
dom/file/FileCreatorHelper.h
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/tests/test_bug1086684.html
dom/webidl/File.webidl
layout/forms/test/test_bug536567_perwindowpb.html
mobile/android/components/FilePicker.js
testing/specialpowers/content/MockFilePicker.jsm
toolkit/components/extensions/test/mochitest/test_chrome_ext_downloads_saveAs.html
toolkit/components/filepicker/nsFilePicker.js
toolkit/components/tooltiptext/tests/browser_input_file_tooltips.js
toolkit/content/tests/browser/browser_save_resend_postdata.js
toolkit/mozapps/extensions/test/browser/browser_bug567127.js
toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js
--- a/browser/base/content/test/general/browser_extension_permissions.js
+++ b/browser/base/content/test/general/browser_extension_permissions.js
@@ -102,24 +102,24 @@ const INSTALL_FUNCTIONS = [
                                        .getService(Ci.nsIChromeRegistry);
     let chromeUrl = Services.io.newURI(gTestPath);
     let fileUrl = ChromeRegistry.convertChromeURL(chromeUrl);
     let file = fileUrl.QueryInterface(Ci.nsIFileURL).file;
     file.leafName = filename;
 
     let MockFilePicker = SpecialPowers.MockFilePicker;
     MockFilePicker.init(window);
-    MockFilePicker.setFiles([file]);
-    MockFilePicker.afterOpenCallback = MockFilePicker.cleanup;
+    MockFilePicker.returnFiles = [file];
 
     await BrowserOpenAddonsMgr("addons://list/extension");
     let contentWin = gBrowser.selectedTab.linkedBrowser.contentWindow;
 
     // Do the install...
     contentWin.gViewController.doCommand("cmd_installFromFile");
+    MockFilePicker.cleanup();
   },
 
   async function installSearch(filename) {
     await SpecialPowers.pushPrefEnv({set: [
       ["extensions.getAddons.maxResults", 10],
       ["extensions.getAddons.search.url", `${BASE}/browser_webext_search.xml`],
     ]});
 
--- a/browser/base/content/test/general/browser_save_link-perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_link-perwindowpb.js
@@ -35,17 +35,17 @@ function triggerSave(aWindow, aCallback)
     var destFile = destDir.clone();
 
     MockFilePicker.displayDirectory = destDir;
     MockFilePicker.showCallback = function(fp) {
       info("showCallback");
       fileName = fp.defaultString;
       info("fileName: " + fileName);
       destFile.append(fileName);
-      MockFilePicker.setFiles([destFile]);
+      MockFilePicker.returnFiles = [destFile];
       MockFilePicker.filterIndex = 1; // kSaveAsType_URL
       info("done showCallback");
     };
 
     mockTransferCallback = function(downloadSuccess) {
       info("mockTransferCallback");
       onTransferComplete(aWindow, downloadSuccess, destDir);
       destDir.remove(true);
--- a/browser/base/content/test/general/browser_save_link_when_window_navigates.js
+++ b/browser/base/content/test/general/browser_save_link_when_window_navigates.js
@@ -40,17 +40,17 @@ function triggerSave(aWindow, aCallback)
   var destFile = destDir.clone();
 
   MockFilePicker.displayDirectory = destDir;
   MockFilePicker.showCallback = function(fp) {
     info("showCallback");
     fileName = fp.defaultString;
     info("fileName: " + fileName);
     destFile.append(fileName);
-    MockFilePicker.setFiles([destFile]);
+    MockFilePicker.returnFiles = [destFile];
     MockFilePicker.filterIndex = 1; // kSaveAsType_URL
     info("done showCallback");
   };
 
   mockTransferCallback = function(downloadSuccess) {
     info("mockTransferCallback");
     onTransferComplete(aWindow, downloadSuccess, destDir);
     destDir.remove(true);
--- a/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
@@ -53,17 +53,17 @@ function promiseImageDownloaded() {
     // Create the folder the image will be saved into.
     var destDir = createTemporarySaveDirectory();
     var destFile = destDir.clone();
 
     MockFilePicker.displayDirectory = destDir;
     MockFilePicker.showCallback = function(fp) {
       fileName = fp.defaultString;
       destFile.append(fileName);
-      MockFilePicker.setFiles([destFile]);
+      MockFilePicker.returnFiles = [destFile];
       MockFilePicker.filterIndex = 1; // kSaveAsType_URL
     };
 
     mockTransferCallback = onTransferComplete;
     mockTransferRegisterer.register();
 
     registerCleanupFunction(function() {
       mockTransferCallback = null;
--- a/browser/base/content/test/general/browser_save_video.js
+++ b/browser/base/content/test/general/browser_save_video.js
@@ -29,17 +29,17 @@ add_task(function* () {
   // Create the folder the video will be saved into.
   var destDir = createTemporarySaveDirectory();
   var destFile = destDir.clone();
 
   MockFilePicker.displayDirectory = destDir;
   MockFilePicker.showCallback = function(fp) {
     fileName = fp.defaultString;
     destFile.append(fileName);
-    MockFilePicker.setFiles([destFile]);
+    MockFilePicker.returnFiles = [destFile];
     MockFilePicker.filterIndex = 1; // kSaveAsType_URL
   };
 
   let transferCompletePromise = new Promise((resolve) => {
     function onTransferComplete(downloadSuccess) {
       ok(downloadSuccess, "Video file should have been downloaded successfully");
 
       is(fileName, "web-video1-expectedName.ogv",
--- a/browser/base/content/test/general/browser_save_video_frame.js
+++ b/browser/base/content/test/general/browser_save_video_frame.js
@@ -80,17 +80,17 @@ add_task(function*() {
 
   // Create the folder the video will be saved into.
   let destDir = createTemporarySaveDirectory();
   let destFile = destDir.clone();
 
   MockFilePicker.displayDirectory = destDir;
   MockFilePicker.showCallback = function(fp) {
     destFile.append(fp.defaultString);
-    MockFilePicker.setFiles([destFile]);
+    MockFilePicker.returnFiles = [destFile];
     MockFilePicker.filterIndex = 1; // kSaveAsType_URL
   };
 
   mockTransferRegisterer.register();
 
   // Make sure that we clean these things up when we're done.
   registerCleanupFunction(function() {
     mockTransferRegisterer.unregister();
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
@@ -50,17 +50,17 @@ function test() {
                            aGlobalLastDir, aCallback) {
     // Check lastDir preference.
     is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
        "LastDir should be the expected display dir");
     // Check gDownloadLastDir value.
     is(gDownloadLastDir.file.path, aDisplayDir.path,
        "gDownloadLastDir should be the expected display dir");
 
-    MockFilePicker.setFiles([aFile]);
+    MockFilePicker.returnFiles = [aFile];
     MockFilePicker.displayDirectory = null;
 
     launcher.saveDestinationAvailable = function (file) {
       ok(!!file, "promptForSaveToFile correctly returned a file");
 
       // File picker should start with expected display dir.
       is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
         "File picker should start with browser.download.lastDir");
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
@@ -57,17 +57,17 @@ function test() {
                            aGlobalLastDir, aCallback) {
     // Check lastDir preference.
     is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
        "LastDir should be the expected display dir");
     // Check gDownloadLastDir value.
     is(gDownloadLastDir.file.path, aDisplayDir.path,
        "gDownloadLastDir should be the expected display dir");
 
-    MockFilePicker.setFiles([aFile]);
+    MockFilePicker.returnFiles = [aFile];
     MockFilePicker.displayDirectory = null;
     aWin.promiseTargetFile(params).then(function() {
       // File picker should start with expected display dir.
       is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
          "File picker should start with browser.download.lastDir");
       // browser.download.lastDir should be modified on not private windows
       is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
          "LastDir should be the expected last dir");
--- a/devtools/client/aboutdebugging/test/browser_addons_install.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_install.js
@@ -18,29 +18,29 @@ add_task(function* () {
 
   // Install the add-on, and verify that it disappears in the about:debugging UI
   yield uninstallAddon({document, id: ADDON_ID, name: ADDON_NAME});
 
   yield closeAboutDebugging(tab);
 });
 
 add_task(function* () {
-  let { tab, document, window } = yield openAboutDebugging("addons");
+  let { tab, document } = yield openAboutDebugging("addons");
   yield waitForInitialAddonList(document);
 
   // Start an observer that looks for the install error before
   // actually doing the install
   let top = document.querySelector(".addons-top");
   let promise = waitForMutation(top, { childList: true });
 
   // Mock the file picker to select a test addon
   let MockFilePicker = SpecialPowers.MockFilePicker;
-  MockFilePicker.init(window);
+  MockFilePicker.init(null);
   let file = getSupportsFile("addons/bad/manifest.json");
-  MockFilePicker.setFiles([file.file]);
+  MockFilePicker.returnFiles = [file.file];
 
   // Trigger the file picker by clicking on the button
   document.getElementById("load-addon-from-file").click();
 
   // Now wait for the install error to appear.
   yield promise;
 
   // And check that it really is there.
--- a/devtools/client/aboutdebugging/test/head.js
+++ b/devtools/client/aboutdebugging/test/head.js
@@ -30,23 +30,22 @@ function* openAboutDebugging(page, win) 
   let url = "about:debugging";
   if (page) {
     url += "#" + page;
   }
 
   let tab = yield addTab(url, { window: win });
   let browser = tab.linkedBrowser;
   let document = browser.contentDocument;
-  let window = browser.contentWindow;
 
   if (!document.querySelector(".app")) {
     yield waitForMutation(document.body, { childList: true });
   }
 
-  return { tab, document, window };
+  return { tab, document };
 }
 
 /**
  * Change url hash for current about:debugging tab, return a promise after
  * new content is loaded.
  * @param  {DOMDocument}  document   container document from current tab
  * @param  {String}       hash       hash for about:debugging
  * @return {Promise}
@@ -111,17 +110,17 @@ function getTabList(document) {
     document.querySelector("#tabs.targets");
 }
 
 function* installAddon({document, path, name, isWebExtension}) {
   // Mock the file picker to select a test addon
   let MockFilePicker = SpecialPowers.MockFilePicker;
   MockFilePicker.init(window);
   let file = getSupportsFile(path);
-  MockFilePicker.setFiles([file.file]);
+  MockFilePicker.returnFiles = [file.file];
 
   let addonList = getAddonList(document);
   let addonListMutation = waitForMutation(addonList, { childList: true });
 
   let onAddonInstalled;
 
   if (isWebExtension) {
     onAddonInstalled = new Promise(done => {
--- a/devtools/client/webide/test/test_simulators.html
+++ b/devtools/client/webide/test/test_simulators.html
@@ -185,28 +185,28 @@
 
           yield set(form.version, sim20.addonID);
 
           ok(!form.version.classList.contains("custom"), "Version selector is not customized after addon change");
           is(form.name.value, customName + "2.0", "Simulator name was updated to new version");
 
           // Pick custom binary, but act like the user aborted the file picker.
 
-          MockFilePicker.setFiles([]);
+          MockFilePicker.returnFiles = [];
           yield set(form.version, "pick");
 
           is(form.version.value, sim20.addonID, "Version selector reverted to last valid choice after customization abort");
           ok(!form.version.classList.contains("custom"), "Version selector is not customized after customization abort");
 
           // Pick custom binary, and actually follow through. (success, verify value = "custom" and textContent = custom path)
 
-          yield MockFilePicker.useAnyFile();
+          MockFilePicker.useAnyFile();
           yield set(form.version, "pick");
 
-          let fakeBinary = MockFilePicker.file;
+          let fakeBinary = MockFilePicker.returnFiles[0];
 
           ok(form.version.value == "custom", "Version selector was set to a new custom binary");
           ok(form.version.classList.contains("custom"), "Version selector is now customized");
           is(form.version.selectedOptions[0].textContent, fakeBinary.path, "Custom option textContent is correct");
 
           yield set(form.version, sim10.addonID);
 
           ok(form.version.classList.contains("custom"), "Version selector remains customized after change back to addon");
@@ -216,25 +216,25 @@
 
           ok(form.version.value == "custom", "Version selector is back to custom");
 
           // Test `profile`.
 
           is(form.profile.value, "default", "Default simulator profile");
           ok(!form.profile.classList.contains("custom"), "Profile selector is not customized");
 
-          MockFilePicker.setFiles([]);
+          MockFilePicker.returnFiles = [];
           yield set(form.profile, "pick");
 
           is(form.profile.value, "default", "Profile selector reverted to last valid choice after customization abort");
           ok(!form.profile.classList.contains("custom"), "Profile selector is not customized after customization abort");
 
           let fakeProfile = FileUtils.getDir("TmpD", []);
 
-          MockFilePicker.setFiles([ fakeProfile ]);
+          MockFilePicker.returnFiles = [ fakeProfile ];
           yield set(form.profile, "pick");
 
           ok(form.profile.value == "custom", "Profile selector was set to a new custom directory");
           ok(form.profile.classList.contains("custom"), "Profile selector is now customized");
           is(form.profile.selectedOptions[0].textContent, fakeProfile.path, "Custom option textContent is correct");
 
           yield set(form.profile, "default");
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2805,16 +2805,37 @@ nsDOMWindowUtils::GetContainerElement(ns
 
   nsCOMPtr<nsIDOMElement> element =
     do_QueryInterface(window->GetFrameElementInternal());
 
   element.forget(aResult);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
+                              nsISupports **aDOMFile)
+{
+  if (!aFile) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
+  if (!innerWindow) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIDOMBlob> blob = File::CreateFromFile(innerWindow, aFile);
+  blob.forget(aDOMFile);
+  return NS_OK;
+}
+
 #ifdef DEBUG
 static bool
 CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)
 {
   gfx::Matrix transform;
   if (!aLayer->GetTransform().Is2D(&transform) ||
       transform.HasNonIntegerTranslation())
     return false;
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -527,16 +527,17 @@ skip-if = toolkit == 'android' #bug 6870
 [test_bug750096.html]
 [test_bug753278.html]
 [test_bug761120.html]
 [test_bug769117.html]
 [test_bug782342.html]
 [test_bug787778.html]
 [test_bug789315.html]
 [test_bug789856.html]
+[test_bug793311.html]
 [test_bug804395.html]
 [test_bug809003.html]
 [test_bug810494.html]
 [test_bug811701.html]
 [test_bug811701.xhtml]
 [test_bug813919.html]
 [test_bug814576.html]
 [test_bug819051.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug793311.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=793311
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 793311</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug {793311} **/
+  SimpleTest.waitForExplicitFinish();
+
+  try {
+    SpecialPowers.DOMWindowUtils.wrapDOMFile(null);
+    ok(false, "wrapDOMFile(null) throws an exception");
+  } catch(e) {
+    ok(true, "wrapDOMFile(null) throws an exception");
+  }
+  SimpleTest.finish();
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=793311">Mozilla Bug 793311</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/dom/file/FileBlobImpl.h
+++ b/dom/file/FileBlobImpl.h
@@ -45,26 +45,16 @@ public:
                                  ErrorResult& aRv) override;
 
   virtual bool IsDirectory() const override;
 
   // We always have size and date for this kind of blob.
   virtual bool IsSizeUnknown() const override { return false; }
   virtual bool IsDateUnknown() const override { return false; }
 
-  void SetName(const nsAString& aName)
-  {
-    mName = aName;
-  }
-
-  void SetType(const nsAString& aType)
-  {
-    mContentType = aType;
-  }
-
 protected:
   virtual ~FileBlobImpl() = default;
 
 private:
   // Create slice
   FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
                uint64_t aLength, const nsAString& aContentType);
 
--- a/dom/file/FileCreatorHelper.cpp
+++ b/dom/file/FileCreatorHelper.cpp
@@ -77,18 +77,17 @@ FileCreatorHelper::CreateFileInternal(ns
   int64_t lastModified = 0;
   if (aBag.mLastModified.WasPassed()) {
     lastModifiedPassed = true;
     lastModified = aBag.mLastModified.Value();
   }
 
   RefPtr<BlobImpl> blobImpl;
   aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
-                       lastModified, aBag.mExistenceCheck, aIsFromNsIFile,
-                       getter_AddRefs(blobImpl));
+                       lastModified, aIsFromNsIFile, getter_AddRefs(blobImpl));
   if (aRv.Failed()) {
      return nullptr;
   }
 
   RefPtr<File> file = File::Create(aWindow, blobImpl);
   return file.forget();
 }
 
@@ -126,18 +125,17 @@ FileCreatorHelper::SendRequest(nsIFile* 
 
   nsAutoString path;
   aRv = aFile->GetPath(path);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
-                          aBag.mLastModified, aBag.mExistenceCheck,
-                          aIsFromNsIFile);
+                          aBag.mLastModified, aIsFromNsIFile);
 }
 
 void
 FileCreatorHelper::ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv)
 {
   if (NS_FAILED(aRv)) {
     mPromise->MaybeReject(aRv);
     return;
@@ -148,59 +146,38 @@ FileCreatorHelper::ResponseReceived(Blob
 }
 
 /* static */ nsresult
 FileCreatorHelper::CreateBlobImplForIPC(const nsAString& aPath,
                                         const nsAString& aType,
                                         const nsAString& aName,
                                         bool aLastModifiedPassed,
                                         int64_t aLastModified,
-                                        bool aExistenceCheck,
                                         bool aIsFromNsIFile,
                                         BlobImpl** aBlobImpl)
 {
   nsCOMPtr<nsIFile> file;
   nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
-                        aExistenceCheck, aIsFromNsIFile, aBlobImpl);
+                        aIsFromNsIFile, aBlobImpl);
 }
 
 /* static */ nsresult
 FileCreatorHelper::CreateBlobImpl(nsIFile* aFile,
                                   const nsAString& aType,
                                   const nsAString& aName,
                                   bool aLastModifiedPassed,
                                   int64_t aLastModified,
-                                  bool aExistenceCheck,
                                   bool aIsFromNsIFile,
                                   BlobImpl** aBlobImpl)
 {
-  if (!aExistenceCheck) {
-    RefPtr<FileBlobImpl> impl = new FileBlobImpl(aFile);
-
-    if (!aName.IsEmpty()) {
-      impl->SetName(aName);
-    }
-
-    if (!aType.IsEmpty()) {
-      impl->SetType(aType);
-    }
-
-    if (aLastModifiedPassed) {
-      impl->SetLastModified(aLastModified);
-    }
-
-    impl.forget(aBlobImpl);
-    return NS_OK;
-  }
-
   RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
   nsresult rv =
     impl->InitializeChromeFile(aFile, aType, aName, aLastModifiedPassed,
                                aLastModified, aIsFromNsIFile);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
--- a/dom/file/FileCreatorHelper.h
+++ b/dom/file/FileCreatorHelper.h
@@ -46,17 +46,16 @@ public:
 
   // For IPC only
   static nsresult
   CreateBlobImplForIPC(const nsAString& aPath,
                        const nsAString& aType,
                        const nsAString& aName,
                        bool aLastModifiedPassed,
                        int64_t aLastModified,
-                       bool aExistenceCheck,
                        bool aIsFromNsIFile,
                        BlobImpl** aBlobImpl);
 
 private:
   static already_AddRefed<File>
   CreateFileInternal(nsPIDOMWindowInner* aWindow,
                      nsIFile* aFile,
                      const ChromeFilePropertyBag& aBag,
@@ -64,17 +63,16 @@ private:
                      ErrorResult& aRv);
 
   static nsresult
   CreateBlobImpl(nsIFile* aFile,
                  const nsAString& aType,
                  const nsAString& aName,
                  bool aLastModifiedPassed,
                  int64_t aLastModified,
-                 bool aExistenceCheck,
                  bool aIsFromNsIFile,
                  BlobImpl** aBlobImpl);
 
   FileCreatorHelper(Promise* aPromise, nsPIDOMWindowInner* aWindow);
   ~FileCreatorHelper();
 
   void
   SendRequest(nsIFile* aFile, const ChromeFilePropertyBag& aBag,
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1559,16 +1559,22 @@ interface nsIDOMWindowUtils : nsISupport
    * property.
    */
   double computeAnimationDistance(in nsIDOMElement element,
                                   in AString property,
                                   in AString value1,
                                   in AString value2);
 
   /**
+   * Wrap an nsIFile in an DOM File
+   * Returns a File object.
+   */
+  nsISupports wrapDOMFile(in nsIFile aFile);
+
+  /**
    * Get the type of the currently focused html input, if any.
    */
   readonly attribute string focusedInputType;
 
   /**
    * Find the view ID for a given element. This is the reverse of
    * findElementWithViewId().
    */
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -3170,32 +3170,30 @@ ContentChild::GetConstructedEventTarget(
 }
 
 void
 ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
                                   const nsAString& aFullPath,
                                   const nsAString& aType,
                                   const nsAString& aName,
                                   const Optional<int64_t>& aLastModified,
-                                  bool aExistenceCheck,
                                   bool aIsFromNsIFile)
 {
   MOZ_ASSERT(aHelper);
 
   bool lastModifiedPassed = false;
   int64_t lastModified = 0;
   if (aLastModified.WasPassed()) {
     lastModifiedPassed = true;
     lastModified = aLastModified.Value();
   }
 
   Unused << SendFileCreationRequest(aUUID, nsString(aFullPath), nsString(aType),
                                     nsString(aName), lastModifiedPassed,
-                                    lastModified, aExistenceCheck,
-                                    aIsFromNsIFile);
+                                    lastModified, aIsFromNsIFile);
   mFileCreationPending.Put(aUUID, aHelper);
 }
 
 mozilla::ipc::IPCResult
 ContentChild::RecvFileCreationResponse(const nsID& aUUID,
                                        const FileCreationResult& aResult)
 {
   FileCreatorHelper* helper = mFileCreationPending.GetWeak(aUUID);
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -628,17 +628,17 @@ public:
                                              base::ProcessId aOtherPid);
 
   // This method is used by FileCreatorHelper for the creation of a BlobImpl.
   void
   FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
                       const nsAString& aFullPath, const nsAString& aType,
                       const nsAString& aName,
                       const Optional<int64_t>& aLastModified,
-                      bool aExistenceCheck, bool aIsFromNsIFile);
+                      bool aIsFromNsIFile);
 
 private:
   static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
   void StartForceKillTimer();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   virtual void ProcessingError(Result aCode, const char* aReason) override;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4982,25 +4982,23 @@ ContentParent::RecvClassifyLocal(const U
 
 mozilla::ipc::IPCResult
 ContentParent::RecvFileCreationRequest(const nsID& aID,
                                        const nsString& aFullPath,
                                        const nsString& aType,
                                        const nsString& aName,
                                        const bool& aLastModifiedPassed,
                                        const int64_t& aLastModified,
-                                       const bool& aExistenceCheck,
                                        const bool& aIsFromNsIFile)
 {
   RefPtr<BlobImpl> blobImpl;
   nsresult rv =
     FileCreatorHelper::CreateBlobImplForIPC(aFullPath, aType, aName,
                                             aLastModifiedPassed,
-                                            aLastModified, aExistenceCheck,
-                                            aIsFromNsIFile,
+                                            aLastModified, aIsFromNsIFile,
                                             getter_AddRefs(blobImpl));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
       return IPC_FAIL_NO_REASON(this);
     }
 
     return IPC_OK();
   }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1106,17 +1106,16 @@ private:
 
   virtual mozilla::ipc::IPCResult RecvDeleteGetFilesRequest(const nsID& aID) override;
 
   virtual mozilla::ipc::IPCResult
   RecvFileCreationRequest(const nsID& aID, const nsString& aFullPath,
                           const nsString& aType, const nsString& aName,
                           const bool& aLastModifiedPassed,
                           const int64_t& aLastModified,
-                          const bool& aExistenceCheck,
                           const bool& aIsFromNsIFile) override;
 
   virtual mozilla::ipc::IPCResult RecvAccumulateChildHistograms(
     InfallibleTArray<Accumulation>&& aAccumulations) override;
   virtual mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(
     InfallibleTArray<KeyedAccumulation>&& aAccumulations) override;
   virtual mozilla::ipc::IPCResult RecvUpdateChildScalars(
     InfallibleTArray<ScalarAction>&& aScalarActions) override;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -1172,18 +1172,17 @@ parent:
      */
      async NotifyLowMemory();
 
      async GetFilesRequest(nsID aID, nsString aDirectory, bool aRecursiveFlag);
      async DeleteGetFilesRequest(nsID aID);
 
      async FileCreationRequest(nsID aID, nsString aFullPath, nsString aType,
                                nsString aName, bool lastModifiedPassed,
-                               int64_t lastModified, bool aExistenceCheck,
-                               bool aIsFromNsIFile);
+                               int64_t lastModified, bool aIsFromNsIFile);
 
      async StoreAndBroadcastBlobURLRegistration(nsCString url, PBlob blob,
                                                 Principal principal);
 
      async UnstoreAndBroadcastBlobURLUnregistration(nsCString url);
 
      async BroadcastLocalStorageChange(nsString documentURI,
                                        nsString key,
--- a/dom/ipc/tests/test_bug1086684.html
+++ b/dom/ipc/tests/test_bug1086684.html
@@ -4,33 +4,33 @@
   <title>Test for recursive CPOW-getting-cookie bug</title>
   <script type="application/javascript"
           src="/tests/SimpleTest/SimpleTest.js">
   </script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 
-  <script type="application/javascript">
+  <script type="application/javascript;version=1.8">
     "use strict";
 
     SimpleTest.waitForExplicitFinish();
 
     const childFrameURL =
       "http://mochi.test:8888/tests/dom/ipc/tests/file_bug1086684.html";
 
     function childFrameScript() {
       "use strict";
 
       let { MockFilePicker } =
         Components.utils.import("chrome://specialpowers/content/MockFilePicker.jsm", {});
 
       function parentReady(message) {
         MockFilePicker.init(content);
-        MockFilePicker.setFiles([message.data.file]);
+        MockFilePicker.returnFiles = [message.data.file];
         MockFilePicker.returnValue = MockFilePicker.returnOK;
 
         let input = content.document.getElementById("f");
         input.addEventListener("change", () => {
           MockFilePicker.cleanup();
           let value = input.value;
           message.target.sendAsyncMessage("testBug1086684:childDone", { value });
         });
--- a/dom/webidl/File.webidl
+++ b/dom/webidl/File.webidl
@@ -21,17 +21,16 @@ interface File : Blob {
 
 dictionary FilePropertyBag {
   DOMString type = "";
   long long lastModified;
 };
 
 dictionary ChromeFilePropertyBag : FilePropertyBag {
   DOMString name = "";
-  boolean existenceCheck = true;
 };
 
 // Mozilla extensions
 partial interface File {
   [GetterThrows, Deprecated="FileLastModifiedDate"]
   readonly attribute Date lastModifiedDate;
 
   [BinaryName="relativePath", Func="mozilla::dom::Directory::WebkitBlinkDirectoryPickerEnabled"]
--- a/layout/forms/test/test_bug536567_perwindowpb.html
+++ b/layout/forms/test/test_bug536567_perwindowpb.html
@@ -111,17 +111,17 @@ function runTest() {
     runTest();
   } else if (test == "clear history") {
     Services.obs.notifyObservers(null, "browser:purge-session-history", "");
     testIndex++;
     runTest();
   } else {
     var file = dirs[test[2]].clone();
     file.append("file.file");
-    MockFilePicker.setFiles([file]);
+    MockFilePicker.returnFiles = [file];
     content.setAttribute('src', domains[test[0]] + '/chrome/layout/forms/test/bug536567_subframe.html');
   }
 }
 
 function endTest() {
   for(var i = 0; i < dirs.length - 1; i++) {
     dirs[i].remove(true);
   }
--- a/mobile/android/components/FilePicker.js
+++ b/mobile/android/components/FilePicker.js
@@ -224,23 +224,25 @@ FilePicker.prototype = {
       this._filePath = file || null;
       this._promptActive = false;
 
       if (!file) {
         return;
       }
 
       if (this._domWin) {
-        return this._domWin.File.createFromNsIFile(this.file, { existenceCheck: false });
+        let utils = this._domWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+        this._domFile = utils.wrapDOMFile(this.file);
+        return;
       }
 
-      return File.createFromNsIFile(this.file, { existenceCheck: false });
-    }).then(domFile => {
-      this._domFile = domFile;
-    }, () => {
+      return File.createFromNsIFile(this.file).then(domFile => {
+        this._domFile = domFile;
+      });
+    }).catch(() => {
     }).then(() => {
       if (this._callback) {
         this._callback.done(this._filePath ?
           Ci.nsIFilePicker.returnOK : Ci.nsIFilePicker.returnCancel);
       }
       delete this._callback;
     });
   },
--- a/testing/specialpowers/content/MockFilePicker.jsm
+++ b/testing/specialpowers/content/MockFilePicker.jsm
@@ -48,17 +48,16 @@ this.MockFilePicker = {
   filterXML: Ci.nsIFilePicker.filterXML,
   filterXUL: Ci.nsIFilePicker.filterXUL,
   filterApps: Ci.nsIFilePicker.filterApps,
   filterAllowURLs: Ci.nsIFilePicker.filterAllowURLs,
   filterAudio: Ci.nsIFilePicker.filterAudio,
   filterVideo: Ci.nsIFilePicker.filterVideo,
 
   window: null,
-  pendingPromises: [],
 
   init: function(window) {
     this.window = window;
 
     this.reset();
     this.factory = newFactory(window);
     if (!registrar.isCIDRegistered(newClassID)) {
       oldClassID = registrar.contractIDToCID(CONTRACT_ID);
@@ -69,17 +68,17 @@ this.MockFilePicker = {
   },
 
   reset: function() {
     this.appendFilterCallback = null;
     this.appendFiltersCallback = null;
     this.displayDirectory = null;
     this.filterIndex = 0;
     this.mode = null;
-    this.returnData = [];
+    this.returnFiles = [];
     this.returnValue = null;
     this.showCallback = null;
     this.afterOpenCallback = null;
     this.shown = false;
     this.showing = false;
   },
 
   cleanup: function() {
@@ -87,74 +86,42 @@ this.MockFilePicker = {
     this.reset();
     this.factory = null;
     if (oldFactory) {
       registrar.unregisterFactory(newClassID, previousFactory);
       registrar.registerFactory(oldClassID, "", CONTRACT_ID, oldFactory);
     }
   },
 
-  internalFileData(obj) {
-    return {
-      nsIFile: "nsIFile" in obj ? obj.nsIFile : null,
-      domFile: "domFile" in obj ? obj.domFile : null,
-      domDirectory: "domDirectory" in obj ? obj.domDirectory : null,
-    };
-  },
-
   useAnyFile: function() {
     var file = FileUtils.getDir("TmpD", [], false);
     file.append("testfile");
     file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
-    let promise = this.window.File.createFromNsIFile(file).then(domFile => {
-      this.returnData = [this.internalFileData({ nsIFile: file, domFile: domFile })];
-    }).then(() => file);
-
-    this.pendingPromises = [promise];
-
-    // We return a promise in order to support some existing mochitests.
-    return promise;
+    this.returnFiles = [file];
   },
 
   useBlobFile: function() {
     var blob = new this.window.Blob([]);
     var file = new this.window.File([blob], 'helloworld.txt', { type: 'plain/text' });
-    this.returnData = [this.internalFileData({ domFile: file })];
-    this.pendingPromises = [];
+    this.returnFiles = [file];
   },
 
   useDirectory: function(aPath) {
     var directory = new this.window.Directory(aPath);
-    this.returnData = [this.internalFileData({ domDirectory: directory })];
-    this.pendingPromises = [];
+    this.returnFiles = [directory];
   },
 
-  setFiles(files) {
-    this.returnData = [];
-    this.pendingPromises = [];
-
-    for (let file of files) {
-      if (file instanceof this.window.File) {
-        this.returnData.push(this.internalFileData({ domFile: file }));
-      } else {
-        let promise = this.window.File.createFromNsIFile(file, { existenceCheck: false });
+  isNsIFile: function(aFile) {
+    let ret = false;
+    try {
+      if (aFile.QueryInterface(Ci.nsIFile))
+        ret = true;
+    } catch(e) {}
 
-        promise.then(domFile => {
-          this.returnData.push(this.internalFileData({ nsIFile: file, domFile: domFile }));
-        });
-        this.pendingPromises.push(promise);
-      }
-    }
-  },
-
-  getNsIFile() {
-    if (this.returnData.length >= 1) {
-      return this.returnData[0].nsIFile;
-    }
-    return null;
+    return ret;
   }
 };
 
 function MockFilePickerInstance(window) {
   this.window = window;
 };
 MockFilePickerInstance.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]),
@@ -172,134 +139,106 @@ MockFilePickerInstance.prototype = {
       MockFilePicker.appendFiltersCallback(this, aFilterMask);
   },
   defaultString: "",
   defaultExtension: "",
   parent: null,
   filterIndex: 0,
   displayDirectory: null,
   get file() {
-    if (MockFilePicker.returnData.length >= 1) {
-      return MockFilePicker.returnData[0].nsIFile;
+    if (MockFilePicker.returnFiles.length >= 1 &&
+        // window.File does not implement nsIFile
+        MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) {
+      return MockFilePicker.returnFiles[0];
     }
 
     return null;
   },
 
   // We don't support directories here.
   get domFileOrDirectory()  {
-    if (MockFilePicker.returnData.length < 1) {
-      return null;
-    }
+    if (MockFilePicker.returnFiles.length >= 1) {
+      // window.File does not implement nsIFile
+      if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) {
+        return MockFilePicker.returnFiles[0];
+      }
 
-    if (MockFilePicker.returnData[0].domFile) {
-      return MockFilePicker.returnData[0].domFile;
+      let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor)
+                             .getInterface(Ci.nsIDOMWindowUtils);
+      return utils.wrapDOMFile(MockFilePicker.returnFiles[0]);
     }
-
-    if (MockFilePicker.returnData[0].domDirectory) {
-      return MockFilePicker.returnData[0].domDirectory;
-    }
-
     return null;
   },
   get fileURL() {
-    if (MockFilePicker.returnData.length >= 1 &&
-        MockFilePicker.returnData[0].nsIFile) {
-      return Services.io.newFileURI(MockFilePicker.returnData[0].nsIFile);
+    if (MockFilePicker.returnFiles.length >= 1 &&
+        // window.File does not implement nsIFile
+        MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) {
+      return Services.io.newFileURI(MockFilePicker.returnFiles[0]);
     }
 
     return null;
   },
   get files() {
     return {
       index: 0,
       QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
       hasMoreElements: function() {
-        return this.index < MockFilePicker.returnData.length;
+        return this.index < MockFilePicker.returnFiles.length;
       },
       getNext: function() {
-        if (!MockFilePicker.returnData[this.index].nsIFile) {
+        // window.File does not implement nsIFile
+        if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) {
           return null;
         }
-        return MockFilePicker.returnData[this.index++].nsIFile;
+        return MockFilePicker.returnFiles[this.index++];
       }
     };
   },
   get domFileOrDirectoryEnumerator()  {
     let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils);
     return {
       index: 0,
       QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
       hasMoreElements: function() {
-        return this.index < MockFilePicker.returnData.length;
+        return this.index < MockFilePicker.returnFiles.length;
       },
       getNext: function() {
         // window.File does not implement nsIFile
-        if (MockFilePicker.returnData[this.index].domFile) {
-          return MockFilePicker.returnData[this.index++].domFile;
+        if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) {
+          return MockFilePicker.returnFiles[this.index++];
         }
-
-        if (MockFilePicker.returnData[this.index].domDirectory) {
-          return MockFilePicker.returnData[this.index++].domDirectory;
-        }
-
-        return null;
+        return utils.wrapDOMFile(MockFilePicker.returnFiles[this.index++]);
       }
     };
   },
   show: function() {
     throw "This is not implemented";
   },
+  _openInternal: function() {
+    MockFilePicker.displayDirectory = this.displayDirectory;
+    MockFilePicker.shown = true;
+    if (typeof MockFilePicker.showCallback == "function") {
+      var returnValue = MockFilePicker.showCallback(this);
+      if (typeof returnValue != "undefined")
+        return returnValue;
+    }
+    return MockFilePicker.returnValue;
+  },
   open: function(aFilePickerShownCallback) {
     MockFilePicker.showing = true;
-    this.window.setTimeout(() => {
-      // Maybe all the pending promises are already resolved, but we want to be sure.
-      Promise.all(MockFilePicker.pendingPromises).then(() => {
-        return Ci.nsIFilePicker.returnOK;
-      }, () => {
-        return Ci.nsIFilePicker.returnCancel;
-      }).then(result => {
-        // Nothing else has to be done.
-        MockFilePicker.pendingPromises = [];
-
-        if (result == Ci.nsIFilePicker.returnCancel) {
-          return result;
-        }
-
-        MockFilePicker.displayDirectory = this.displayDirectory;
-        MockFilePicker.shown = true;
-        if (typeof MockFilePicker.showCallback == "function") {
-          try {
-            var returnValue = MockFilePicker.showCallback(this);
-            if (typeof returnValue != "undefined") {
-              return returnValue;
-            }
-          } catch(ex) {
-            return Ci.nsIFilePicker.returnCancel;
-          }
-        }
-
-        return MockFilePicker.returnValue;
-      }).then(result => {
-        // Some additional result file can be set by the callback. Let's
-        // resolve the pending promises again.
-        return Promise.all(MockFilePicker.pendingPromises).then(() => {
-          return result;
-        }, () => {
-          return Ci.nsIFilePicker.returnCancel;
-        });
-      }).then(result => {
-        MockFilePicker.pendingPromises = [];
-
-        if (aFilePickerShownCallback) {
-          aFilePickerShownCallback.done(result);
-        }
-
-        if (typeof MockFilePicker.afterOpenCallback == "function") {
-          this.window.setTimeout(() => {
-            MockFilePicker.afterOpenCallback(this);
-          }, 0);
-        }
-      });
-    });
+    this.window.setTimeout(function() {
+      let result = Components.interfaces.nsIFilePicker.returnCancel;
+      try {
+        result = this._openInternal();
+      } catch(ex) {
+      }
+      if (aFilePickerShownCallback) {
+        aFilePickerShownCallback.done(result);
+      }
+      if (typeof MockFilePicker.afterOpenCallback == "function") {
+        this.window.setTimeout(() => {
+          MockFilePicker.afterOpenCallback(this);
+        }, 0);
+      }
+    }.bind(this), 0);
   }
 };
--- a/toolkit/components/extensions/test/mochitest/test_chrome_ext_downloads_saveAs.html
+++ b/toolkit/components/extensions/test/mochitest/test_chrome_ext_downloads_saveAs.html
@@ -30,17 +30,18 @@ add_task(function* test_downloads_saveAs
     browser.test.sendMessage("ready");
   }
 
   const {MockFilePicker} = SpecialPowers;
   const manifest = {background, manifest: {permissions: ["downloads"]}};
   const extension = ExtensionTestUtils.loadExtension(manifest);
 
   MockFilePicker.init(window);
-  const file = yield MockFilePicker.useAnyFile();
+  MockFilePicker.useAnyFile();
+  const [file] = MockFilePicker.returnFiles;
 
   yield extension.startup();
   yield extension.awaitMessage("ready");
 
   extension.sendMessage("download");
   let result = yield extension.awaitMessage("done");
 
   ok(result.ok, "downloads.download() works with saveAs");
--- a/toolkit/components/filepicker/nsFilePicker.js
+++ b/toolkit/components/filepicker/nsFilePicker.js
@@ -99,16 +99,45 @@ nsFilePicker.prototype = {
     return enumerator ? enumerator.mFiles[0] : null;
   },
 
   /* readonly attribute nsISimpleEnumerator domFileOrDirectoryEnumerator; */
   get domFileOrDirectoryEnumerator() {
     if (!this.mFilesEnumerator) {
       return null;
     }
+
+    if (!this.mDOMFilesEnumerator) {
+      this.mDOMFilesEnumerator = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISimpleEnumerator]),
+
+        mFiles: [],
+        mIndex: 0,
+
+        hasMoreElements() {
+          return (this.mIndex < this.mFiles.length);
+        },
+
+        getNext() {
+          if (this.mIndex >= this.mFiles.length) {
+            throw Components.results.NS_ERROR_FAILURE;
+          }
+          return this.mFiles[this.mIndex++];
+        }
+      };
+
+      var utils = this.mParentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                                    .getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+      for (var i = 0; i < this.mFilesEnumerator.mFiles.length; ++i) {
+        var file = utils.wrapDOMFile(this.mFilesEnumerator.mFiles[i]);
+        this.mDOMFilesEnumerator.mFiles.push(file);
+      }
+    }
+
     return this.mDOMFilesEnumerator;
   },
 
   /* readonly attribute nsIURI fileURL; */
   get fileURL() {
     if (this.mFileURL)
       return this.mFileURL;
 
@@ -196,64 +225,26 @@ nsFilePicker.prototype = {
   appendFilter(title, extensions) {
     this.mFilterTitles.push(title);
     this.mFilters.push(extensions);
   },
 
   open(aFilePickerShownCallback) {
     var tm = Components.classes["@mozilla.org/thread-manager;1"]
                        .getService(Components.interfaces.nsIThreadManager);
-    tm.mainThread.dispatch(() => {
+    tm.mainThread.dispatch(function() {
       let result = Components.interfaces.nsIFilePicker.returnCancel;
       try {
         result = this.show();
       } catch (ex) {
       }
-
-      let promises = [];
-
-      // Let's create the DOMFileEnumerator right now because it requires some
-      // async operation.
-      if (this.mFilesEnumerator) {
-        this.mDOMFilesEnumerator = {
-          QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISimpleEnumerator]),
-
-          mFiles: [],
-          mIndex: 0,
-
-          hasMoreElements() {
-            return (this.mIndex < this.mFiles.length);
-          },
-
-          getNext() {
-            if (this.mIndex >= this.mFiles.length) {
-              throw Components.results.NS_ERROR_FAILURE;
-            }
-            return this.mFiles[this.mIndex++];
-          }
-        };
-
-        for (let i = 0; i < this.mFilesEnumerator.mFiles.length; ++i) {
-          if (this.mFilesEnumerator.mFiles[i].exists()) {
-            let promise =
-              this.mParentWindow.File.createFromNsIFile(
-                this.mFilesEnumerator.mFiles[i]).then(file => {
-                  this.mDOMFilesEnumerator.mFiles.push(file);
-                });
-            promises.push(promise);
-          }
-        }
+      if (aFilePickerShownCallback) {
+        aFilePickerShownCallback.done(result);
       }
-
-      Promise.all(promises).then(() => {
-        if (aFilePickerShownCallback) {
-          aFilePickerShownCallback.done(result);
-        }
-      });
-    }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
+    }.bind(this), Components.interfaces.nsIThread.DISPATCH_NORMAL);
   },
 
   show() {
     var o = {};
     o.title = this.mTitle;
     o.mode = this.mMode;
     o.displayDirectory = this.mDisplayDirectory;
     o.defaultString = this.mDefaultString;
--- a/toolkit/components/tooltiptext/tests/browser_input_file_tooltips.js
+++ b/toolkit/components/tooltiptext/tests/browser_input_file_tooltips.js
@@ -58,31 +58,32 @@ function* do_test(test) {
   });
 
   if (test.value) {
     info("Creating mock filepicker to select files");
     let MockFilePicker = SpecialPowers.MockFilePicker;
     MockFilePicker.init(window);
     MockFilePicker.returnValue = MockFilePicker.returnOK;
     MockFilePicker.displayDirectory = FileUtils.getDir("TmpD", [], false);
-    MockFilePicker.setFiles([tempFile]);
-    MockFilePicker.afterOpenCallback = MockFilePicker.cleanup;
+    MockFilePicker.returnFiles = [tempFile];
 
     try {
       // Open the File Picker dialog (MockFilePicker) to select
       // the files for the test.
       yield BrowserTestUtils.synthesizeMouseAtCenter("#test_input", {}, tab.linkedBrowser);
       info("Waiting for the input to have the requisite files");
       yield ContentTask.spawn(tab.linkedBrowser, {}, function*() {
         let input = content.document.querySelector("#test_input");
         yield ContentTaskUtils.waitForCondition(() => input.files.length,
           "The input should have at least one file selected");
         info(`The input has ${input.files.length} file(s) selected.`);
       });
-    } catch (e) {}
+    } finally {
+      MockFilePicker.cleanup();
+    }
   } else {
     info("No real file selection required.");
   }
 
   let awaitTooltipOpen = new Promise(resolve => {
     let tooltipId = Services.appinfo.browserTabsRemoteAutostart ?
                       "remoteBrowserTooltip" :
                       "aHTMLTooltip";
--- a/toolkit/content/tests/browser/browser_save_resend_postdata.js
+++ b/toolkit/content/tests/browser/browser_save_resend_postdata.js
@@ -48,17 +48,17 @@ function test() {
 
   function handleInnerSubmit() {
     gBrowser.removeEventListener("DOMContentLoaded", handleInnerSubmit);
 
     // Create the folder the page will be saved into.
     var destDir = createTemporarySaveDirectory();
     var file = destDir.clone();
     file.append("no_default_file_name");
-    MockFilePicker.setFiles([file]);
+    MockFilePicker.returnFiles = [file];
     MockFilePicker.showCallback = function(fp) {
       MockFilePicker.filterIndex = 1; // kSaveAsType_URL
     };
 
     mockTransferCallback = onTransferComplete;
     mockTransferRegisterer.register();
 
     registerCleanupFunction(function() {
@@ -75,17 +75,17 @@ function test() {
                  docToSave.referrer ? makeURI(docToSave.referrer) : null,
                  docToSave, false, null);
   }
 
   function onTransferComplete(downloadSuccess) {
     ok(downloadSuccess, "The inner frame should have been downloaded successfully");
 
     // Read the entire saved file.
-    var file = MockFilePicker.getNsIFile();
+    var file = MockFilePicker.returnFiles[0];
     var fileContents = readShortFile(file);
 
     // Check if outer POST data is found (bug 471962).
     is(fileContents.indexOf("inputfield=outer"), -1,
        "The saved inner frame does not contain outer POST data");
 
     // Check if inner POST data is found (bug 485196).
     isnot(fileContents.indexOf("inputfield=inner"), -1,
--- a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js
@@ -86,17 +86,17 @@ function checkInstallConfirmation(...url
 
 add_task(function* test_install_from_file() {
   gManagerWindow = yield open_manager("addons://list/extension");
 
   var filePaths = [
                    get_addon_file_url("browser_bug567127_1.xpi"),
                    get_addon_file_url("browser_bug567127_2.xpi")
                   ];
-  MockFilePicker.setFiles(filePaths.map(aPath => aPath.file));
+  MockFilePicker.returnFiles = filePaths.map(aPath => aPath.file);
 
   // Set handler that executes the core test after the window opens,
   // and resolves the promise when the window closes
   let pInstallURIClosed = checkInstallConfirmation(...filePaths.map(path => path.spec));
 
   gManagerWindow.gViewController.doCommand("cmd_installFromFile");
 
   yield pInstallURIClosed;
--- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
@@ -282,31 +282,31 @@ add_test(function() {
     input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input");
     is(input.value, "", "Label value should be empty");
     is(input.tooltipText, "", "Label tooltip should be empty");
 
     var testFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
     testFile.append("\u2622");
     var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile);
 
-    MockFilePicker.setFiles([testFile]);
+    MockFilePicker.returnFiles = [testFile];
     MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
 
     let promise = new Promise(resolve => {
       MockFilePicker.afterOpenCallback = resolve;
       EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
     });
 
     promise.then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
       is(input.value, testFile.path, "Label value should match file chosen");
       is(input.tooltipText, testFile.path, "Label tooltip should match file chosen");
       is(Preferences.get("extensions.inlinesettings1.file", "wrong"), testFile.path, "File pref should match file chosen");
 
-      MockFilePicker.setFiles([curProcD]);
+      MockFilePicker.returnFiles = [curProcD];
       MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
 
       return new Promise(resolve => {
         MockFilePicker.afterOpenCallback = resolve;
         EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
       });
     }).then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
@@ -315,30 +315,30 @@ add_test(function() {
       is(Preferences.get("extensions.inlinesettings1.file", "wrong"), testFile.path, "File pref should not have changed");
 
       ok(!settings[7].hasAttribute("first-row"), "Not the first row");
       button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button");
       input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input");
       is(input.value, "", "Label value should be empty");
       is(input.tooltipText, "", "Label tooltip should be empty");
 
-      MockFilePicker.setFiles([testFile]);
+      MockFilePicker.returnFiles = [testFile];
       MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
 
       return new Promise(resolve => {
         MockFilePicker.afterOpenCallback = resolve;
         EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
       });
     }).then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
       is(input.value, testFile.path, "Label value should match file chosen");
       is(input.tooltipText, testFile.path, "Label tooltip should match file chosen");
       is(Preferences.get("extensions.inlinesettings1.directory", "wrong"), testFile.path, "Directory pref should match file chosen");
 
-      MockFilePicker.setFiles([curProcD]);
+      MockFilePicker.returnFiles = [curProcD];
       MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
 
       return new Promise(resolve => {
         MockFilePicker.afterOpenCallback = resolve;
         EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
       });
     }).then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
--- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js
@@ -277,31 +277,31 @@ add_test(function() {
 
     input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input");
     is(input.value, "", "Label value should be empty");
     is(input.tooltipText, "", "Label tooltip should be empty");
 
     var profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
     var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile);
 
-    MockFilePicker.setFiles([profD]);
+    MockFilePicker.returnFiles = [profD];
     MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
 
     let promise = new Promise(resolve => {
       MockFilePicker.afterOpenCallback = resolve;
       EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
     });
 
     promise.then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
       is(input.value, profD.path, "Label value should match file chosen");
       is(input.tooltipText, profD.path, "Label tooltip should match file chosen");
       is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen");
 
-      MockFilePicker.setFiles([curProcD]);
+      MockFilePicker.returnFiles = [curProcD];
       MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
 
       return promise = new Promise(resolve => {
         MockFilePicker.afterOpenCallback = resolve;
         EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
       });
     }).then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
@@ -310,30 +310,30 @@ add_test(function() {
       is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed");
 
       ok(!settings[7].hasAttribute("first-row"), "Not the first row");
       button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button");
       input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input");
       is(input.value, "", "Label value should be empty");
       is(input.tooltipText, "", "Label tooltip should be empty");
 
-      MockFilePicker.setFiles([profD]);
+      MockFilePicker.returnFiles = [profD];
       MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
 
       return new Promise(resolve => {
         MockFilePicker.afterOpenCallback = resolve;
         EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
       });
     }).then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
       is(input.value, profD.path, "Label value should match file chosen");
       is(input.tooltipText, profD.path, "Label tooltip should match file chosen");
       is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen");
 
-      MockFilePicker.setFiles([curProcD]);
+      MockFilePicker.returnFiles = [curProcD];
       MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
 
       return new Promise(resolve => {
         MockFilePicker.afterOpenCallback = resolve;
         EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
       });
     }).then(() => {
       is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");