Bug 1163388 - patch 2 - get rid of nsIDOMFile, r=ehsan
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 18 May 2015 14:52:26 +0100
changeset 276743 a6bf6230c4a57a61468d57fa4279de3710a7fcd1
parent 276742 bbee8cb95f97d1a44a6eb4f47f8b0c406495a29d
child 276744 a28dbf1faa66289c1cab95153581b9abd8d77d7a
push id897
push userjlund@mozilla.com
push dateMon, 14 Sep 2015 18:56:12 +0000
treeherdermozilla-release@9411e2d2b214 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1163388
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1163388 - patch 2 - get rid of nsIDOMFile, r=ehsan
b2g/components/test/mochitest/screenshot_helper.js
dom/apps/ImportExport.jsm
dom/base/File.cpp
dom/base/File.h
dom/base/FileIOObject.h
dom/base/moz.build
dom/base/nsDOMWindowUtils.cpp
dom/base/nsFrameLoader.cpp
dom/base/nsIDOMBlob.idl
dom/base/nsIDOMFile.idl
dom/base/nsIDOMFileList.idl
dom/bindings/ToJSValue.h
dom/bluetooth/bluedroid/BluetoothOppManager.cpp
dom/bluetooth/bluedroid/BluetoothOppManager.h
dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
dom/bluetooth/bluetooth2/BluetoothService.h
dom/bluetooth/bluetooth2/ipc/BluetoothServiceChildProcess.cpp
dom/bluetooth/bluetooth2/ipc/BluetoothServiceChildProcess.h
dom/fetch/InternalResponse.cpp
dom/html/HTMLCanvasElement.cpp
dom/html/HTMLCanvasElement.h
dom/html/HTMLInputElement.cpp
dom/html/nsFormSubmission.cpp
dom/indexedDB/IDBMutableFile.cpp
dom/indexedDB/IDBMutableFile.h
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/test/file.js
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
dom/ipc/FilePickerParent.cpp
dom/ipc/FilePickerParent.h
dom/media/MediaManager.cpp
dom/media/webrtc/MediaEngineGonkVideoSource.h
dom/nfc/nsINfcContentHelper.idl
dom/settings/SettingsDB.jsm
dom/settings/SettingsRequestManager.jsm
dom/wifi/WifiCertService.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/tests/chrome/test_cloneInto.xul
js/xpconnect/tests/unit/component-blob.js
js/xpconnect/tests/unit/component-file.js
js/xpconnect/tests/unit/test_blob2.js
js/xpconnect/tests/unit/test_file2.js
toolkit/components/filepicker/nsFilePicker.js
toolkit/modules/PropertyListUtils.jsm
widget/nsBaseFilePicker.cpp
widget/nsBaseFilePicker.h
widget/nsFilePickerProxy.cpp
widget/nsFilePickerProxy.h
widget/nsIFilePicker.idl
--- a/b2g/components/test/mochitest/screenshot_helper.js
+++ b/b2g/components/test/mochitest/screenshot_helper.js
@@ -1,11 +1,13 @@
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 
+Cu.importGlobalProperties(['File']);
+
 const { Services } = Cu.import("resource://gre/modules/Services.jsm");
 
 // Load a duplicated copy of the jsm to prevent messing with the currently running one
 let scope = {};
 Services.scriptloader.loadSubScript("resource://gre/modules/Screenshot.jsm", scope);
 const { Screenshot } = scope;
 
 let index = -1;
@@ -20,17 +22,17 @@ function next() {
   } catch(ex) {
     assert.ok(false, "Caught exception: " + ex);
   }
 }
 
 let steps = [
   function getScreenshot() {
     let screenshot = Screenshot.get();
-    assert.ok(screenshot instanceof Ci.nsIDOMFile,
+    assert.ok(screenshot instanceof File,
               "Screenshot.get() returns a File");
     next();
   },
 
   function endOfTest() {
     sendAsyncMessage("finish");
   }
 ];
--- a/dom/apps/ImportExport.jsm
+++ b/dom/apps/ImportExport.jsm
@@ -9,16 +9,18 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/Webapps.jsm");
 
+Cu.importGlobalProperties(['File']);
+
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
   "resource://gre/modules/FileUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
   "resource://gre/modules/NetUtil.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PermissionsInstaller",
   "resource://gre/modules/PermissionsInstaller.jsm");
@@ -279,17 +281,17 @@ this.ImportExport = {
   // InvalidPrivilegeLevel, InvalidOrigin, DuplicateOrigin
   import: Task.async(function*(aBlob) {
 
     // First, do we even have a blob?
     if (!aBlob || !aBlob instanceof Ci.nsIDOMBlob) {
       throw "NoBlobFound";
     }
 
-    let isFileBlob = aBlob instanceof Ci.nsIDOMFile;
+    let isFileBlob = aBlob instanceof File;
     // We can't QI the DOMFile to nsIFile, so we need to create one.
     let zipFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     if (!isFileBlob) {
       let path = yield this._writeBlobToTempFile(aBlob);
       zipFile.initWithPath(path);
     } else {
       zipFile.initWithPath(aBlob.mozFullPath);
     }
@@ -493,17 +495,17 @@ this.ImportExport = {
   // Possible errors are:
   // NoBlobFound, InvalidZip, MissingMetadataFile.
   extractManifest: Task.async(function*(aBlob) {
     // First, do we even have a blob?
     if (!aBlob || !aBlob instanceof Ci.nsIDOMBlob) {
       throw "NoBlobFound";
     }
 
-    let isFileBlob = aBlob instanceof Ci.nsIDOMFile;
+    let isFileBlob = aBlob instanceof File;
     // We can't QI the DOMFile to nsIFile, so we need to create one.
     let zipFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     if (!isFileBlob) {
       let path = yield this._writeBlobToTempFile(aBlob);
       zipFile.initWithPath(path);
     } else {
       zipFile.initWithPath(aBlob.mozFullPath);
     }
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -434,32 +434,16 @@ NS_IMETHODIMP
 Blob::GetInternalStream(nsIInputStream** aStream)
 {
   return mImpl->GetInternalStream(aStream);
 }
 
 ////////////////////////////////////////////////////////////////////////////
 // mozilla::dom::File implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(File)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(File, Blob)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(File, Blob)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(File)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMFile)
-NS_INTERFACE_MAP_END_INHERITING(Blob)
-
-NS_IMPL_ADDREF_INHERITED(File, Blob)
-NS_IMPL_RELEASE_INHERITED(File, Blob)
-
 File::File(nsISupports* aParent, BlobImpl* aImpl)
   : Blob(aParent, aImpl)
 {
   MOZ_ASSERT(aImpl->IsFile());
 }
 
 /* static */ File*
 File::Create(nsISupports* aParent, BlobImpl* aImpl)
@@ -1277,19 +1261,19 @@ NS_IMETHODIMP
 FileList::GetLength(uint32_t* aLength)
 {
   *aLength = Length();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-FileList::Item(uint32_t aIndex, nsIDOMFile **aFile)
+FileList::Item(uint32_t aIndex, nsISupports** aFile)
 {
-  nsRefPtr<File> file = Item(aIndex);
+  nsCOMPtr<nsIDOMBlob> file = Item(aIndex);
   file.forget(aFile);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////
 // BlobSet implementation
 
 already_AddRefed<Blob>
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -15,17 +15,17 @@
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/Date.h"
 #include "mozilla/dom/indexedDB/FileInfo.h"
 #include "mozilla/dom/indexedDB/FileManager.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
-#include "nsIDOMFile.h"
+#include "nsIDOMBlob.h"
 #include "nsIDOMFileList.h"
 #include "nsIFile.h"
 #include "nsIMutable.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsString.h"
 #include "nsTemporaryFileInputStream.h"
 #include "nsWrapperCache.h"
 #include "nsWeakReference.h"
@@ -152,27 +152,20 @@ protected:
   // Note: we should not store any other state in this class!
   nsRefPtr<BlobImpl> mImpl;
 
 private:
   nsCOMPtr<nsISupports> mParent;
 };
 
 class File final : public Blob
-                 , public nsIDOMFile
 {
   friend class Blob;
 
 public:
-  NS_DECL_NSIDOMFILE
-  NS_FORWARD_NSIDOMBLOB(Blob::)
-
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(File, Blob);
-
   // Note: BlobImpl must be a File in order to use this method.
   // Check impl->IsFile().
   static File*
   Create(nsISupports* aParent, BlobImpl* aImpl);
 
   static already_AddRefed<File>
   Create(nsISupports* aParent, const nsAString& aName,
          const nsAString& aContentType, uint64_t aLength,
--- a/dom/base/FileIOObject.h
+++ b/dom/base/FileIOObject.h
@@ -4,17 +4,16 @@
  * 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/. */
 
 #ifndef FileIOObject_h__
 #define FileIOObject_h__
 
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsIFile.h"
-#include "nsIDOMFile.h"
 #include "nsITimer.h"
 #include "nsCOMPtr.h"
 #include "nsIAsyncInputStream.h"
 
 #include "mozilla/dom/DOMError.h"
 
 #define NS_PROGRESS_EVENT_INTERVAL 50
 
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -6,20 +6,20 @@
 
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsIConsoleAPIStorage.idl',
     'nsIContentPolicy.idl',
     'nsIContentPolicyBase.idl',
     'nsIDocumentEncoder.idl',
+    'nsIDOMBlob.idl',
     'nsIDOMDataChannel.idl',
     'nsIDOMDOMCursor.idl',
     'nsIDOMDOMRequest.idl',
-    'nsIDOMFile.idl',
     'nsIDOMFileList.idl',
     'nsIDOMFileReader.idl',
     'nsIDOMFormData.idl',
     'nsIDOMParser.idl',
     'nsIDOMSerializer.idl',
     'nsIDroppedLinkHandler.idl',
     'nsIEntropyCollector.idl',
     'nsIFrameLoader.idl',
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2588,34 +2588,34 @@ nsDOMWindowUtils::GetContainerElement(ns
     do_QueryInterface(window->GetFrameElementInternal());
 
   element.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
-                              nsIDOMFile **aDOMFile)
+                              nsISupports **aDOMFile)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   if (!aFile) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsPIDOMWindow* innerWindow = window->GetCurrentInnerWindow();
   if (!innerWindow) {
     return NS_ERROR_FAILURE;
   }
 
-  nsRefPtr<File> file = File::CreateFromFile(innerWindow, aFile);
-  file.forget(aDOMFile);
+  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;
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -18,17 +18,16 @@
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMMozBrowserFrame.h"
 #include "nsIDOMWindow.h"
 #include "nsIPresShell.h"
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMFile.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebProgress.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsIBaseWindow.h"
 #include "nsContentUtils.h"
rename from dom/base/nsIDOMFile.idl
rename to dom/base/nsIDOMBlob.idl
--- a/dom/base/nsIDOMFile.idl
+++ b/dom/base/nsIDOMBlob.idl
@@ -48,19 +48,8 @@ interface nsIDOMBlob : nsISupports
 
   // Called before the blob is stored in a database to decide if it can be
   // shared or needs to be copied. It can be called on any thread.
   [notxpcom] FileInfo getFileInfo(in FileManager aFileManager);
 
   // Return true if this blob is a memory file.
   [notxpcom] bool isMemoryFile();
 };
-
-// We want to avoid multiple inheritance of nsIDOMBlob so we can downcast from
-// nsIDOMBlob to Blob safely.  Our chain is:
-//  - Blob -> nsIDOMBlob
-//  - File -> nsIDOMFile and Blob
-[scriptable, builtinclass, uuid(26e292a6-f5aa-4560-b523-ae22a4c7dfca)]
-interface nsIDOMFile : nsISupports
-{
-  // Empty interface used by addons and some test to check if the object is a
-  // blob or file. This interface will be removed by bug 1163388
-};
--- a/dom/base/nsIDOMFileList.idl
+++ b/dom/base/nsIDOMFileList.idl
@@ -1,15 +1,14 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "nsISupports.idl"
 
-interface nsIDOMFile;
-
-[uuid(283aa7b2-da81-4c72-aea2-9797b440fe34)]
+[uuid(57128a85-34de-42db-a252-84dd57724a59)]
 interface nsIDOMFileList : nsISupports
 {
   readonly attribute unsigned long length;
-  nsIDOMFile item(in unsigned long index);
+  // returns a DOM File object
+  nsISupports item(in unsigned long index);
 };
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -167,17 +167,17 @@ ToJSValue(JSContext* aCx,
   if (!obj) {
     return false;
   }
   aValue.setObject(*obj);
   return true;
 }
 
 // Accept objects that inherit from nsISupports but not nsWrapperCache (e.g.
-// nsIDOMFile).
+// DOM File).
 template <class T>
 MOZ_WARN_UNUSED_RESULT
 typename EnableIf<!IsBaseOf<nsWrapperCache, T>::value &&
                   !IsBaseOf<CallbackObject, T>::value &&
                   IsBaseOf<nsISupports, T>::value, bool>::Type
 ToJSValue(JSContext* aCx,
           T& aArgument,
           JS::MutableHandle<JS::Value> aValue)
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
@@ -67,24 +67,24 @@ namespace {
   static bool sInShutdown = false;
 }
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothOppManager::SendFileBatch final
 {
 public:
-  SendFileBatch(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob)
+  SendFileBatch(const nsAString& aDeviceAddress, Blob* aBlob)
     : mDeviceAddress(aDeviceAddress)
   {
     mBlobs.AppendElement(aBlob);
   }
 
   nsString mDeviceAddress;
-  nsCOMArray<nsIDOMBlob> mBlobs;
+  nsTArray<nsRefPtr<Blob>> mBlobs;
 };
 
 NS_IMETHODIMP
 BluetoothOppManager::Observe(nsISupports* aSubject,
                              const char* aTopic,
                              const char16_t* aData)
 {
   MOZ_ASSERT(sBluetoothOppManager);
@@ -415,31 +415,31 @@ BluetoothOppManager::SendFile(const nsAS
   nsRefPtr<BlobImpl> impl = aActor->GetBlobImpl();
   nsRefPtr<Blob> blob = Blob::Create(nullptr, impl);
 
   return SendFile(aDeviceAddress, blob.get());
 }
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
-                              nsIDOMBlob* aBlob)
+                              Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   AppendBlobToSend(aDeviceAddress, aBlob);
   if (!mSocket) {
     ProcessNextBatch();
   }
 
   return true;
 }
 
 void
 BluetoothOppManager::AppendBlobToSend(const nsAString& aDeviceAddress,
-                                      nsIDOMBlob* aBlob)
+                                      Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   int indexTail = mBatches.Length() - 1;
 
   /**
    * Create a new batch if
    * - mBatches is empty, or
@@ -789,17 +789,17 @@ BluetoothOppManager::ExtractBlobHeaders(
   return true;
 }
 
 void
 BluetoothOppManager::RetrieveSentFileName()
 {
   mFileName.Truncate();
 
-  nsRefPtr<File> file = static_cast<Blob*>(mBlob.get()).ToFile();
+  nsRefPtr<File> file = static_cast<Blob*>(mBlob.get())->ToFile();
   if (file) {
     file->GetName(mFileName);
   }
 
   /**
    * We try our best to get the file extention to avoid interoperability issues.
    * However, once we found that we are unable to get suitable extension or
    * information about the content type, sending a pre-defined file name without
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.h
@@ -9,23 +9,23 @@
 
 #include "BluetoothCommon.h"
 #include "BluetoothProfileManagerBase.h"
 #include "BluetoothSocketObserver.h"
 #include "DeviceStorage.h"
 #include "mozilla/ipc/SocketBase.h"
 #include "nsCOMArray.h"
 
-class nsIDOMBlob;
 class nsIOutputStream;
 class nsIInputStream;
 class nsIVolumeMountLock;
 
 namespace mozilla {
 namespace dom {
+class Blob;
 class BlobParent;
 }
 }
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSocket;
 class ObexHeaderSet;
@@ -50,17 +50,17 @@ public:
 
   static BluetoothOppManager* Get();
   void ClientDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
   void ServerDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
 
   bool Listen();
 
   bool SendFile(const nsAString& aDeviceAddress, BlobParent* aActor);
-  bool SendFile(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob);
+  bool SendFile(const nsAString& aDeviceAddress, Blob* aBlob);
   bool StopSendingFile();
   bool ConfirmReceivingFile(bool aConfirm);
 
   void SendConnectRequest();
   void SendPutHeaderRequest(const nsAString& aFileName, int aFileSize);
   void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength);
   void SendPutFinalRequest();
   void SendDisconnectRequest();
@@ -97,17 +97,17 @@ private:
   void AfterOppDisconnected();
   void ValidateFileName();
   bool IsReservedChar(char16_t c);
   void ClearQueue();
   void RetrieveSentFileName();
   void NotifyAboutFileChange();
   bool AcquireSdcardMountLock();
   void SendObexData(uint8_t* aData, uint8_t aOpcode, int aSize);
-  void AppendBlobToSend(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob);
+  void AppendBlobToSend(const nsAString& aDeviceAddress, Blob* aBlob);
   void DiscardBlobsToSend();
   bool ProcessNextBatch();
   void ConnectInternal(const nsAString& aDeviceAddress);
 
   /**
    * Usually we won't get a full PUT packet in one operation, which means that
    * a packet may be devided into several parts and BluetoothOppManager should
    * be in charge of assembling.
@@ -194,17 +194,17 @@ private:
   uint32_t mFileLength;
   uint32_t mSentFileLength;
   bool mWaitingToSendPutFinal;
 
   nsAutoArrayPtr<uint8_t> mBodySegment;
   nsAutoArrayPtr<uint8_t> mReceivedDataBuffer;
 
   int mCurrentBlobIndex;
-  nsCOMPtr<nsIDOMBlob> mBlob;
+  nsRefPtr<Blob> mBlob;
   nsTArray<SendFileBatch> mBatches;
 
   /**
    * A seperate member thread is required because our read calls can block
    * execution, which is not allowed to happen on the IOThread.
    */
   nsCOMPtr<nsIThread> mReadFileThread;
   nsCOMPtr<nsIOutputStream> mOutputStream;
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -1822,17 +1822,17 @@ BluetoothServiceBluedroid::SendFile(cons
   }
 
   DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
 #endif
 }
 
 void
 BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress,
-                                    nsIDOMBlob* aBlob,
+                                    Blob* aBlob,
                                     BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Currently we only support one device sending one file at a time,
   // so we don't need aDeviceAddress here because the target device
   // has been determined when calling 'Connect()'. Nevertheless, keep
   // it for future use.
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
@@ -125,17 +125,17 @@ public:
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable);
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
-           nsIDOMBlob* aBlob,
+           Blob* aBlob,
            BluetoothReplyRunnable* aRunnable);
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable);
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
@@ -430,17 +430,17 @@ public:
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable);
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
-           nsIDOMBlob* aBlob,
+           Blob* aBlob,
            BluetoothReplyRunnable* aRunnable);
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable);
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
--- a/dom/bluetooth/bluetooth2/BluetoothService.h
+++ b/dom/bluetooth/bluetooth2/BluetoothService.h
@@ -7,25 +7,23 @@
 #ifndef mozilla_dom_bluetooth_bluetootheventservice_h__
 #define mozilla_dom_bluetooth_bluetootheventservice_h__
 
 #include "BluetoothCommon.h"
 #include "BluetoothInterface.h"
 #include "BluetoothProfileManagerBase.h"
 #include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
-#include "nsIDOMFile.h"
 #include "nsIObserver.h"
 #include "nsTObserverArray.h"
 #include "nsThreadUtils.h"
 
-class nsIDOMBlob;
-
 namespace mozilla {
 namespace dom {
+class Blob;
 class BlobChild;
 class BlobParent;
 }
 }
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothManager;
@@ -290,17 +288,17 @@ public:
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
-           nsIDOMBlob* aBlob,
+           Blob* aBlob,
            BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
--- a/dom/bluetooth/bluetooth2/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/bluetooth2/ipc/BluetoothServiceChildProcess.cpp
@@ -311,17 +311,17 @@ BluetoothServiceChildProcess::SendFile(
 {
   SendRequest(aRunnable,
               SendFileRequest(nsString(aDeviceAddress), nullptr, aBlobChild));
 }
 
 void
 BluetoothServiceChildProcess::SendFile(
   const nsAString& aDeviceAddress,
-  nsIDOMBlob* aBlobChild,
+  Blob* aBlobChild,
   BluetoothReplyRunnable* aRunnable)
 {
   // Parent-process-only method
   MOZ_CRASH("This should never be called!");
 }
 
 void
 BluetoothServiceChildProcess::StopSendingFile(
--- a/dom/bluetooth/bluetooth2/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/bluetooth2/ipc/BluetoothServiceChildProcess.h
@@ -135,17 +135,17 @@ public:
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
-           nsIDOMBlob* aBlob,
+           Blob* aBlob,
            BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress,
--- a/dom/fetch/InternalResponse.cpp
+++ b/dom/fetch/InternalResponse.cpp
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "InternalResponse.h"
 
-#include "nsIDOMFile.h"
-
 #include "mozilla/dom/InternalHeaders.h"
 #include "nsStreamUtils.h"
 #include "nsSerializationHelper.h"
 
 namespace mozilla {
 namespace dom {
 
 InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -642,42 +642,48 @@ HTMLCanvasElement::ToBlob(JSContext* aCx
                                        callback);
 }
 
 already_AddRefed<File>
 HTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                 const nsAString& aType,
                                 ErrorResult& aRv)
 {
-  nsCOMPtr<nsIDOMFile> file;
+  nsCOMPtr<nsISupports> file;
   aRv = MozGetAsFile(aName, aType, getter_AddRefs(file));
-  nsRefPtr<File> tmp = static_cast<File*>(file.get());
-  return tmp.forget();
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(file);
+  nsRefPtr<Blob> domBlob = static_cast<Blob*>(blob.get());
+  MOZ_ASSERT(domBlob->IsFile());
+  return domBlob->ToFile();
 }
 
 NS_IMETHODIMP
 HTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                 const nsAString& aType,
-                                nsIDOMFile** aResult)
+                                nsISupports** aResult)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eMozGetAsFile);
 
   // do a trust check if this is a write-only canvas
   if ((mWriteOnly) &&
       !nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   return MozGetAsBlobImpl(aName, aType, aResult);
 }
 
 nsresult
 HTMLCanvasElement::MozGetAsBlobImpl(const nsAString& aName,
                                     const nsAString& aType,
-                                    nsIDOMFile** aResult)
+                                    nsISupports** aResult)
 {
   nsCOMPtr<nsIInputStream> stream;
   nsAutoString type(aType);
   nsresult rv = ExtractData(type, EmptyString(), getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint64_t imgSize;
   rv = stream->Available(&imgSize);
@@ -691,17 +697,17 @@ HTMLCanvasElement::MozGetAsBlobImpl(cons
   JSContext* cx = nsContentUtils::GetCurrentJSContext();
   if (cx) {
     JS_updateMallocCounter(cx, imgSize);
   }
 
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(OwnerDoc()->GetScopeObject());
 
   // The File takes ownership of the buffer
-  nsRefPtr<File> file =
+  nsCOMPtr<nsIDOMBlob> file =
     File::CreateMemoryFile(win, imgData, (uint32_t)imgSize, aName, type,
                            PR_Now());
 
   file.forget(aResult);
   return NS_OK;
 }
 
 static bool
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -232,17 +232,17 @@ protected:
                        const nsAString& aOptions,
                        nsIInputStream** aStream);
   nsresult ToDataURLImpl(JSContext* aCx,
                          const nsAString& aMimeType,
                          const JS::Value& aEncoderOptions,
                          nsAString& aDataURL);
   nsresult MozGetAsBlobImpl(const nsAString& aName,
                             const nsAString& aType,
-                            nsIDOMFile** aResult);
+                            nsISupports** aResult);
   void CallPrintCallback();
 
   CanvasContextType mCurrentContextType;
   nsRefPtr<HTMLCanvasElement> mOriginalCanvas;
   nsRefPtr<PrintCallback> mPrintCallback;
   nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
   nsRefPtr<HTMLCanvasPrintState> mPrintState;
 
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -400,17 +400,19 @@ public:
     int32_t length = path.Length() - leafName.Length();
     MOZ_ASSERT(length >= 0);
     if (length > 0) {
       // Note that we leave the trailing "/" on the path.
       BlobImplFile* blobImpl = static_cast<BlobImplFile*>(domFile->Impl());
       MOZ_ASSERT(blobImpl);
       blobImpl->SetPath(Substring(path, 0, uint32_t(length)));
     }
-    *aResult = domFile.forget().downcast<nsIDOMFile>().take();
+
+    nsCOMPtr<nsIDOMBlob> blob = domFile.get();
+    blob.forget(aResult);
     LookupAndCacheNext();
     return NS_OK;
   }
 
   NS_IMETHOD
   HasMoreElements(bool* aResult) override
   {
     *aResult = !!mNextFile;
@@ -483,17 +485,17 @@ private:
   nsCOMPtr<nsIFile> mNextFile;
   nsTArray<nsCOMPtr<nsISimpleEnumerator> > mDirEnumeratorStack;
 };
 
 NS_IMPL_ISUPPORTS(DirPickerRecursiveFileEnumerator, nsISimpleEnumerator)
 
 /**
  * This may return nullptr if aDomFile's implementation of
- * nsIDOMFile::mozFullPathInternal does not successfully return a non-empty
+ * File::mozFullPathInternal does not successfully return a non-empty
  * string that is a valid path. This can happen on Firefox OS, for example,
  * where the file picker can create Blobs.
  */
 static already_AddRefed<nsIFile>
 DOMFileToLocalFile(File* aDomFile)
 {
   nsString path;
   ErrorResult rv;
@@ -532,19 +534,19 @@ public:
     if (!NS_IsMainThread()) {
       // Build up list of File objects on this dedicated thread:
       nsCOMPtr<nsISimpleEnumerator> iter =
         new DirPickerRecursiveFileEnumerator(mTopDir);
       bool hasMore = true;
       nsCOMPtr<nsISupports> tmp;
       while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
         iter->GetNext(getter_AddRefs(tmp));
-        nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
-        MOZ_ASSERT(domFile);
-        mFileList.AppendElement(static_cast<File*>(domFile.get()));
+        nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(tmp);
+        MOZ_ASSERT(domBlob);
+        mFileList.AppendElement(static_cast<File*>(domBlob.get()));
         mFileListLength = mFileList.Length();
         if (mCanceled) {
           MOZ_ASSERT(!mInput, "This is bad - how did this happen?");
           // There's no point dispatching to the main thread (that doesn't
           // guarantee that we'll be destroyed there).
           return NS_OK;
         }
       }
@@ -691,30 +693,33 @@ HTMLInputElement::nsFilePickerShownCallb
       return NS_OK;
     }
 
     nsCOMPtr<nsISupports> tmp;
     bool hasMore = true;
 
     while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
       iter->GetNext(getter_AddRefs(tmp));
-      nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
-      NS_WARN_IF_FALSE(domFile,
+      nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(tmp);
+      NS_WARN_IF_FALSE(domBlob,
                        "Null file object from FilePicker's file enumerator?");
-      if (domFile) {
-        newFiles.AppendElement(static_cast<File*>(domFile.get()));
+      if (domBlob) {
+        newFiles.AppendElement(static_cast<File*>(domBlob.get()));
       }
     }
   } else {
     MOZ_ASSERT(mode == static_cast<int16_t>(nsIFilePicker::modeOpen));
-    nsCOMPtr<nsIDOMFile> domFile;
-    nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile));
+    nsCOMPtr<nsISupports> tmp;
+    nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(tmp));
     NS_ENSURE_SUCCESS(rv, rv);
-    if (domFile) {
-      newFiles.AppendElement(static_cast<File*>(domFile.get()));
+
+    nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(tmp);
+    if (blob) {
+      nsRefPtr<File> file = static_cast<Blob*>(blob.get())->ToFile();
+      newFiles.AppendElement(file);
     }
   }
 
   if (newFiles.IsEmpty()) {
     return NS_OK;
   }
 
   // Store the last used directory using the content pref service:
--- a/dom/html/nsFormSubmission.cpp
+++ b/dom/html/nsFormSubmission.cpp
@@ -13,17 +13,16 @@
 #include "nsGkAtoms.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsError.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsISaveAsCharset.h"
 #include "nsIFile.h"
-#include "nsIDOMFile.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsStringStream.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsLinebreakConverter.h"
 #include "nsEscape.h"
 #include "nsUnicharUtils.h"
--- a/dom/indexedDB/IDBMutableFile.cpp
+++ b/dom/indexedDB/IDBMutableFile.cpp
@@ -22,17 +22,16 @@
 #include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
 #include "mozilla/dom/quota/FileStreams.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsError.h"
-#include "nsIDOMFile.h"
 #include "nsIPrincipal.h"
 
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
 using namespace mozilla::dom::quota;
 using namespace mozilla::ipc;
@@ -323,17 +322,17 @@ int64_t
 IDBMutableFile::GetFileId() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mFileInfo);
 
   return mFileInfo->Id();
 }
 
-already_AddRefed<nsIDOMFile>
+already_AddRefed<File>
 IDBMutableFile::CreateFileObject(IDBFileHandle* aFileHandle,
                                  MetadataParameters* aMetadataParams)
 {
   nsRefPtr<BlobImpl> impl =
     new BlobImplSnapshot(mName,
                          mType,
                          aMetadataParams,
                          mFile,
@@ -388,22 +387,20 @@ IDBMutableFile::GetFile(ErrorResult& aEr
 nsresult
 GetFileHelper::GetSuccessResult(JSContext* aCx,
                                 JS::MutableHandle<JS::Value> aVal)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   auto fileHandle = static_cast<IDBFileHandle*>(mFileHandle.get());
 
-  nsCOMPtr<nsIDOMFile> domFile =
+  nsRefPtr<File> domFile =
     mMutableFile->CreateFileObject(fileHandle, mParams);
 
-  nsresult rv =
-    nsContentUtils::WrapNative(aCx, domFile, &NS_GET_IID(nsIDOMFile), aVal);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
+  if (!ToJSValue(aCx, domFile, aVal)) {
     return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
   }
 
   return NS_OK;
 }
 
 } // namespace indexedDB
 } // namespace dom
--- a/dom/indexedDB/IDBMutableFile.h
+++ b/dom/indexedDB/IDBMutableFile.h
@@ -13,26 +13,26 @@
 #include "mozilla/dom/FileModeBinding.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/FileModeBinding.h"
 #include "mozilla/dom/MutableFile.h"
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 
-class nsIDOMFile;
 class nsPIDOMWindow;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 class DOMRequest;
+class File;
 class MetadataParameters;
 
 namespace indexedDB {
 
 class FileInfo;
 class IDBDatabase;
 class IDBFileHandle;
 
@@ -78,17 +78,17 @@ public:
   GetFileId() const;
 
   FileInfo*
   GetFileInfo() const
   {
     return mFileInfo;
   }
 
-  already_AddRefed<nsIDOMFile>
+  already_AddRefed<File>
   CreateFileObject(IDBFileHandle* aFileHandle,
                    MetadataParameters* aMetadataParams);
 
   void
   Invalidate();
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBMutableFile, DOMEventTargetHelper)
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -12,17 +12,16 @@
 #include "IDBObjectStore.h"
 #include "IDBRequest.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "nsIAppShell.h"
-#include "nsIDOMFile.h"
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTHashtable.h"
 #include "nsWidgetsCID.h"
 #include "ProfilerHelpers.h"
 #include "ReportInternalError.h"
 #include "WorkerFeature.h"
 #include "WorkerPrivate.h"
--- a/dom/indexedDB/test/file.js
+++ b/dom/indexedDB/test/file.js
@@ -89,22 +89,21 @@ function verifyBuffers(buffer1, buffer2)
 {
   ok(compareBuffers(buffer1, buffer2), "Correct blob data");
 }
 
 function verifyBlob(blob1, blob2, fileId, blobReadHandler)
 {
   is(blob1 instanceof Components.interfaces.nsIDOMBlob, true,
      "Instance of nsIDOMBlob");
-  is(blob1 instanceof Components.interfaces.nsIDOMFile,
-     blob2 instanceof Components.interfaces.nsIDOMFile,
-     "Instance of nsIDOMFile");
+  is(blob1 instanceof File, blob2 instanceof File,
+     "Instance of DOM File");
   is(blob1.size, blob2.size, "Correct size");
   is(blob1.type, blob2.type, "Correct type");
-  if (blob2 instanceof Components.interfaces.nsIDOMFile) {
+  if (blob2 instanceof File) {
     is(blob1.name, blob2.name, "Correct name");
   }
   is(utils.getFileId(blob1), fileId, "Correct file id");
 
   let buffer1;
   let buffer2;
 
   for (let i = 0; i < bufferCache.length; i++) {
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -34,29 +34,27 @@ interface nsIDOMNode;
 interface nsIDOMNodeList;
 interface nsIDOMElement;
 interface nsIDOMHTMLCanvasElement;
 interface nsIDOMEvent;
 interface nsIDOMStyleSheet;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
-interface nsIDOMBlob;
-interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsITranslationNodeList;
 interface nsIJSRAIIHelper;
 interface nsIContentPermissionRequest;
 interface nsIObserver;
 
-[scriptable, uuid(1a75c351-d115-4d51-94df-731dd1723a1f)]
+[scriptable, uuid(34a42cdc-7a04-4e71-8a5c-63e092fba58e)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1440,19 +1438,20 @@ interface nsIDOMWindowUtils : nsISupport
    * property.
    */
   double computeAnimationDistance(in nsIDOMElement element,
                                   in AString property,
                                   in AString value1,
                                   in AString value2);
 
   /**
-   * Wrap an nsIFile in an nsIDOMFile
+   * Wrap an nsIFile in an DOM File
+   * Returns a File object.
    */
-  nsIDOMFile wrapDOMFile(in nsIFile aFile);
+  nsISupports wrapDOMFile(in nsIFile aFile);
 
   /**
    * Get the type of the currently focused html input, if any.
    */
   readonly attribute string focusedInputType;
 
   /**
    * Given a view ID from the compositor process, retrieve the element
--- a/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLCanvasElement.idl
@@ -11,21 +11,20 @@
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#graphics
  *
  * @status UNDER_DEVELOPMENT
  */
 
 interface nsIDOMBlob;
-interface nsIDOMFile;
 interface nsIVariant;
 interface nsIInputStreamCallback;
 
-[uuid(8978d1c5-2981-4678-a1c3-b0b7bae04fbc)]
+[uuid(2c984658-2e7c-4774-8ac5-cf1b39f8bec3)]
 interface nsIDOMHTMLCanvasElement : nsISupports
 {
   attribute unsigned long width;
   attribute unsigned long height;
   attribute boolean mozOpaque;
 
   // Valid calls are:
   //  toDataURL();              -- defaults to image/png
@@ -33,17 +32,18 @@ interface nsIDOMHTMLCanvasElement : nsIS
   //  toDataURL(type, params);  -- uses given type, and any valid parameters
   [implicit_jscontext]
   DOMString toDataURL([optional] in DOMString type,
                       [optional] in jsval params);
 
   // Valid calls are
   // mozGetAsFile(name);              -- defaults to image/png
   // mozGetAsFile(name, type);        -- uses given type
-  nsIDOMFile mozGetAsFile(in DOMString name, [optional] in DOMString type);
+  // The return value is a File object.
+  nsISupports mozGetAsFile(in DOMString name, [optional] in DOMString type);
 
   // A Mozilla-only extension to get a canvas context backed by double-buffered
   // shared memory. Only privileged callers can call this.
   nsISupports MozGetIPCContext(in DOMString contextId);
 
   // A Mozilla-only extension that returns the canvas' image data as a data
   // stream in the desired image format.
   void mozFetchAsStream(in nsIInputStreamCallback callback,
--- a/dom/ipc/FilePickerParent.cpp
+++ b/dom/ipc/FilePickerParent.cpp
@@ -3,17 +3,16 @@
 /* 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/. */
 
 #include "FilePickerParent.h"
 #include "nsComponentManagerUtils.h"
 #include "nsNetCID.h"
 #include "nsIDocument.h"
-#include "nsIDOMFile.h"
 #include "nsIDOMWindow.h"
 #include "nsIFile.h"
 #include "nsISimpleEnumerator.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TabParent.h"
--- a/dom/ipc/FilePickerParent.h
+++ b/dom/ipc/FilePickerParent.h
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #ifndef mozilla_dom_FilePickerParent_h
 #define mozilla_dom_FilePickerParent_h
 
-#include "nsIDOMFile.h"
 #include "nsIEventTarget.h"
 #include "nsIFilePicker.h"
 #include "nsCOMArray.h"
 #include "nsThreadUtils.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/PFilePickerParent.h"
 
 namespace mozilla {
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -108,16 +108,17 @@ GetMediaManagerLog()
 {
   static PRLogModuleInfo *sLog;
   if (!sLog)
     sLog = PR_NewLogModule("MediaManager");
   return sLog;
 }
 #define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 
+using dom::File;
 using dom::MediaStreamConstraints;
 using dom::MediaTrackConstraintSet;
 using dom::MediaTrackConstraints;
 using dom::MediaStreamError;
 using dom::GetUserMediaRequest;
 using dom::Sequence;
 using dom::OwningBooleanOrMediaTrackConstraints;
 using dom::SupportedAudioConstraints;
@@ -260,63 +261,16 @@ private:
   nsCOMPtr<SuccessCallbackType> mOnSuccess;
   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
   nsRefPtr<MediaMgrError> mError;
   uint64_t mWindowID;
   nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
 /**
- * Invoke the "onSuccess" callback in content. The callback will take a
- * DOMBlob in the case of {picture:true}, and a MediaStream in the case of
- * {audio:true} or {video:true}. There is a constructor available for each
- * form. Do this only on the main thread.
- */
-class SuccessCallbackRunnable : public nsRunnable
-{
-public:
-  SuccessCallbackRunnable(
-    nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
-    nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
-    nsIDOMFile* aFile, uint64_t aWindowID)
-    : mFile(aFile)
-    , mWindowID(aWindowID)
-    , mManager(MediaManager::GetInstance())
-  {
-    mOnSuccess.swap(aOnSuccess);
-    mOnFailure.swap(aOnFailure);
-  }
-
-  NS_IMETHOD
-  Run()
-  {
-    // Only run if the window is still active.
-    NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
-
-    nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
-    nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
-
-    if (!(mManager->IsWindowStillActive(mWindowID))) {
-      return NS_OK;
-    }
-    // This is safe since we're on main-thread, and the windowlist can only
-    // be invalidated from the main-thread (see OnNavigation)
-    onSuccess->OnSuccess(mFile);
-    return NS_OK;
-  }
-
-private:
-  nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
-  nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
-  nsCOMPtr<nsIDOMFile> mFile;
-  uint64_t mWindowID;
-  nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
-};
-
-/**
  * Invoke the GetUserMediaDevices success callback. Wrapped in a runnable
  * so that it may be called on the main thread. The error callback is also
  * passed so it can be released correctly.
  */
 class DeviceSuccessCallbackRunnable: public nsRunnable
 {
 public:
   DeviceSuccessCallbackRunnable(
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.h
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.h
@@ -107,17 +107,17 @@ protected:
   size_t NumCapabilities() override;
   // Initialize the recording frame (MediaBuffer) callback and Gonk camera.
   // MediaBuffer will transfers to MediaStreamGraph via AppendToTrack.
   nsresult InitDirectMediaBuffer();
 
   mozilla::ReentrantMonitor mCallbackMonitor; // Monitor for camera callback handling
   // This is only modified on MainThread (AllocImpl and DeallocImpl)
   nsRefPtr<ICameraControl> mCameraControl;
-  nsCOMPtr<nsIDOMFile> mLastCapture;
+  nsRefPtr<dom::File> mLastCapture;
 
   android::sp<android::GonkCameraSource> mCameraSource;
 
   // These are protected by mMonitor in parent class
   nsTArray<nsRefPtr<PhotoCallback>> mPhotoCallbacks;
   int mRotation;
   int mCameraAngle; // See dom/base/ScreenOrientation.h
   bool mBackCamera;
--- a/dom/nfc/nsINfcContentHelper.idl
+++ b/dom/nfc/nsINfcContentHelper.idl
@@ -205,17 +205,17 @@ interface nsINfcContentHelper : nsISuppo
    */
   DOMString queryRFState();
 
   /**
    * Initiate send file operation.
    *
    * @param blob
    *        Raw data of the file to be sent. This object represents a file-like
-   *        (nsIDOMFile) object of immutable, raw data. The blob data needs
+   *        (DOM File) object of immutable, raw data. The blob data needs
    *        to be 'object wrapped' before calling this interface.
    *
    * @param sessionToken
    *        Current token
    *
    * @param callback
    *        Called when request is finished
    */
--- a/dom/settings/SettingsDB.jsm
+++ b/dom/settings/SettingsDB.jsm
@@ -3,17 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 
-Cu.importGlobalProperties(['Blob']);
+Cu.importGlobalProperties(['Blob', 'File']);
 Cu.import("resource://gre/modules/Services.jsm");
 
 this.EXPORTED_SYMBOLS = ["SettingsDB", "SETTINGSDB_NAME", "SETTINGSSTORE_NAME"];
 
 let DEBUG = false;
 let VERBOSE = false;
 
 try {
@@ -204,17 +204,17 @@ SettingsDB.prototype = {
     return aValue
   },
 
   getObjectKind: function(aObject) {
     if (aObject === null || aObject === undefined) {
       return "primitive";
     } else if (Array.isArray(aObject)) {
       return "array";
-    } else if (aObject instanceof Ci.nsIDOMFile) {
+    } else if (aObject instanceof File) {
       return "file";
     } else if (aObject instanceof Ci.nsIDOMBlob) {
       return "blob";
     } else if (aObject.constructor.name == "Date") {
       return "date";
     } else if (TYPED_ARRAY_THINGS.has(aObject.constructor.name)) {
       return aObject.constructor.name;
     } else if (typeof aObject == "object") {
--- a/dom/settings/SettingsRequestManager.jsm
+++ b/dom/settings/SettingsRequestManager.jsm
@@ -3,16 +3,18 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
+Cu.importGlobalProperties(['File']);
+
 this.EXPORTED_SYMBOLS = ["SettingsRequestManager"];
 
 Cu.import("resource://gre/modules/SettingsDB.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PermissionsTable.jsm");
 
 let DEBUG = false;
@@ -240,17 +242,17 @@ let SettingsRequestManager = {
     mrm.registerStrongReporter(this);
   },
 
   _serializePreservingBinaries: function _serializePreservingBinaries(aObject) {
     function needsUUID(aValue) {
       if (!aValue || !aValue.constructor) {
         return false;
       }
-      return (aValue.constructor.name == "Date") || (aValue instanceof Ci.nsIDOMFile) ||
+      return (aValue.constructor.name == "Date") || (aValue instanceof File) ||
              (aValue instanceof Ci.nsIDOMBlob);
     }
     // We need to serialize settings objects, otherwise they can change between
     // the set() call and the enqueued request being processed. We can't simply
     // parse(stringify(obj)) because that breaks things like Blobs, Files and
     // Dates, so we use stringify's replacer and parse's reviver parameters to
     // preserve binaries.
     let binaries = Object.create(null);
--- a/dom/wifi/WifiCertService.cpp
+++ b/dom/wifi/WifiCertService.cpp
@@ -13,17 +13,17 @@
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Endian.h"
 #include "mozilla/ModuleUtils.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "cert.h"
 #include "certdb.h"
 #include "CryptoTask.h"
-#include "nsIDOMFile.h"
+#include "nsIDOMBlob.h"
 #include "nsIWifiService.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "ScopedNSSTypes.h"
 
 #define NS_WIFICERTSERVICE_CID \
   { 0x83585afd, 0x0e11, 0x43aa, {0x83, 0x46, 0xf3, 0x4d, 0x97, 0x5e, 0x46, 0x77} }
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -23,17 +23,16 @@
 #include "mozilla/TimeStamp.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "nsZipArchive.h"
-#include "nsIDOMFile.h"
 #include "nsIDOMFileList.h"
 #include "nsWindowMemoryReporter.h"
 #include "nsDOMClassInfo.h"
 #include "ShimInterfaceInfo.h"
 
 using namespace mozilla;
 using namespace JS;
 using namespace js;
--- a/js/xpconnect/tests/chrome/test_cloneInto.xul
+++ b/js/xpconnect/tests/chrome/test_cloneInto.xul
@@ -44,17 +44,17 @@
 
   function getType(a) {
     if (a === null || a === undefined)
       return 'null';
 
     if (Array.isArray(a))
       return 'array';
 
-    if (a instanceof Ci.nsIDOMFile)
+    if (a instanceof File)
       return 'file';
 
     if (a instanceof Ci.nsIDOMBlob)
       return 'blob';
 
     if (TypedArrayThings.indexOf(a.constructor.name) !== -1)
       return a.constructor.name;
 
--- a/js/xpconnect/tests/unit/component-blob.js
+++ b/js/xpconnect/tests/unit/component-blob.js
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.importGlobalProperties(['Blob']);
+Components.utils.importGlobalProperties(['Blob', 'File']);
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 function do_check_true(cond, text) {
   // we don't have the test harness' utilities in this scope, so we need this
   // little helper. In the failure case, the exception is propagated to the
@@ -26,17 +26,17 @@ BlobComponent.prototype =
     // throw if anything goes wrong
     let testContent = "<a id=\"a\"><b id=\"b\">hey!<\/b><\/a>";
     // should be able to construct a file
     var f1 = new Blob([testContent], {"type" : "text/xml"});
 
     // do some tests
     do_check_true(f1 instanceof Ci.nsIDOMBlob, "Should be a DOM Blob");
 
-    do_check_true(!(f1 instanceof Ci.nsIDOMFile), "Should not be a DOM File");
+    do_check_true(!(f1 instanceof File), "Should not be a DOM File");
 
     do_check_true(f1.type == "text/xml", "Wrong type");
 
     do_check_true(f1.size == testContent.length, "Wrong content size");
 
     var f2 = new Blob();
     do_check_true(f2.size == 0, "Wrong size");
     do_check_true(f2.type == "", "Wrong type");
--- a/js/xpconnect/tests/unit/component-file.js
+++ b/js/xpconnect/tests/unit/component-file.js
@@ -31,18 +31,18 @@ FileComponent.prototype =
     file.append("xpcshell.ini");
 
     // should be able to construct a file
     var f1 = new File(file.path);
     // and with nsIFiles
     var f2 = new File(file);
 
     // do some tests
-    do_check_true(f1 instanceof Ci.nsIDOMFile, "Should be a DOM File");
-    do_check_true(f2 instanceof Ci.nsIDOMFile, "Should be a DOM File");
+    do_check_true(f1 instanceof File, "Should be a DOM File");
+    do_check_true(f2 instanceof File, "Should be a DOM File");
 
     do_check_true(f1.name == "xpcshell.ini", "Should be the right file");
     do_check_true(f2.name == "xpcshell.ini", "Should be the right file");
 
     do_check_true(f1.type == "", "Should be the right type");
     do_check_true(f2.type == "", "Should be the right type");
 
     var threw = false;
--- a/js/xpconnect/tests/unit/test_blob2.js
+++ b/js/xpconnect/tests/unit/test_blob2.js
@@ -1,26 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-Components.utils.importGlobalProperties(['Blob']);
+Components.utils.importGlobalProperties(['Blob', 'File']);
 
 const Ci = Components.interfaces;
 
 function run_test() {
   // throw if anything goes wrong
   let testContent = "<a id=\"a\"><b id=\"b\">hey!<\/b><\/a>";
   // should be able to construct a file
   var f1 = new Blob([testContent], {"type" : "text/xml"});
 
   // do some tests
   do_check_true(f1 instanceof Ci.nsIDOMBlob, "Should be a DOM Blob");
 
-  do_check_true(!(f1 instanceof Ci.nsIDOMFile), "Should not be a DOM File");
+  do_check_true(!(f1 instanceof File), "Should not be a DOM File");
 
   do_check_true(f1.type == "text/xml", "Wrong type");
 
   do_check_true(f1.size == testContent.length, "Wrong content size");
 
   var f2 = new Blob();
   do_check_true(f2.size == 0, "Wrong size");
   do_check_true(f2.type == "", "Wrong type");
--- a/js/xpconnect/tests/unit/test_file2.js
+++ b/js/xpconnect/tests/unit/test_file2.js
@@ -16,18 +16,18 @@ function run_test() {
   file.append("xpcshell.ini");
 
   // should be able to construct a file
   var f1 = new File(file.path);
   // and with nsIFiles
   var f2 = new File(file);
 
   // do some tests
-  do_check_true(f1 instanceof Ci.nsIDOMFile, "Should be a DOM File");
-  do_check_true(f2 instanceof Ci.nsIDOMFile, "Should be a DOM File");
+  do_check_true(f1 instanceof File, "Should be a DOM File");
+  do_check_true(f2 instanceof File, "Should be a DOM File");
 
   do_check_true(f1.name == "xpcshell.ini", "Should be the right file");
   do_check_true(f2.name == "xpcshell.ini", "Should be the right file");
 
   do_check_true(f1.type == "", "Should be the right type");
   do_check_true(f2.type == "", "Should be the right type");
 
   var threw = false;
--- a/toolkit/components/filepicker/nsFilePicker.js
+++ b/toolkit/components/filepicker/nsFilePicker.js
@@ -88,17 +88,17 @@ nsFilePicker.prototype = {
   },
 
   /* readonly attribute nsILocalFile file; */
   get file()  { return this.mFilesEnumerator.mFiles[0]; },
 
   /* readonly attribute nsISimpleEnumerator files; */
   get files()  { return this.mFilesEnumerator; },
 
-  /* readonly attribute nsIDOMFile domfile; */
+  /* readonly attribute DOM File domfile; */
   get domfile()  {
     let enumerator = this.domfiles;
     return enumerator ? enumerator.mFiles[0] : null;
   },
 
   /* readonly attribute nsISimpleEnumerator domfiles; */
   get domfiles()  {
     if (!this.mFilesEnumerator) {
--- a/toolkit/modules/PropertyListUtils.jsm
+++ b/toolkit/modules/PropertyListUtils.jsm
@@ -78,17 +78,17 @@ this.PropertyListUtils = Object.freeze({
    * @param aCallback
    *        If the property list is read successfully, aPropertyListRoot is set
    *        to the root object of the property list.
    *        Use getPropertyListObjectType to detect its type.
    *        If it's not read successfully, aPropertyListRoot is set to null.
    *        The reaon for failure is reported to the Error Console.
    */
   read: function PLU_read(aFile, aCallback) {
-    if (!(aFile instanceof Ci.nsILocalFile || aFile instanceof Ci.nsIDOMFile))
+    if (!(aFile instanceof Ci.nsILocalFile || aFile instanceof File))
       throw new Error("aFile is not a file object");
     if (typeof(aCallback) != "function")
       throw new Error("Invalid value for aCallback");
 
     // We guarantee not to throw directly for any other exceptions, and always
     // call aCallback.
     Services.tm.mainThread.dispatch(function() {
       let file = aFile;
--- a/widget/nsBaseFilePicker.cpp
+++ b/widget/nsBaseFilePicker.cpp
@@ -91,17 +91,17 @@ public:
       return NS_OK;
     }
 
     nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
     if (!localFile) {
       return NS_ERROR_FAILURE;
     }
 
-    nsCOMPtr<nsIDOMFile> domFile = File::CreateFromFile(mParent, localFile);
+    nsCOMPtr<nsIDOMBlob> domFile = File::CreateFromFile(mParent, localFile);
     domFile.forget(aResult);
     return NS_OK;
   }
 
   NS_IMETHOD
   HasMoreElements(bool* aResult) override
   {
     return mIterator->HasMoreElements(aResult);
@@ -306,28 +306,28 @@ nsBaseFilePicker::SetAddToRecentDocs(boo
 NS_IMETHODIMP
 nsBaseFilePicker::GetMode(int16_t* aMode)
 {
   *aMode = mMode;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsBaseFilePicker::GetDomfile(nsIDOMFile** aDomfile)
+nsBaseFilePicker::GetDomfile(nsISupports** aDomfile)
 {
   nsCOMPtr<nsIFile> localFile;
   nsresult rv = GetFile(getter_AddRefs(localFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!localFile) {
     *aDomfile = nullptr;
     return NS_OK;
   }
 
-  nsRefPtr<File> domFile = File::CreateFromFile(mParent, localFile);
+  nsCOMPtr<nsIDOMBlob> domFile = File::CreateFromFile(mParent, localFile);
   domFile.forget(aDomfile);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseFilePicker::GetDomfiles(nsISimpleEnumerator** aDomfiles)
 {
   nsCOMPtr<nsISimpleEnumerator> iter;
--- a/widget/nsBaseFilePicker.h
+++ b/widget/nsBaseFilePicker.h
@@ -32,17 +32,17 @@ public:
   NS_IMETHOD SetFilterIndex(int32_t aFilterIndex);
   NS_IMETHOD GetFiles(nsISimpleEnumerator **aFiles);
   NS_IMETHOD GetDisplayDirectory(nsIFile * *aDisplayDirectory);
   NS_IMETHOD SetDisplayDirectory(nsIFile * aDisplayDirectory);
   NS_IMETHOD GetAddToRecentDocs(bool *aFlag);
   NS_IMETHOD SetAddToRecentDocs(bool aFlag);
   NS_IMETHOD GetMode(int16_t *aMode);
 
-  NS_IMETHOD GetDomfile(nsIDOMFile** aDomfile);
+  NS_IMETHOD GetDomfile(nsISupports** aDomfile);
   NS_IMETHOD GetDomfiles(nsISimpleEnumerator** aDomfiles);
 
 protected:
 
   virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle) = 0;
 
   bool mAddToRecentDocs;
   nsCOMPtr<nsIFile> mDisplayDirectory;
--- a/widget/nsFilePickerProxy.cpp
+++ b/widget/nsFilePickerProxy.cpp
@@ -160,39 +160,81 @@ nsFilePickerProxy::Recv__delete__(const 
 
       if (!blobImpl->IsFile()) {
         return true;
       }
 
       nsRefPtr<File> file = File::Create(mParent, blobImpl);
       MOZ_ASSERT(file);
 
-      mDomfiles.AppendObject(file);
+      mDomfiles.AppendElement(file);
     }
   }
 
   if (mCallback) {
     mCallback->Done(aResult);
     mCallback = nullptr;
   }
 
   return true;
 }
 
 NS_IMETHODIMP
-nsFilePickerProxy::GetDomfile(nsIDOMFile** aDomfile)
+nsFilePickerProxy::GetDomfile(nsISupports** aDomfile)
 {
   *aDomfile = nullptr;
   if (mDomfiles.IsEmpty()) {
     return NS_OK;
   }
 
   MOZ_ASSERT(mDomfiles.Length() == 1);
-  nsCOMPtr<nsIDOMFile> domfile = mDomfiles[0];
-  domfile.forget(aDomfile);
+  nsCOMPtr<nsIDOMBlob> blob = mDomfiles[0].get();
+  blob.forget(aDomfile);
   return NS_OK;
 }
 
+namespace {
+
+class SimpleEnumerator final : public nsISimpleEnumerator
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  explicit SimpleEnumerator(const nsTArray<nsRefPtr<File>>& aFiles)
+    : mFiles(aFiles)
+    , mIndex(0)
+  {}
+
+  NS_IMETHOD
+  HasMoreElements(bool* aRetvalue) override
+  {
+    MOZ_ASSERT(aRetvalue);
+    *aRetvalue = mFiles.Length() >= mIndex;
+    return NS_OK;
+  }
+
+  NS_IMETHOD
+  GetNext(nsISupports** aSupports) override
+  {
+    nsCOMPtr<nsIDOMBlob> blob = mFiles[mIndex++].get();
+    blob.forget(aSupports);
+    return NS_OK;
+  }
+
+private:
+  ~SimpleEnumerator()
+  {}
+
+  nsTArray<nsRefPtr<File>> mFiles;
+  uint32_t mIndex;
+};
+
+NS_IMPL_ISUPPORTS(SimpleEnumerator, nsISimpleEnumerator)
+
+} // anonymous namespace
+
 NS_IMETHODIMP
 nsFilePickerProxy::GetDomfiles(nsISimpleEnumerator** aDomfiles)
 {
-  return NS_NewArrayEnumerator(aDomfiles, mDomfiles);
+  nsRefPtr<SimpleEnumerator> enumerator = new SimpleEnumerator(mDomfiles);
+  enumerator.forget(aDomfiles);
+  return NS_OK;
 }
--- a/widget/nsFilePickerProxy.h
+++ b/widget/nsFilePickerProxy.h
@@ -13,16 +13,22 @@
 #include "nsCOMArray.h"
 
 #include "mozilla/dom/PFilePickerChild.h"
 
 class nsIWidget;
 class nsIFile;
 class nsPIDOMWindow;
 
+namespace mozilla {
+namespace dom {
+class File;
+}
+}
+
 /**
   This class creates a proxy file picker to be used in content processes.
   The file picker just collects the initialization data and when Show() is
   called, remotes everything to the chrome process which in turn can show a
   platform specific file picker.
 */
 class nsFilePickerProxy : public nsBaseFilePicker,
                           public mozilla::dom::PFilePickerChild
@@ -40,31 +46,31 @@ public:
     NS_IMETHODIMP GetDefaultExtension(nsAString& aDefaultExtension) override;
     NS_IMETHODIMP SetDefaultExtension(const nsAString& aDefaultExtension) override;
     NS_IMETHODIMP GetFilterIndex(int32_t* aFilterIndex) override;
     NS_IMETHODIMP SetFilterIndex(int32_t aFilterIndex) override;
     NS_IMETHODIMP GetFile(nsIFile** aFile) override;
     NS_IMETHODIMP GetFileURL(nsIURI** aFileURL) override;
     NS_IMETHODIMP GetFiles(nsISimpleEnumerator** aFiles) override;
 
-    NS_IMETHODIMP GetDomfile(nsIDOMFile** aFile) override;
+    NS_IMETHODIMP GetDomfile(nsISupports** aFile) override;
     NS_IMETHODIMP GetDomfiles(nsISimpleEnumerator** aFiles) override;
 
     NS_IMETHODIMP Show(int16_t* aReturn) override;
     NS_IMETHODIMP Open(nsIFilePickerShownCallback* aCallback) override;
 
     // PFilePickerChild
     virtual bool
     Recv__delete__(const MaybeInputFiles& aFiles, const int16_t& aResult) override;
 
 private:
     ~nsFilePickerProxy();
     void InitNative(nsIWidget*, const nsAString&) override;
 
-    nsCOMArray<nsIDOMFile> mDomfiles;
+    nsTArray<nsRefPtr<mozilla::dom::File>> mDomfiles;
     nsCOMPtr<nsIFilePickerShownCallback> mCallback;
 
     int16_t   mSelectedType;
     nsString  mFile;
     nsString  mDefault;
     nsString  mDefaultExtension;
 
     InfallibleTArray<nsString> mFilters;
--- a/widget/nsIFilePicker.idl
+++ b/widget/nsIFilePicker.idl
@@ -3,33 +3,32 @@
  * 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/. */
 
 #include "nsISupports.idl"
 
 interface nsIFile;
 interface nsIURI;
-interface nsIDOMFile;
 interface nsIDOMWindow;
 interface nsISimpleEnumerator;
 
 [scriptable, function, uuid(0d79adad-b244-49A5-9997-2a8cad93fc44)]
 interface nsIFilePickerShownCallback : nsISupports
 {
  /**
   * Callback which is called when a filepicker is shown and a result
   * is returned.
   *
   * @param aResult One of returnOK, returnCancel, or returnReplace
   */
   void done(in short aResult);
 };
 
-[scriptable, uuid(f93509a0-0434-11e3-8ffd-0800200c9a66)]
+[scriptable, uuid(9840d564-42c8-4d78-9a4d-71002343c918)]
 interface nsIFilePicker : nsISupports
 {
   const short modeOpen        = 0;              // Load a file or directory
   const short modeSave        = 1;              // Save a file or directory
   const short modeGetFolder   = 2;              // Select a folder/directory
   const short modeOpenMultiple= 3;              // Load multiple files
 
   const short returnOK        = 0;              // User hit Ok, process selection
@@ -138,21 +137,21 @@ interface nsIFilePicker : nsISupports
   * Get the enumerator for the selected files
   * only works in the modeOpenMultiple mode
   *
   * @return Returns the files currently selected
   */
   readonly attribute nsISimpleEnumerator files;
 
  /**
-  * Get the nsIDOMFile for the file.
+  * Get the DOM File for the file.
   *
   * @return Returns the file currently selected as File
   */
-  readonly attribute nsIDOMFile domfile;
+  readonly attribute nsISupports domfile;
 
  /**
   * Get the enumerator for the selected files
   * only works in the modeOpenMultiple mode
   *
   * @return Returns the files currently selected as Files
   */
   readonly attribute nsISimpleEnumerator domfiles;