Backed out 7 changesets (bug 1047483, bug 1079301, bug 1079335) for webplatform test failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 07 Oct 2014 13:16:11 -0400
changeset 232411 47a1219c63246bd760e74c88ed67a722c0230367
parent 232410 7d06b68c44d08db324aba6173f0c2681e82bd390
child 232412 e1b7ef73bdaea35e97cdd4ce48eeb12b873d1a0e
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1047483, 1079301, 1079335
milestone35.0a1
backs out7d06b68c44d08db324aba6173f0c2681e82bd390
92030169528eebbb1d4daf24976209fd6881ad33
c09d7f95554aedf53620a150a4f3c494d21820b7
c199f1057d7efc897cabb123ca9dd349c94eb33f
18830d07884c13f1d7af36fbad444c4578859630
e087289ccfbb9db1a0b471b6baa665810d95edaf
6238ff5d3ed0cdc42ec39ec772a1ffd705ed7846
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
Backed out 7 changesets (bug 1047483, bug 1079301, bug 1079335) for webplatform test failures. Backed out changeset 7d06b68c44d0 (bug 1079335) Backed out changeset 92030169528e (bug 1079301) Backed out changeset c09d7f95554a (bug 1047483) Backed out changeset c199f1057d7e (bug 1047483) Backed out changeset 18830d07884c (bug 1047483) Backed out changeset e087289ccfbb (bug 1047483) Backed out changeset 6238ff5d3ed0 (bug 1047483) CLOSED TREE
CLOBBER
b2g/components/FilePicker.js
b2g/components/test/mochitest/test_filepicker_path.html
browser/base/content/test/general/browser_blob-channelname.js
content/base/public/BlobSet.h
content/base/public/File.h
content/base/public/moz.build
content/base/public/nsContentUtils.h
content/base/public/nsDOMFile.h
content/base/src/File.cpp
content/base/src/FileIOObject.cpp
content/base/src/MultipartFileImpl.cpp
content/base/src/MultipartFileImpl.h
content/base/src/WebSocket.cpp
content/base/src/WebSocket.h
content/base/src/moz.build
content/base/src/nsContentUtils.cpp
content/base/src/nsDOMBlobBuilder.cpp
content/base/src/nsDOMBlobBuilder.h
content/base/src/nsDOMDataChannel.cpp
content/base/src/nsDOMDataChannel.h
content/base/src/nsDOMFile.cpp
content/base/src/nsDOMFileReader.cpp
content/base/src/nsDOMFileReader.h
content/base/src/nsFormData.cpp
content/base/src/nsFormData.h
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsHostObjectProtocolHandler.cpp
content/base/src/nsXMLHttpRequest.cpp
content/base/src/nsXMLHttpRequest.h
content/base/test/chrome/test_bug914381.html
content/base/test/test_blobconstructor.html
content/base/test/test_bug403852.html
content/html/content/public/HTMLCanvasElement.h
content/html/content/src/HTMLCanvasElement.cpp
content/html/content/src/HTMLInputElement.cpp
content/html/content/src/HTMLInputElement.h
content/html/content/test/test_formData.html
content/media/EncodedBufferCache.cpp
content/media/EncodedBufferCache.h
content/media/MediaRecorder.cpp
content/media/imagecapture/CaptureTask.cpp
content/media/imagecapture/CaptureTask.h
content/media/imagecapture/ImageCapture.cpp
content/media/imagecapture/ImageCapture.h
content/media/webrtc/MediaEngine.h
content/media/webrtc/MediaEngineDefault.cpp
content/media/webrtc/MediaEngineWebRTC.h
content/media/webrtc/MediaEngineWebRTCVideo.cpp
dom/archivereader/ArchiveEvent.cpp
dom/archivereader/ArchiveEvent.h
dom/archivereader/ArchiveReader.cpp
dom/archivereader/ArchiveReader.h
dom/archivereader/ArchiveZipEvent.cpp
dom/archivereader/ArchiveZipEvent.h
dom/archivereader/ArchiveZipFile.cpp
dom/archivereader/ArchiveZipFile.h
dom/base/ImageEncoder.cpp
dom/base/ImageEncoder.h
dom/base/MessagePort.cpp
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/URL.cpp
dom/base/URL.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsDOMWindowUtils.cpp
dom/base/nsGlobalWindow.cpp
dom/base/test/file_url.jsm
dom/base/test/test_messageChannel_post.html
dom/bindings/Bindings.conf
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothAdapter.h
dom/bluetooth/bluedroid/BluetoothOppManager.cpp
dom/bluetooth/bluez/BluetoothOppManager.cpp
dom/browser-element/BrowserElementParent.jsm
dom/camera/DOMCameraControl.cpp
dom/camera/DOMCameraControlListener.cpp
dom/contacts/ContactManager.js
dom/contacts/tests/test_contacts_blobs.html
dom/devicestorage/DeviceStorageRequestChild.cpp
dom/devicestorage/DeviceStorageRequestParent.cpp
dom/devicestorage/nsDeviceStorage.cpp
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
dom/events/test/test_eventctors.html
dom/fetch/Request.cpp
dom/filehandle/FileHandle.cpp
dom/filehandle/FileHandle.h
dom/filesystem/CreateFileTask.cpp
dom/filesystem/CreateFileTask.h
dom/filesystem/DeviceStorageFileSystem.cpp
dom/filesystem/DeviceStorageFileSystem.h
dom/filesystem/Directory.cpp
dom/filesystem/Directory.h
dom/filesystem/FileSystemBase.h
dom/filesystem/FileSystemTaskBase.cpp
dom/filesystem/GetFileOrDirectoryTask.cpp
dom/filesystem/GetFileOrDirectoryTask.h
dom/filesystem/RemoveTask.cpp
dom/filesystem/RemoveTask.h
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/FileSnapshot.cpp
dom/indexedDB/FileSnapshot.h
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBDatabase.h
dom/indexedDB/IDBMutableFile.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBTransaction.h
dom/indexedDB/IndexedDatabase.h
dom/indexedDB/IndexedDatabaseInlines.h
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/IndexedDatabaseManager.h
dom/indexedDB/test/unit/test_temporary_storage.js
dom/ipc/Blob.cpp
dom/ipc/BlobChild.h
dom/ipc/BlobParent.h
dom/ipc/ContentBridgeChild.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/FilePickerParent.cpp
dom/ipc/StructuredCloneUtils.cpp
dom/ipc/StructuredCloneUtils.h
dom/ipc/nsIContentChild.cpp
dom/ipc/nsIContentChild.h
dom/ipc/nsIContentParent.cpp
dom/ipc/nsIContentParent.h
dom/media/MediaManager.cpp
dom/mobilemessage/MmsMessage.cpp
dom/mobilemessage/MmsMessage.h
dom/mobilemessage/gonk/WspPduHelper.jsm
dom/mobilemessage/ipc/SmsParent.cpp
dom/network/UDPSocket.cpp
dom/settings/SettingsDB.jsm
dom/webidl/Blob.webidl
dom/webidl/BlobEvent.webidl
dom/webidl/Directory.webidl
dom/webidl/File.webidl
dom/webidl/FileList.webidl
dom/webidl/FileReaderSync.webidl
dom/webidl/HTMLCanvasElement.webidl
dom/webidl/XMLHttpRequest.webidl
dom/workers/File.cpp
dom/workers/File.h
dom/workers/FileReaderSync.cpp
dom/workers/FileReaderSync.h
dom/workers/RegisterBindings.cpp
dom/workers/URL.cpp
dom/workers/URL.h
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/XMLHttpRequest.cpp
dom/workers/XMLHttpRequest.h
dom/workers/moz.build
dom/workers/test/fileReaderSyncErrors_worker.js
ipc/glue/BackgroundImpl.cpp
ipc/glue/BackgroundParent.h
ipc/glue/InputStreamUtils.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/ExportHelpers.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/xpcprivate.h
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
layout/build/nsLayoutModule.cpp
parser/html/nsHtml5StreamParser.cpp
testing/specialpowers/content/MockFilePicker.jsm
toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
toolkit/crashreporter/CrashSubmit.jsm
toolkit/modules/PropertyListUtils.jsm
widget/nsIFilePicker.idl
widget/xpwidgets/nsBaseFilePicker.cpp
widget/xpwidgets/nsBaseFilePicker.h
widget/xpwidgets/nsFilePickerProxy.cpp
widget/xpwidgets/nsFilePickerProxy.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1047483 - Porting DOMFile/DOMBlob to WebIDL requires CLOBBER
+Bug 1069071: IPDL changes require CLOBBER
--- a/b2g/components/FilePicker.js
+++ b/b2g/components/FilePicker.js
@@ -176,17 +176,17 @@ FilePicker.prototype = {
 
     let data = message.data;
     if (!data.success || !data.result.blob) {
       this.fireError();
       return;
     }
 
     // The name to be shown can be part of the message, or can be taken from
-    // the File (if the blob is a File).
+    // the DOMFile (if the blob is a DOMFile).
     let name = data.result.name;
     if (!name &&
         (data.result.blob instanceof this.mParent.File) &&
         data.result.blob.name) {
       name = data.result.blob.name;
     }
 
     // Let's try to remove the full path and take just the filename.
@@ -202,19 +202,19 @@ FilePicker.prototype = {
         let mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
         let mimeInfo = mimeSvc.getFromTypeAndExtension(data.result.blob.type, '');
         if (mimeInfo) {
           name += '.' + mimeInfo.primaryExtension;
         }
       }
     }
 
-    let file = new this.mParent.File([data.result.blob],
-                                     name,
-                                     { type: data.result.blob.type });
+    let file = new this.mParent.File(data.result.blob,
+                                     { name: name,
+                                       type: data.result.blob.type });
 
     if (file) {
       this.fireSuccess(file);
     } else {
       this.fireError();
     }
   }
 };
--- a/b2g/components/test/mochitest/test_filepicker_path.html
+++ b/b2g/components/test/mochitest/test_filepicker_path.html
@@ -62,17 +62,17 @@ var testCases = [
                               blob: new File(['1234567890'],
                                              'useless-name.txt',
                                              { type: 'text/plain' }),
                               name: 'test5.txt'
                             }
                 },
     fileName: 'test5.txt'},
   // case 6: returns file without name. This case may fail because we
-  //         need to make sure the File can be sent through
+  //         need to make sure the DOMFile can be sent through
   //         sendAsyncMessage API.
   { pickedResult: { success: true,
                     result: {
                               type: 'text/plain',
                               blob: new File(['1234567890'],
                                              'test6.txt',
                                              { type: 'text/plain' })
                             }
@@ -91,17 +91,17 @@ chromeScript.addMessageListener('file-pi
 function handleMessage(data) {
   var fileInput = document.getElementById('fileInput');
   switch (data.type) {
     case 'pick-result-updated':
       fileInput.click();
       break;
     case 'file-picked-posted':
       is(fileInput.value, activeTestCase.fileName,
-         'File should be able to send through message.');
+         'DOMFile should be able to send through message.');
       processTestCase();
       break;
   }
 }
 
 function processTestCase() {
   if (!testCases.length) {
     SimpleTest.finish();
@@ -122,9 +122,9 @@ function processTestCase() {
     expectedResult.result.name = name
   }
   chromeScript.sendAsyncMessage('update-pick-result', expectedResult);
 }
 
 </script>
 <input type="file" id="fileInput">
 </body>
-</html>
+</html>
\ No newline at end of file
--- a/browser/base/content/test/general/browser_blob-channelname.js
+++ b/browser/base/content/test/general/browser_blob-channelname.js
@@ -1,11 +1,11 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 Cu.import("resource://gre/modules/NetUtil.jsm");
 
 function test() {
-    var file = new File([new Blob(['test'], {type: 'text/plain'})], "test-name");
+    var file = new File(new Blob(['test'], {type: 'text/plain'}), {name: 'test-name'});
     var url = URL.createObjectURL(file);
     var channel = NetUtil.newChannel(url);
 
     is(channel.contentDispositionFilename, 'test-name', "filename matches");
 }
deleted file mode 100644
--- a/content/base/public/BlobSet.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*- Mode: C++; 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/. */
-
-#ifndef mozilla_dom_BlobSet_h
-#define mozilla_dom_BlobSet_h
-
-#include "mozilla/CheckedInt.h"
-#include "mozilla/dom/File.h"
-
-namespace mozilla {
-namespace dom {
-
-class BlobSet {
-public:
-  BlobSet()
-    : mData(nullptr), mDataLen(0), mDataBufferLen(0)
-  {}
-
-  ~BlobSet()
-  {
-    moz_free(mData);
-  }
-
-  nsresult AppendVoidPtr(const void* aData, uint32_t aLength);
-  nsresult AppendString(const nsAString& aString, bool nativeEOL, JSContext* aCx);
-  nsresult AppendBlobImpl(FileImpl* aBlobImpl);
-  nsresult AppendBlobImpls(const nsTArray<nsRefPtr<FileImpl>>& aBlobImpls);
-
-  nsTArray<nsRefPtr<FileImpl>>& GetBlobImpls() { Flush(); return mBlobImpls; }
-
-  already_AddRefed<File> GetBlobInternal(nsISupports* aParent,
-                                         const nsACString& aContentType);
-
-protected:
-  bool ExpandBufferSize(uint64_t aSize)
-  {
-    using mozilla::CheckedUint32;
-
-    if (mDataBufferLen >= mDataLen + aSize) {
-      mDataLen += aSize;
-      return true;
-    }
-
-    // Start at 1 or we'll loop forever.
-    CheckedUint32 bufferLen =
-      std::max<uint32_t>(static_cast<uint32_t>(mDataBufferLen), 1);
-    while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize)
-      bufferLen *= 2;
-
-    if (!bufferLen.isValid())
-      return false;
-
-    void* data = moz_realloc(mData, bufferLen.value());
-    if (!data)
-      return false;
-
-    mData = data;
-    mDataBufferLen = bufferLen.value();
-    mDataLen += aSize;
-    return true;
-  }
-
-  void Flush() {
-    if (mData) {
-      // If we have some data, create a blob for it
-      // and put it on the stack
-
-      nsRefPtr<FileImpl> blobImpl =
-        new FileImplMemory(mData, mDataLen, EmptyString());
-      mBlobImpls.AppendElement(blobImpl);
-      mData = nullptr; // The nsDOMMemoryFile takes ownership of the buffer
-      mDataLen = 0;
-      mDataBufferLen = 0;
-    }
-  }
-
-  nsTArray<nsRefPtr<FileImpl>> mBlobImpls;
-  void* mData;
-  uint64_t mDataLen;
-  uint64_t mDataBufferLen;
-};
-
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_BlobSet_h
--- a/content/base/public/moz.build
+++ b/content/base/public/moz.build
@@ -38,16 +38,17 @@ EXPORTS += [
     'nsContentCID.h',
     'nsContentCreatorFunctions.h',
     'nsContentPolicyUtils.h',
     'nsContentTypeParser.h',
     'nsContentUtils.h',
     'nsCopySupport.h',
     'nsDeprecatedOperationList.h',
     'nsDocElementCreatedNotificationRunner.h',
+    'nsDOMFile.h',
     'nsHostObjectProtocolHandler.h',
     'nsIAttribute.h',
     'nsIContent.h',
     'nsIContentInlines.h',
     'nsIContentIterator.h',
     'nsIContentSerializer.h',
     'nsIDocument.h',
     'nsIDocumentInlines.h',
@@ -61,21 +62,19 @@ EXPORTS += [
     'nsNameSpaceManager.h',
     'nsReferencedElement.h',
     'nsTreeSanitizer.h',
     'nsViewportInfo.h',
     'nsXMLNameSpaceMap.h',
 ]
 
 EXPORTS.mozilla.dom += [
-    'BlobSet.h',
     'DirectionalityUtils.h',
     'Element.h',
     'ElementInlines.h',
-    'File.h',
     'FragmentOrElement.h',
     'FromParser.h',
 ]
 
 EXPORTS.mozilla += [
     'CORSMode.h',
 ]
 
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1664,17 +1664,16 @@ public:
 
   /**
    * Creates an arraybuffer from a binary string.
    */
   static nsresult CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
                                     JSObject** aResult);
 
   static nsresult CreateBlobBuffer(JSContext* aCx,
-                                   nsISupports* aParent,
                                    const nsACString& aData,
                                    JS::MutableHandle<JS::Value> aBlob);
 
   static void StripNullChars(const nsAString& aInStr, nsAString& aOutStr);
 
   /**
    * Strip all \n, \r and nulls from the given string
    * @param aString the string to remove newlines from [in/out]
rename from content/base/public/File.h
rename to content/base/public/nsDOMFile.h
--- a/content/base/public/File.h
+++ b/content/base/public/nsDOMFile.h
@@ -1,267 +1,209 @@
 /* -*- Mode: C++; 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/. */
 
-#ifndef mozilla_dom_File_h
-#define mozilla_dom_File_h
+#ifndef nsDOMFile_h__
+#define nsDOMFile_h__
 
 #include "mozilla/Attributes.h"
+#include "nsICharsetDetectionObserver.h"
+#include "nsIFile.h"
+#include "nsIDOMFile.h"
+#include "nsIDOMFileList.h"
+#include "nsIInputStream.h"
+#include "nsIJSNativeInitializer.h"
+#include "nsIMutable.h"
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsIXMLHttpRequest.h"
+#include "nsAutoPtr.h"
+#include "nsFileStreams.h"
+#include "nsTemporaryFileInputStream.h"
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
+#include <stdint.h>
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
-#include "mozilla/dom/Date.h"
+#include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/indexedDB/FileInfo.h"
 #include "mozilla/dom/indexedDB/FileManager.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
-#include "mozilla/dom/UnionTypes.h"
-#include "nsAutoPtr.h"
+#include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMFile.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"
 
 class nsDOMMultipartFile;
 class nsIFile;
 class nsIInputStream;
 class nsIClassInfo;
 
-#define PIFILEIMPL_IID \
+#define PIDOMFILEIMPL_IID \
   { 0x218ee173, 0xf44f, 0x4d30, \
     { 0xab, 0x0c, 0xd6, 0x66, 0xea, 0xc2, 0x84, 0x47 } }
 
-class PIFileImpl : public nsISupports
+class PIDOMFileImpl : public nsISupports
 {
 public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(PIFILEIMPL_IID)
+  NS_DECLARE_STATIC_IID_ACCESSOR(PIDOMFILEIMPL_IID)
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(PIFileImpl, PIFILEIMPL_IID)
+NS_DEFINE_STATIC_IID_ACCESSOR(PIDOMFileImpl, PIDOMFILEIMPL_IID)
 
 namespace mozilla {
 namespace dom {
 
 namespace indexedDB {
 class FileInfo;
 };
 
-struct BlobPropertyBag;
-struct ChromeFilePropertyBag;
-struct FilePropertyBag;
-class FileImpl;
+class DOMFileImpl;
 
-class File MOZ_FINAL : public nsIDOMFile
-                     , public nsIXHRSendable
-                     , public nsIMutable
-                     , public nsSupportsWeakReference
-                     , public nsWrapperCache
+class DOMFile MOZ_FINAL : public nsIDOMFile
+                        , public nsIXHRSendable
+                        , public nsIMutable
+                        , public nsIJSNativeInitializer
+                        , public nsSupportsWeakReference
 {
 public:
   NS_DECL_NSIDOMBLOB
   NS_DECL_NSIDOMFILE
   NS_DECL_NSIXHRSENDABLE
   NS_DECL_NSIMUTABLE
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(File, nsIDOMFile)
-
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aName,
-         const nsAString& aContentType, uint64_t aLength,
-         uint64_t aLastModifiedDate);
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DOMFile, nsIDOMFile)
 
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aName,
-         const nsAString& aContentType, uint64_t aLength);
+  static already_AddRefed<DOMFile>
+  Create(const nsAString& aName, const nsAString& aContentType,
+         uint64_t aLength, uint64_t aLastModifiedDate);
 
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aContentType,
+  static already_AddRefed<DOMFile>
+  Create(const nsAString& aName, const nsAString& aContentType,
          uint64_t aLength);
 
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aContentType, uint64_t aStart,
+  static already_AddRefed<DOMFile>
+  Create(const nsAString& aContentType, uint64_t aLength);
+
+  static already_AddRefed<DOMFile>
+  Create(const nsAString& aContentType, uint64_t aStart,
          uint64_t aLength);
 
-  static already_AddRefed<File>
-  CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
+  static already_AddRefed<DOMFile>
+  CreateMemoryFile(void* aMemoryBuffer, uint64_t aLength,
                    const nsAString& aName, const nsAString& aContentType,
                    uint64_t aLastModifiedDate);
 
-  static already_AddRefed<File>
-  CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
+  static already_AddRefed<DOMFile>
+  CreateMemoryFile(void* aMemoryBuffer, uint64_t aLength,
                    const nsAString& aContentType);
 
-  static already_AddRefed<File>
-  CreateTemporaryFileBlob(nsISupports* aParent, PRFileDesc* aFD,
-                          uint64_t aStartPos, uint64_t aLength,
+  static already_AddRefed<DOMFile>
+  CreateTemporaryFileBlob(PRFileDesc* aFD, uint64_t aStartPos,
+                          uint64_t aLength,
                           const nsAString& aContentType);
 
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile);
+  static already_AddRefed<DOMFile>
+  CreateFromFile(nsIFile* aFile);
 
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, const nsAString& aContentType,
-                 uint64_t aLength, nsIFile* aFile,
-                 indexedDB::FileInfo* aFileInfo);
-
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, const nsAString& aName,
-                 const nsAString& aContentType, uint64_t aLength,
+  static already_AddRefed<DOMFile>
+  CreateFromFile(const nsAString& aContentType, uint64_t aLength,
                  nsIFile* aFile, indexedDB::FileInfo* aFileInfo);
 
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                 indexedDB::FileInfo* aFileInfo);
+  static already_AddRefed<DOMFile>
+  CreateFromFile(const nsAString& aName, const nsAString& aContentType,
+                 uint64_t aLength, nsIFile* aFile,
+                    indexedDB::FileInfo* aFileInfo);
 
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile, const nsAString& aName,
+  static already_AddRefed<DOMFile>
+  CreateFromFile(nsIFile* aFile, indexedDB::FileInfo* aFileInfo);
+
+  static already_AddRefed<DOMFile>
+  CreateFromFile(nsIFile* aFile, const nsAString& aName,
                  const nsAString& aContentType);
 
-  File(nsISupports* aParent, FileImpl* aImpl);
+  explicit DOMFile(DOMFileImpl* aImpl)
+    : mImpl(aImpl)
+  {
+    MOZ_ASSERT(mImpl);
+  }
 
-  FileImpl* Impl() const
+  DOMFileImpl* Impl() const
   {
     return mImpl;
   }
 
-  const nsTArray<nsRefPtr<FileImpl>>* GetSubBlobImpls() const;
+  const nsTArray<nsRefPtr<DOMFileImpl>>* GetSubBlobImpls() const;
 
   bool IsSizeUnknown() const;
 
   bool IsDateUnknown() const;
 
   bool IsFile() const;
 
   void SetLazyData(const nsAString& aName, const nsAString& aContentType,
                    uint64_t aLength, uint64_t aLastModifiedDate);
 
-  already_AddRefed<File>
-  CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
-              ErrorResult& aRv);
-
-  // WebIDL methods
-  nsISupports* GetParentObject() const
-  {
-    return mParent;
-  }
-
-  // Blob constructor
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
-
-  // Blob constructor
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
-              const BlobPropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // File constructor
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
-              const nsAString& aName,
-              const FilePropertyBag& aBag,
-              ErrorResult& aRv);
+  already_AddRefed<nsIDOMBlob>
+  CreateSlice(uint64_t aStart, uint64_t aLength,
+              const nsAString& aContentType);
 
-  // File constructor - ChromeOnly
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              File& aData,
-              const ChromeFilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // File constructor - ChromeOnly
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const nsAString& aData,
-              const ChromeFilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // File constructor - ChromeOnly
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              nsIFile* aData,
-              const ChromeFilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
-
-  uint64_t GetSize(ErrorResult& aRv);
-
-  // XPCOM GetType is OK
-
-  // XPCOM GetName is OK
-
-  int64_t GetLastModified(ErrorResult& aRv);
-
-  Date GetLastModifiedDate(ErrorResult& aRv);
-
-  void GetMozFullPath(nsAString& aFilename, ErrorResult& aRv);
-
-  already_AddRefed<File> Slice(const Optional<int64_t>& aStart,
-                               const Optional<int64_t>& aEnd,
-                               const nsAString& aContentType,
-                               ErrorResult& aRv);
+  // nsIJSNativeInitializer
+  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
+                        const JS::CallArgs& aArgs) MOZ_OVERRIDE;
 
 private:
-  ~File() {};
+  ~DOMFile() {};
 
-  // The member is the real backend implementation of this File/Blob.
+  // The member is the real backend implementation of this DOMFile/DOMBlob.
   // It's thread-safe and not CC-able and it's the only element that is moved
   // between threads.
   // Note: we should not store any other state in this class!
-  const nsRefPtr<FileImpl> mImpl;
-
-  nsCOMPtr<nsISupports> mParent;
+  const nsRefPtr<DOMFileImpl> mImpl;
 };
 
-// This is the abstract class for any File backend. It must be nsISupports
+// This is the abstract class for any DOMFile backend. It must be nsISupports
 // because this class must be ref-counted and it has to work with IPC.
-class FileImpl : public PIFileImpl
+class DOMFileImpl : public PIDOMFileImpl
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
-  FileImpl() {}
+  DOMFileImpl() {}
 
-  virtual void GetName(nsAString& aName) = 0;
+  virtual nsresult GetName(nsAString& aName) = 0;
 
   virtual nsresult GetPath(nsAString& aName) = 0;
 
-  virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
-
-  virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) = 0;
+  virtual nsresult
+  GetLastModifiedDate(JSContext* aCx,
+                      JS::MutableHandle<JS::Value> aDate) = 0;
 
-  virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) = 0;
+  virtual nsresult GetMozFullPath(nsAString& aName) = 0;
 
-  virtual uint64_t GetSize(ErrorResult& aRv) = 0;
+  virtual nsresult GetMozFullPathInternal(nsAString &aFileName) = 0;
 
-  virtual void GetType(nsAString& aType) = 0;
+  virtual nsresult GetSize(uint64_t* aSize) = 0;
 
-  already_AddRefed<FileImpl>
-  Slice(const Optional<int64_t>& aStart, const Optional<int64_t>& aEnd,
-        const nsAString& aContentType, ErrorResult& aRv);
+  virtual nsresult GetType(nsAString& aType) = 0;
+
+  virtual nsresult GetMozLastModifiedDate(uint64_t* aDate) = 0;
 
-  virtual already_AddRefed<FileImpl>
+  nsresult Slice(int64_t aStart, int64_t aEnd, const nsAString& aContentType,
+                 uint8_t aArgc, DOMFileImpl** aBlobImpl);
+
+  virtual already_AddRefed<DOMFileImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) = 0;
+              const nsAString& aContentType) = 0;
 
-  virtual const nsTArray<nsRefPtr<FileImpl>>*
+  virtual const nsTArray<nsRefPtr<DOMFileImpl>>*
   GetSubBlobImpls() const = 0;
 
   virtual nsresult GetInternalStream(nsIInputStream** aStream) = 0;
 
   virtual int64_t GetFileId() = 0;
 
   virtual void AddFileInfo(indexedDB::FileInfo* aFileInfo) = 0;
 
@@ -285,122 +227,118 @@ public:
   virtual bool IsMemoryFile() const = 0;
 
   virtual bool IsSizeUnknown() const = 0;
 
   virtual bool IsDateUnknown() const = 0;
 
   virtual bool IsFile() const = 0;
 
+  virtual nsresult Initialize(nsISupports* aOwner, JSContext* aCx,
+                              JSObject* aObj, const JS::CallArgs& aArgs) = 0;
+
   // These 2 methods are used when the implementation has to CC something.
   virtual void Unlink() = 0;
   virtual void Traverse(nsCycleCollectionTraversalCallback &aCb) = 0;
 
   virtual bool IsCCed() const
   {
     return false;
   }
 
 protected:
-  virtual ~FileImpl() {}
+  virtual ~DOMFileImpl() {}
 };
 
-class FileImplBase : public FileImpl
+class DOMFileImplBase : public DOMFileImpl
 {
 public:
-  FileImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, uint64_t aLastModifiedDate)
+  DOMFileImplBase(const nsAString& aName, const nsAString& aContentType,
+                  uint64_t aLength, uint64_t aLastModifiedDate)
     : mIsFile(true)
     , mImmutable(false)
     , mContentType(aContentType)
     , mName(aName)
     , mStart(0)
     , mLength(aLength)
     , mLastModificationDate(aLastModifiedDate)
   {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  FileImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength)
+  DOMFileImplBase(const nsAString& aName, const nsAString& aContentType,
+                  uint64_t aLength)
     : mIsFile(true)
     , mImmutable(false)
     , mContentType(aContentType)
     , mName(aName)
     , mStart(0)
     , mLength(aLength)
     , mLastModificationDate(UINT64_MAX)
   {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  FileImplBase(const nsAString& aContentType, uint64_t aLength)
+  DOMFileImplBase(const nsAString& aContentType, uint64_t aLength)
     : mIsFile(false)
     , mImmutable(false)
     , mContentType(aContentType)
     , mStart(0)
     , mLength(aLength)
     , mLastModificationDate(UINT64_MAX)
   {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  FileImplBase(const nsAString& aContentType, uint64_t aStart,
-               uint64_t aLength)
+  DOMFileImplBase(const nsAString& aContentType, uint64_t aStart,
+                  uint64_t aLength)
     : mIsFile(false)
     , mImmutable(false)
     , mContentType(aContentType)
     , mStart(aStart)
     , mLength(aLength)
     , mLastModificationDate(UINT64_MAX)
   {
     NS_ASSERTION(aLength != UINT64_MAX,
                  "Must know length when creating slice");
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  virtual void GetName(nsAString& aName) MOZ_OVERRIDE;
+  virtual nsresult GetName(nsAString& aName) MOZ_OVERRIDE;
 
   virtual nsresult GetPath(nsAString& aName) MOZ_OVERRIDE;
 
-  virtual int64_t GetLastModified(ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual nsresult GetLastModifiedDate(JSContext* aCx,
+                               JS::MutableHandle<JS::Value> aDate) MOZ_OVERRIDE;
 
-  virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual nsresult GetMozFullPath(nsAString& aName) MOZ_OVERRIDE;
 
-  virtual void GetMozFullPathInternal(nsAString& aFileName,
-                                      ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual nsresult GetMozFullPathInternal(nsAString& aFileName) MOZ_OVERRIDE;
+
+  virtual nsresult GetSize(uint64_t* aSize) MOZ_OVERRIDE;
 
-  virtual uint64_t GetSize(ErrorResult& aRv) MOZ_OVERRIDE
-  {
-    return mLength;
-  }
+  virtual nsresult GetType(nsAString& aType) MOZ_OVERRIDE;
 
-  virtual void GetType(nsAString& aType) MOZ_OVERRIDE;
+  virtual nsresult GetMozLastModifiedDate(uint64_t* aDate) MOZ_OVERRIDE;
 
-  virtual already_AddRefed<FileImpl>
+  virtual already_AddRefed<DOMFileImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) MOZ_OVERRIDE
-  {
-    return nullptr;
-  }
+              const nsAString& aContentType) MOZ_OVERRIDE;
 
-  virtual const nsTArray<nsRefPtr<FileImpl>>*
+  virtual const nsTArray<nsRefPtr<DOMFileImpl>>*
   GetSubBlobImpls() const MOZ_OVERRIDE
   {
     return nullptr;
   }
 
-  virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
+  virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
 
   virtual int64_t GetFileId() MOZ_OVERRIDE;
 
   virtual void AddFileInfo(indexedDB::FileInfo* aFileInfo) MOZ_OVERRIDE;
 
   virtual indexedDB::FileInfo*
   GetFileInfo(indexedDB::FileManager* aFileManager) MOZ_OVERRIDE;
 
@@ -457,21 +395,27 @@ public:
     return false;
   }
 
   virtual bool IsSizeUnknown() const
   {
     return mLength == UINT64_MAX;
   }
 
+  virtual nsresult Initialize(nsISupports* aOwner, JSContext* aCx,
+                              JSObject* aObj, const JS::CallArgs& aArgs)
+  {
+    return NS_OK;
+  }
+
   virtual void Unlink() {}
   virtual void Traverse(nsCycleCollectionTraversalCallback &aCb) {}
 
 protected:
-  virtual ~FileImplBase() {}
+  virtual ~DOMFileImplBase() {}
 
   indexedDB::FileInfo* GetFileInfo() const
   {
     NS_ASSERTION(IsStoredFile(), "Should only be called on stored files!");
     NS_ASSERTION(!mFileInfos.IsEmpty(), "Must have at least one file info!");
 
     return mFileInfos.ElementAt(0);
   }
@@ -491,42 +435,45 @@ protected:
   // Protected by IndexedDatabaseManager::FileMutex()
   nsTArray<nsRefPtr<indexedDB::FileInfo>> mFileInfos;
 };
 
 /**
  * This class may be used off the main thread, and in particular, its
  * constructor and destructor may not run on the same thread.  Be careful!
  */
-class FileImplMemory MOZ_FINAL : public FileImplBase
+class DOMFileImplMemory MOZ_FINAL : public DOMFileImplBase
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
-  FileImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
-                 const nsAString& aContentType, uint64_t aLastModifiedDate)
-    : FileImplBase(aName, aContentType, aLength, aLastModifiedDate)
+  DOMFileImplMemory(void* aMemoryBuffer, uint64_t aLength,
+                    const nsAString& aName,
+                    const nsAString& aContentType,
+                    uint64_t aLastModifiedDate)
+    : DOMFileImplBase(aName, aContentType, aLength, aLastModifiedDate)
     , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   {
     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
   }
 
-  FileImplMemory(void* aMemoryBuffer, uint64_t aLength,
-                 const nsAString& aContentType)
-    : FileImplBase(aContentType, aLength)
+  DOMFileImplMemory(void* aMemoryBuffer,
+                    uint64_t aLength,
+                    const nsAString& aContentType)
+    : DOMFileImplBase(aContentType, aLength)
     , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   {
     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
   }
 
   virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
 
-  virtual already_AddRefed<FileImpl>
+  virtual already_AddRefed<DOMFileImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) MOZ_OVERRIDE;
+              const nsAString& aContentType) MOZ_OVERRIDE;
 
   virtual bool IsMemoryFile() const MOZ_OVERRIDE
   {
     return true;
   }
 
   class DataOwner MOZ_FINAL : public mozilla::LinkedListElement<DataOwner> {
   public:
@@ -569,194 +516,195 @@ public:
     static bool sMemoryReporterRegistered;
 
     void* mData;
     uint64_t mLength;
   };
 
 private:
   // Create slice
-  FileImplMemory(const FileImplMemory* aOther, uint64_t aStart,
-                 uint64_t aLength, const nsAString& aContentType)
-    : FileImplBase(aContentType, aOther->mStart + aStart, aLength)
+  DOMFileImplMemory(const DOMFileImplMemory* aOther, uint64_t aStart,
+                    uint64_t aLength, const nsAString& aContentType)
+    : DOMFileImplBase(aContentType, aOther->mStart + aStart, aLength)
     , mDataOwner(aOther->mDataOwner)
   {
     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
     mImmutable = aOther->mImmutable;
   }
 
-  ~FileImplMemory() {}
+  ~DOMFileImplMemory() {}
 
   // Used when backed by a memory store
   nsRefPtr<DataOwner> mDataOwner;
 };
 
-class FileImplTemporaryFileBlob MOZ_FINAL : public FileImplBase
+class DOMFileImplTemporaryFileBlob MOZ_FINAL : public DOMFileImplBase
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
-  FileImplTemporaryFileBlob(PRFileDesc* aFD, uint64_t aStartPos,
-                            uint64_t aLength, const nsAString& aContentType)
-    : FileImplBase(aContentType, aLength)
+  DOMFileImplTemporaryFileBlob(PRFileDesc* aFD, uint64_t aStartPos,
+                               uint64_t aLength, const nsAString& aContentType)
+    : DOMFileImplBase(aContentType, aLength)
     , mLength(aLength)
     , mStartPos(aStartPos)
     , mContentType(aContentType)
   {
     mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
   }
 
   virtual nsresult GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
 
-  virtual already_AddRefed<FileImpl>
+  virtual already_AddRefed<DOMFileImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) MOZ_OVERRIDE;
+              const nsAString& aContentType) MOZ_OVERRIDE;
 
 private:
-  FileImplTemporaryFileBlob(const FileImplTemporaryFileBlob* aOther,
-                            uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType)
-    : FileImplBase(aContentType, aLength)
+  DOMFileImplTemporaryFileBlob(const DOMFileImplTemporaryFileBlob* aOther,
+                               uint64_t aStart, uint64_t aLength,
+                               const nsAString& aContentType)
+    : DOMFileImplBase(aContentType, aLength)
     , mLength(aLength)
     , mStartPos(aStart)
     , mFileDescOwner(aOther->mFileDescOwner)
     , mContentType(aContentType) {}
 
-  ~FileImplTemporaryFileBlob() {}
+  ~DOMFileImplTemporaryFileBlob() {}
 
   uint64_t mLength;
   uint64_t mStartPos;
   nsRefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
   nsString mContentType;
 };
 
-class FileImplFile : public FileImplBase
+class DOMFileImplFile : public DOMFileImplBase
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // Create as a file
-  explicit FileImplFile(nsIFile* aFile)
-    : FileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
+  explicit DOMFileImplFile(nsIFile* aFile)
+    : DOMFileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mStoredFile(false)
   {
     NS_ASSERTION(mFile, "must have file");
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
     mFile->GetLeafName(mName);
   }
 
-  FileImplFile(nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
-    : FileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
+  DOMFileImplFile(nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
+    : DOMFileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mStoredFile(true)
   {
     NS_ASSERTION(mFile, "must have file");
     NS_ASSERTION(aFileInfo, "must have file info");
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
     mFile->GetLeafName(mName);
 
     mFileInfos.AppendElement(aFileInfo);
   }
 
   // Create as a file
-  FileImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile)
-    : FileImplBase(aName, aContentType, aLength, UINT64_MAX)
+  DOMFileImplFile(const nsAString& aName, const nsAString& aContentType,
+                  uint64_t aLength, nsIFile* aFile)
+    : DOMFileImplBase(aName, aContentType, aLength, UINT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mStoredFile(false)
   {
     NS_ASSERTION(mFile, "must have file");
   }
 
-  FileImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile,
-               uint64_t aLastModificationDate)
-    : FileImplBase(aName, aContentType, aLength, aLastModificationDate)
+  DOMFileImplFile(const nsAString& aName, const nsAString& aContentType,
+                  uint64_t aLength, nsIFile* aFile,
+                  uint64_t aLastModificationDate)
+    : DOMFileImplBase(aName, aContentType, aLength, aLastModificationDate)
     , mFile(aFile)
     , mWholeFile(true)
     , mStoredFile(false)
   {
     NS_ASSERTION(mFile, "must have file");
   }
 
   // Create as a file with custom name
-  FileImplFile(nsIFile* aFile, const nsAString& aName,
-               const nsAString& aContentType)
-    : FileImplBase(aName, aContentType, UINT64_MAX, UINT64_MAX)
+  DOMFileImplFile(nsIFile* aFile, const nsAString& aName,
+                  const nsAString& aContentType)
+    : DOMFileImplBase(aName, aContentType, UINT64_MAX, UINT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mStoredFile(false)
   {
     NS_ASSERTION(mFile, "must have file");
     if (aContentType.IsEmpty()) {
       // Lazily get the content type and size
       mContentType.SetIsVoid(true);
     }
   }
 
   // Create as a stored file
-  FileImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile,
-               indexedDB::FileInfo* aFileInfo)
-    : FileImplBase(aName, aContentType, aLength, UINT64_MAX)
+  DOMFileImplFile(const nsAString& aName, const nsAString& aContentType,
+                  uint64_t aLength, nsIFile* aFile,
+                  indexedDB::FileInfo* aFileInfo)
+    : DOMFileImplBase(aName, aContentType, aLength, UINT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mStoredFile(true)
   {
     NS_ASSERTION(mFile, "must have file");
     mFileInfos.AppendElement(aFileInfo);
   }
 
   // Create as a stored blob
-  FileImplFile(const nsAString& aContentType, uint64_t aLength,
-               nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
-    : FileImplBase(aContentType, aLength)
+  DOMFileImplFile(const nsAString& aContentType, uint64_t aLength,
+                  nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
+    : DOMFileImplBase(aContentType, aLength)
     , mFile(aFile)
     , mWholeFile(true)
     , mStoredFile(true)
   {
     NS_ASSERTION(mFile, "must have file");
     mFileInfos.AppendElement(aFileInfo);
   }
 
   // Create as a file to be later initialized
-  FileImplFile()
-    : FileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
+  DOMFileImplFile()
+    : DOMFileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
     , mWholeFile(true)
     , mStoredFile(false)
   {
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
     mName.SetIsVoid(true);
   }
 
   // Overrides
-  virtual uint64_t GetSize(ErrorResult& aRv) MOZ_OVERRIDE;
-  virtual void GetType(nsAString& aType) MOZ_OVERRIDE;
-  virtual int64_t GetLastModified(ErrorResult& aRv) MOZ_OVERRIDE;
-  virtual void GetMozFullPathInternal(nsAString& aFullPath,
-                                      ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual nsresult GetSize(uint64_t* aSize) MOZ_OVERRIDE;
+  virtual nsresult GetType(nsAString& aType) MOZ_OVERRIDE;
+  virtual nsresult GetLastModifiedDate(JSContext* aCx,
+                               JS::MutableHandle<JS::Value> aLastModifiedDate) MOZ_OVERRIDE;
+  virtual nsresult GetMozLastModifiedDate(uint64_t* aLastModifiedDate) MOZ_OVERRIDE;
+  virtual nsresult GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
   virtual nsresult GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
 
   void SetPath(const nsAString& aFullPath);
 
 protected:
-  virtual ~FileImplFile() {}
+  virtual ~DOMFileImplFile() {}
 
 private:
   // Create slice
-  FileImplFile(const FileImplFile* aOther, uint64_t aStart,
-               uint64_t aLength, const nsAString& aContentType)
-    : FileImplBase(aContentType, aOther->mStart + aStart, aLength)
+  DOMFileImplFile(const DOMFileImplFile* aOther, uint64_t aStart,
+                  uint64_t aLength, const nsAString& aContentType)
+    : DOMFileImplBase(aContentType, aOther->mStart + aStart, aLength)
     , mFile(aOther->mFile)
     , mWholeFile(false)
     , mStoredFile(aOther->mStoredFile)
   {
     NS_ASSERTION(mFile, "must have file");
     mImmutable = aOther->mImmutable;
 
     if (mStoredFile) {
@@ -771,107 +719,99 @@ private:
         mozilla::MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
         fileInfo = aOther->GetFileInfo();
       }
 
       mFileInfos.AppendElement(fileInfo);
     }
   }
 
-  virtual already_AddRefed<FileImpl>
+  virtual already_AddRefed<DOMFileImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) MOZ_OVERRIDE;
+              const nsAString& aContentType) MOZ_OVERRIDE;
 
   virtual bool IsStoredFile() const MOZ_OVERRIDE
   {
     return mStoredFile;
   }
 
   virtual bool IsWholeFile() const MOZ_OVERRIDE
   {
     return mWholeFile;
   }
 
   nsCOMPtr<nsIFile> mFile;
   bool mWholeFile;
   bool mStoredFile;
 };
 
-class FileList MOZ_FINAL : public nsIDOMFileList,
-                           public nsWrapperCache
+} // dom namespace
+} // file namespace
+
+class nsDOMFileList MOZ_FINAL : public nsIDOMFileList,
+                                public nsWrapperCache
 {
-  ~FileList() {}
+  ~nsDOMFileList() {}
 
 public:
-  explicit FileList(nsISupports *aParent) : mParent(aParent)
+  explicit nsDOMFileList(nsISupports *aParent) : mParent(aParent)
   {
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FileList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMFileList)
 
   NS_DECL_NSIDOMFILELIST
 
   virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
 
   nsISupports* GetParentObject()
   {
     return mParent;
   }
 
   void Disconnect()
   {
     mParent = nullptr;
   }
 
-  bool Append(File *aFile) { return mFiles.AppendElement(aFile); }
+  bool Append(nsIDOMFile *aFile) { return mFiles.AppendObject(aFile); }
 
-  bool Remove(uint32_t aIndex) {
-    if (aIndex < mFiles.Length()) {
-      mFiles.RemoveElementAt(aIndex);
-      return true;
-    }
-
-    return false;
-  }
-
+  bool Remove(uint32_t aIndex) { return mFiles.RemoveObjectAt(aIndex); }
   void Clear() { return mFiles.Clear(); }
 
-  static FileList* FromSupports(nsISupports* aSupports)
+  static nsDOMFileList* FromSupports(nsISupports* aSupports)
   {
 #ifdef DEBUG
     {
       nsCOMPtr<nsIDOMFileList> list_qi = do_QueryInterface(aSupports);
 
       // If this assertion fires the QI implementation for the object in
       // question doesn't use the nsIDOMFileList pointer as the nsISupports
       // pointer. That must be fixed, or we'll crash...
       NS_ASSERTION(list_qi == static_cast<nsIDOMFileList*>(aSupports),
                    "Uh, fix QI!");
     }
 #endif
 
-    return static_cast<FileList*>(aSupports);
+    return static_cast<nsDOMFileList*>(aSupports);
   }
 
-  File* Item(uint32_t aIndex)
+  nsIDOMFile* Item(uint32_t aIndex)
   {
-    return mFiles.SafeElementAt(aIndex);
+    return mFiles.SafeObjectAt(aIndex);
   }
-  File* IndexedGetter(uint32_t aIndex, bool& aFound)
+  nsIDOMFile* IndexedGetter(uint32_t aIndex, bool& aFound)
   {
-    aFound = aIndex < mFiles.Length();
-    return aFound ? mFiles.ElementAt(aIndex) : nullptr;
+    aFound = aIndex < static_cast<uint32_t>(mFiles.Count());
+    return aFound ? mFiles.ObjectAt(aIndex) : nullptr;
   }
   uint32_t Length()
   {
-    return mFiles.Length();
+    return mFiles.Count();
   }
 
 private:
-  nsTArray<nsRefPtr<File>> mFiles;
+  nsCOMArray<nsIDOMFile> mFiles;
   nsISupports *mParent;
 };
 
-} // dom namespace
-} // file namespace
-
-#endif // mozilla_dom_File_h
+#endif
--- a/content/base/src/FileIOObject.cpp
+++ b/content/base/src/FileIOObject.cpp
@@ -1,20 +1,20 @@
 /* -*- Mode: C++; 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 "FileIOObject.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/ProgressEvent.h"
 #include "mozilla/EventDispatcher.h"
-#include "nsComponentManagerUtils.h"
+#include "nsDOMFile.h"
 #include "nsError.h"
 #include "nsIDOMEvent.h"
+#include "mozilla/dom/ProgressEvent.h"
+#include "nsComponentManagerUtils.h"
 
 #define ERROR_STR "error"
 #define ABORT_STR "abort"
 #define PROGRESS_STR "progress"
 
 namespace mozilla {
 namespace dom {
 
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -6,17 +6,16 @@
 
 #include "WebSocket.h"
 #include "mozilla/dom/WebSocketBinding.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/OldDebugAPI.h"
 #include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDOMWindow.h"
 #include "nsIDocument.h"
 #include "nsXPCOM.h"
 #include "nsIXPConnect.h"
 #include "nsContentUtils.h"
 #include "nsError.h"
@@ -34,16 +33,17 @@
 #include "nsICryptoHash.h"
 #include "nsJSUtils.h"
 #include "nsIScriptError.h"
 #include "nsNetUtil.h"
 #include "nsILoadGroup.h"
 #include "mozilla/Preferences.h"
 #include "xpcpublic.h"
 #include "nsContentPolicyUtils.h"
+#include "nsDOMFile.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIObserverService.h"
 #include "nsIWebSocketChannel.h"
 
 namespace mozilla {
 namespace dom {
 
 #define UTF_8_REPLACEMENT_CHAR    static_cast<char16_t>(0xFFFD)
@@ -893,17 +893,17 @@ WebSocket::CreateAndDispatchMessageEvent
     return NS_ERROR_FAILURE;
   }
   JSContext* cx = jsapi.cx();
 
   // Create appropriate JS object for message
   JS::Rooted<JS::Value> jsData(cx);
   if (isBinary) {
     if (mBinaryType == dom::BinaryType::Blob) {
-      rv = nsContentUtils::CreateBlobBuffer(cx, GetOwner(), aData, &jsData);
+      rv = nsContentUtils::CreateBlobBuffer(cx, aData, &jsData);
       NS_ENSURE_SUCCESS(rv, rv);
     } else if (mBinaryType == dom::BinaryType::Arraybuffer) {
       JS::Rooted<JSObject*> arrayBuf(cx);
       rv = nsContentUtils::CreateArrayBuffer(cx, aData, arrayBuf.address());
       NS_ENSURE_SUCCESS(rv, rv);
       jsData = OBJECT_TO_JSVAL(arrayBuf);
     } else {
       NS_RUNTIMEABORT("Unknown binary type!");
@@ -1189,29 +1189,30 @@ WebSocket::Send(const nsAString& aData,
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   NS_ConvertUTF16toUTF8 msgString(aData);
   Send(nullptr, msgString, msgString.Length(), false, aRv);
 }
 
 void
-WebSocket::Send(File& aData, ErrorResult& aRv)
+WebSocket::Send(nsIDOMBlob* aData,
+                ErrorResult& aRv)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   nsCOMPtr<nsIInputStream> msgStream;
-  nsresult rv = aData.GetInternalStream(getter_AddRefs(msgStream));
+  nsresult rv = aData->GetInternalStream(getter_AddRefs(msgStream));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   uint64_t msgLength;
-  rv = aData.GetSize(&msgLength);
+  rv = aData->GetSize(&msgLength);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   if (msgLength > UINT32_MAX) {
     aRv.Throw(NS_ERROR_FILE_TOO_BIG);
     return;
--- a/content/base/src/WebSocket.h
+++ b/content/base/src/WebSocket.h
@@ -27,18 +27,16 @@
 #include "nsWrapperCache.h"
 
 #define DEFAULT_WS_SCHEME_PORT  80
 #define DEFAULT_WSS_SCHEME_PORT 443
 
 namespace mozilla {
 namespace dom {
 
-class File;
-
 class WebSocket MOZ_FINAL : public DOMEventTargetHelper,
                             public nsIInterfaceRequestor,
                             public nsIWebSocketListener,
                             public nsIObserver,
                             public nsSupportsWeakReference,
                             public nsIRequest
 {
 friend class CallDispatchConnectionCloseEvents;
@@ -128,17 +126,17 @@ public: // WebIDL interface:
 
   // webIDL: attribute DOMString binaryType;
   dom::BinaryType BinaryType() const { return mBinaryType; }
   void SetBinaryType(dom::BinaryType aData) { mBinaryType = aData; }
 
   // webIDL: void send(DOMString|Blob|ArrayBufferView data);
   void Send(const nsAString& aData,
             ErrorResult& aRv);
-  void Send(File& aData,
+  void Send(nsIDOMBlob* aData,
             ErrorResult& aRv);
   void Send(const ArrayBuffer& aData,
             ErrorResult& aRv);
   void Send(const ArrayBufferView& aData,
             ErrorResult& aRv);
 
 private: // constructor && distructor
   explicit WebSocket(nsPIDOMWindow* aOwnerWindow);
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -94,22 +94,20 @@ UNIFIED_SOURCES += [
     'DOMMatrix.cpp',
     'DOMParser.cpp',
     'DOMPoint.cpp',
     'DOMQuad.cpp',
     'DOMRect.cpp',
     'DOMStringList.cpp',
     'Element.cpp',
     'EventSource.cpp',
-    'File.cpp',
     'FileIOObject.cpp',
     'FragmentOrElement.cpp',
     'ImportManager.cpp',
     'Link.cpp',
-    'MultipartFileImpl.cpp',
     'NodeIterator.cpp',
     'nsAtomListUtils.cpp',
     'nsAttrAndChildArray.cpp',
     'nsAttrValue.cpp',
     'nsAttrValueOrString.cpp',
     'nsCCUncollectableMarker.cpp',
     'nsChannelPolicy.cpp',
     'nsContentAreaDragDrop.cpp',
@@ -121,17 +119,19 @@ UNIFIED_SOURCES += [
     'nsCrossSiteListenerProxy.cpp',
     'nsCSPContext.cpp',
     'nsCSPParser.cpp',
     'nsCSPService.cpp',
     'nsCSPUtils.cpp',
     'nsDataDocumentContentPolicy.cpp',
     'nsDocumentEncoder.cpp',
     'nsDOMAttributeMap.cpp',
+    'nsDOMBlobBuilder.cpp',
     'nsDOMCaretPosition.cpp',
+    'nsDOMFile.cpp',
     'nsDOMFileReader.cpp',
     'nsDOMMutationObserver.cpp',
     'nsDOMSerializer.cpp',
     'nsDOMSettableTokenList.cpp',
     'nsDOMTokenList.cpp',
     'nsElementFrameLoaderOwner.cpp',
     'nsFormData.cpp',
     'nsFrameLoader.cpp',
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -85,17 +85,16 @@
 #include "nsGkAtoms.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsHtml5Module.h"
 #include "nsHtml5StringParser.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsICategoryManager.h"
 #include "nsIChannelEventSink.h"
 #include "nsIChannelPolicy.h"
-#include "nsICharsetDetectionObserver.h"
 #include "nsIChromeRegistry.h"
 #include "nsIConsoleService.h"
 #include "nsIContent.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIContentSink.h"
 #include "nsIContentViewer.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
@@ -5988,36 +5987,30 @@ nsContentUtils::CreateArrayBuffer(JSCont
 
   return NS_OK;
 }
 
 // Initial implementation: only stores to RAM, not file
 // TODO: bug 704447: large file support
 nsresult
 nsContentUtils::CreateBlobBuffer(JSContext* aCx,
-                                 nsISupports* aParent,
                                  const nsACString& aData,
                                  JS::MutableHandle<JS::Value> aBlob)
 {
   uint32_t blobLen = aData.Length();
   void* blobData = moz_malloc(blobLen);
-  nsRefPtr<File> blob;
+  nsCOMPtr<nsIDOMBlob> blob;
   if (blobData) {
     memcpy(blobData, aData.BeginReading(), blobLen);
-    blob = mozilla::dom::File::CreateMemoryFile(aParent, blobData, blobLen,
-                                                EmptyString());
+    blob = mozilla::dom::DOMFile::CreateMemoryFile(blobData, blobLen,
+                                                   EmptyString());
   } else {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-
-  if (!WrapNewBindingObject(aCx, blob, aBlob)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
+  return nsContentUtils::WrapNative(aCx, blob, aBlob);
 }
 
 void
 nsContentUtils::StripNullChars(const nsAString& aInStr, nsAString& aOutStr)
 {
   // In common cases where we don't have nulls in the
   // string we can simple simply bypass the checking code.
   int32_t firstNullPos = aInStr.FindChar('\0');
rename from content/base/src/MultipartFileImpl.cpp
rename to content/base/src/nsDOMBlobBuilder.cpp
--- a/content/base/src/MultipartFileImpl.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -1,353 +1,520 @@
 /* -*- Mode: C++; 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 "MultipartFileImpl.h"
+#include "nsDOMBlobBuilder.h"
 #include "jsfriendapi.h"
-#include "mozilla/dom/BlobSet.h"
+#include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/FileBinding.h"
 #include "nsAutoPtr.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIMultiplexInputStream.h"
 #include "nsStringStream.h"
 #include "nsTArray.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsIScriptError.h"
 #include "nsIXPConnect.h"
 #include <algorithm>
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-NS_IMPL_ISUPPORTS_INHERITED0(MultipartFileImpl, FileImpl)
+NS_IMPL_ISUPPORTS_INHERITED0(DOMMultipartFileImpl, DOMFileImpl)
 
 nsresult
-MultipartFileImpl::GetInternalStream(nsIInputStream** aStream)
+DOMMultipartFileImpl::GetSize(uint64_t* aLength)
+{
+  *aLength = mLength;
+  return NS_OK;
+}
+
+nsresult
+DOMMultipartFileImpl::GetInternalStream(nsIInputStream** aStream)
 {
   nsresult rv;
   *aStream = nullptr;
 
   nsCOMPtr<nsIMultiplexInputStream> stream =
     do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
   NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE);
 
   uint32_t i;
   for (i = 0; i < mBlobImpls.Length(); i++) {
     nsCOMPtr<nsIInputStream> scratchStream;
-    FileImpl* blobImpl = mBlobImpls.ElementAt(i).get();
+    DOMFileImpl* blobImpl = mBlobImpls.ElementAt(i).get();
 
     rv = blobImpl->GetInternalStream(getter_AddRefs(scratchStream));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = stream->AppendStream(scratchStream);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return CallQueryInterface(stream, aStream);
 }
 
-already_AddRefed<FileImpl>
-MultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
-                               const nsAString& aContentType,
-                               ErrorResult& aRv)
+already_AddRefed<DOMFileImpl>
+DOMMultipartFileImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
+                                  const nsAString& aContentType)
 {
   // If we clamped to nothing we create an empty blob
-  nsTArray<nsRefPtr<FileImpl>> blobImpls;
+  nsTArray<nsRefPtr<DOMFileImpl>> blobImpls;
 
   uint64_t length = aLength;
   uint64_t skipStart = aStart;
 
   // Prune the list of blobs if we can
   uint32_t i;
   for (i = 0; length && skipStart && i < mBlobImpls.Length(); i++) {
-    FileImpl* blobImpl = mBlobImpls[i].get();
+    DOMFileImpl* blobImpl = mBlobImpls[i].get();
 
-    uint64_t l = blobImpl->GetSize(aRv);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return nullptr;
-    }
+    uint64_t l;
+    nsresult rv = blobImpl->GetSize(&l);
+    NS_ENSURE_SUCCESS(rv, nullptr);
 
     if (skipStart < l) {
       uint64_t upperBound = std::min<uint64_t>(l - skipStart, length);
 
-      nsRefPtr<FileImpl> firstBlobImpl =
-        blobImpl->CreateSlice(skipStart, upperBound,
-                              aContentType, aRv);
-      if (NS_WARN_IF(aRv.Failed())) {
-        return nullptr;
+      nsRefPtr<DOMFileImpl> firstImpl;
+      rv = blobImpl->Slice(skipStart, skipStart + upperBound, aContentType, 3,
+                           getter_AddRefs(firstImpl));
+      NS_ENSURE_SUCCESS(rv, nullptr);
+
+      // Avoid wrapping a single blob inside an DOMMultipartFileImpl
+      if (length == upperBound) {
+        return firstImpl.forget();
       }
 
-      // Avoid wrapping a single blob inside an MultipartFileImpl
-      if (length == upperBound) {
-        return firstBlobImpl.forget();
-      }
-
-      blobImpls.AppendElement(firstBlobImpl);
+      blobImpls.AppendElement(firstImpl);
       length -= upperBound;
       i++;
       break;
     }
     skipStart -= l;
   }
 
   // Now append enough blobs until we're done
   for (; length && i < mBlobImpls.Length(); i++) {
-    FileImpl* blobImpl = mBlobImpls[i].get();
+    DOMFileImpl* blobImpl = mBlobImpls[i].get();
 
-    uint64_t l = blobImpl->GetSize(aRv);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return nullptr;
-    }
+    uint64_t l;
+    nsresult rv = blobImpl->GetSize(&l);
+    NS_ENSURE_SUCCESS(rv, nullptr);
 
     if (length < l) {
-      nsRefPtr<FileImpl> lastBlobImpl =
-        blobImpl->CreateSlice(0, length, aContentType, aRv);
-      if (NS_WARN_IF(aRv.Failed())) {
-        return nullptr;
-      }
+      nsRefPtr<DOMFileImpl> lastBlob;
+      rv = blobImpl->Slice(0, length, aContentType, 3,
+                           getter_AddRefs(lastBlob));
+      NS_ENSURE_SUCCESS(rv, nullptr);
 
-      blobImpls.AppendElement(lastBlobImpl);
+      blobImpls.AppendElement(lastBlob);
     } else {
       blobImpls.AppendElement(blobImpl);
     }
     length -= std::min<uint64_t>(l, length);
   }
 
   // we can create our blob now
-  nsRefPtr<FileImpl> impl =
-    new MultipartFileImpl(blobImpls, aContentType);
+  nsRefPtr<DOMFileImpl> impl =
+    new DOMMultipartFileImpl(blobImpls, aContentType);
   return impl.forget();
 }
 
-void
-MultipartFileImpl::InitializeBlob()
+/* static */ nsresult
+DOMMultipartFileImpl::NewFile(const nsAString& aName, nsISupports** aNewObject)
+{
+  nsCOMPtr<nsISupports> file =
+    do_QueryObject(new DOMFile(new DOMMultipartFileImpl(aName)));
+  file.forget(aNewObject);
+  return NS_OK;
+}
+
+/* static */ nsresult
+DOMMultipartFileImpl::NewBlob(nsISupports** aNewObject)
+{
+  nsCOMPtr<nsISupports> file =
+    do_QueryObject(new DOMFile(new DOMMultipartFileImpl()));
+  file.forget(aNewObject);
+  return NS_OK;
+}
+
+static nsIDOMBlob*
+GetXPConnectNative(JSContext* aCx, JSObject* aObj) {
+  nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
+    nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, aObj));
+  return blob;
+}
+
+nsresult
+DOMMultipartFileImpl::Initialize(nsISupports* aOwner,
+                                 JSContext* aCx,
+                                 JSObject* aObj,
+                                 const JS::CallArgs& aArgs)
+{
+  if (!mIsFile) {
+    return InitBlob(aCx, aArgs.length(), aArgs.array(), GetXPConnectNative);
+  }
+
+  if (!nsContentUtils::IsCallerChrome()) {
+    return InitFile(aCx, aArgs.length(), aArgs.array());
+  }
+
+  if (aArgs.length() > 0) {
+    JS::Value* argv = aArgs.array();
+    if (argv[0].isObject()) {
+      JS::Rooted<JSObject*> obj(aCx, &argv[0].toObject());
+      if (JS_IsArrayObject(aCx, obj)) {
+        return InitFile(aCx, aArgs.length(), aArgs.array());
+      }
+    }
+  }
+
+  return InitChromeFile(aCx, aArgs.length(), aArgs.array());
+}
+
+nsresult
+DOMMultipartFileImpl::InitBlob(JSContext* aCx,
+                               uint32_t aArgc,
+                               JS::Value* aArgv,
+                               UnwrapFuncPtr aUnwrapFunc)
 {
+  bool nativeEOL = false;
+  if (aArgc > 1) {
+    BlobPropertyBag d;
+    if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1]))) {
+      return NS_ERROR_TYPE_ERR;
+    }
+    mContentType = d.mType;
+    nativeEOL = d.mEndings == EndingTypes::Native;
+  }
+
+  if (aArgc > 0) {
+    return ParseBlobArrayArgument(aCx, aArgv[0], nativeEOL, aUnwrapFunc);
+  }
+
   SetLengthAndModifiedDate();
+
+  return NS_OK;
+}
+
+nsresult
+DOMMultipartFileImpl::ParseBlobArrayArgument(JSContext* aCx, JS::Value& aValue,
+                                             bool aNativeEOL,
+                                             UnwrapFuncPtr aUnwrapFunc)
+{
+  if (!aValue.isObject()) {
+    return NS_ERROR_TYPE_ERR; // We're not interested
+  }
+
+  JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
+  if (!JS_IsArrayObject(aCx, obj)) {
+    return NS_ERROR_TYPE_ERR; // We're not interested
+  }
+
+  BlobSet blobSet;
+
+  uint32_t length;
+  MOZ_ALWAYS_TRUE(JS_GetArrayLength(aCx, obj, &length));
+  for (uint32_t i = 0; i < length; ++i) {
+    JS::Rooted<JS::Value> element(aCx);
+    if (!JS_GetElement(aCx, obj, i, &element))
+      return NS_ERROR_TYPE_ERR;
+
+    if (element.isObject()) {
+      JS::Rooted<JSObject*> obj(aCx, &element.toObject());
+      nsCOMPtr<nsIDOMBlob> blob = aUnwrapFunc(aCx, obj);
+      if (blob) {
+        nsRefPtr<DOMFileImpl> blobImpl =
+          static_cast<DOMFile*>(blob.get())->Impl();
+
+        // Flatten so that multipart blobs will never nest
+        const nsTArray<nsRefPtr<DOMFileImpl>>* subBlobImpls =
+          blobImpl->GetSubBlobImpls();
+        if (subBlobImpls) {
+          blobSet.AppendBlobImpls(*subBlobImpls);
+        } else {
+          blobSet.AppendBlobImpl(blobImpl);
+        }
+        continue;
+      }
+      if (JS_IsArrayBufferViewObject(obj)) {
+        nsresult rv = blobSet.AppendVoidPtr(
+                                          JS_GetArrayBufferViewData(obj),
+                                          JS_GetArrayBufferViewByteLength(obj));
+        NS_ENSURE_SUCCESS(rv, rv);
+        continue;
+      }
+      if (JS_IsArrayBufferObject(obj)) {
+        nsresult rv = blobSet.AppendArrayBuffer(obj);
+        NS_ENSURE_SUCCESS(rv, rv);
+        continue;
+      }
+    }
+
+    // coerce it to a string
+    JSString* str = JS::ToString(aCx, element);
+    NS_ENSURE_TRUE(str, NS_ERROR_TYPE_ERR);
+
+    nsresult rv = blobSet.AppendString(str, aNativeEOL, aCx);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  mBlobImpls = blobSet.GetBlobImpls();
+
+  SetLengthAndModifiedDate();
+
+  return NS_OK;
 }
 
 void
-MultipartFileImpl::InitializeBlob(
-       JSContext* aCx,
-       const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
-       const nsAString& aContentType,
-       bool aNativeEOL,
-       ErrorResult& aRv)
-{
-  mContentType = aContentType;
-  BlobSet blobSet;
-
-  for (uint32_t i = 0, len = aData.Length(); i < len; ++i) {
-    const OwningArrayBufferOrArrayBufferViewOrBlobOrString& data = aData[i];
-
-    if (data.IsBlob()) {
-      nsRefPtr<File> file = data.GetAsBlob().get();
-      blobSet.AppendBlobImpl(file->Impl());
-    }
-
-    else if (data.IsString()) {
-      aRv = blobSet.AppendString(data.GetAsString(), aNativeEOL, aCx);
-      if (aRv.Failed()) {
-        return;
-      }
-    }
-
-    else if (data.IsArrayBuffer()) {
-      const ArrayBuffer& buffer = data.GetAsArrayBuffer();
-      buffer.ComputeLengthAndData();
-      aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length());
-      if (aRv.Failed()) {
-        return;
-      }
-    }
-
-    else if (data.IsArrayBufferView()) {
-      const ArrayBufferView& buffer = data.GetAsArrayBufferView();
-      buffer.ComputeLengthAndData();
-      aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length());
-      if (aRv.Failed()) {
-        return;
-      }
-    }
-
-    else {
-      MOZ_CRASH("Impossible blob data type.");
-    }
-  }
-
-
-  mBlobImpls = blobSet.GetBlobImpls();
-  SetLengthAndModifiedDate();
-}
-
-void
-MultipartFileImpl::SetLengthAndModifiedDate()
+DOMMultipartFileImpl::SetLengthAndModifiedDate()
 {
   MOZ_ASSERT(mLength == UINT64_MAX);
   MOZ_ASSERT(mLastModificationDate == UINT64_MAX);
 
   uint64_t totalLength = 0;
 
   for (uint32_t index = 0, count = mBlobImpls.Length(); index < count; index++) {
-    nsRefPtr<FileImpl>& blob = mBlobImpls[index];
+    nsRefPtr<DOMFileImpl>& blob = mBlobImpls[index];
 
 #ifdef DEBUG
     MOZ_ASSERT(!blob->IsSizeUnknown());
     MOZ_ASSERT(!blob->IsDateUnknown());
 #endif
 
-    ErrorResult error;
-    uint64_t subBlobLength = blob->GetSize(error);
-    MOZ_ALWAYS_TRUE(!error.Failed());
+    uint64_t subBlobLength;
+    MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blob->GetSize(&subBlobLength)));
 
     MOZ_ASSERT(UINT64_MAX - subBlobLength >= totalLength);
     totalLength += subBlobLength;
   }
 
   mLength = totalLength;
 
   if (mIsFile) {
-    // We cannot use PR_Now() because bug 493756 and, for this reason:
-    //   var x = new Date(); var f = new File(...);
-    //   x.getTime() < f.dateModified.getTime()
-    // could fail.
-    mLastModificationDate = JS_Now();
+    mLastModificationDate = PR_Now();
   }
 }
 
-void
-MultipartFileImpl::GetMozFullPathInternal(nsAString& aFilename,
-                                          ErrorResult& aRv)
+nsresult
+DOMMultipartFileImpl::GetMozFullPathInternal(nsAString& aFilename)
 {
-  if (!mIsFromNsIFile || mBlobImpls.Length() == 0) {
-    FileImplBase::GetMozFullPathInternal(aFilename, aRv);
-    return;
+  if (!mIsFromNsiFile || mBlobImpls.Length() == 0) {
+    return DOMFileImplBase::GetMozFullPathInternal(aFilename);
   }
 
-  FileImpl* blobImpl = mBlobImpls.ElementAt(0).get();
+  DOMFileImpl* blobImpl = mBlobImpls.ElementAt(0).get();
   if (!blobImpl) {
-    FileImplBase::GetMozFullPathInternal(aFilename, aRv);
-    return;
+    return DOMFileImplBase::GetMozFullPathInternal(aFilename);
   }
 
-  blobImpl->GetMozFullPathInternal(aFilename, aRv);
+  return blobImpl->GetMozFullPathInternal(aFilename);
 }
 
-void
-MultipartFileImpl::InitializeChromeFile(File& aBlob,
-                                        const ChromeFilePropertyBag& aBag,
-                                        ErrorResult& aRv)
+nsresult
+DOMMultipartFileImpl::InitChromeFile(JSContext* aCx,
+                                     uint32_t aArgc,
+                                     JS::Value* aArgv)
 {
-  NS_ASSERTION(!mImmutable, "Something went wrong ...");
+  nsresult rv;
 
-  if (mImmutable) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
+  NS_ASSERTION(!mImmutable, "Something went wrong ...");
+  NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED);
   MOZ_ASSERT(nsContentUtils::IsCallerChrome());
+  NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
 
-  mName = aBag.mName;
-  mContentType = aBag.mType;
-  mIsFromNsIFile = true;
-
-  // XXXkhuey this is terrible
-  if (mContentType.IsEmpty()) {
-    aBlob.GetType(mContentType);
+  if (aArgc > 1) {
+    FilePropertyBag d;
+    if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1]))) {
+      return NS_ERROR_TYPE_ERR;
+    }
+    mName = d.mName;
+    mContentType = d.mType;
   }
 
 
-  BlobSet blobSet;
-  blobSet.AppendBlobImpl(aBlob.Impl());
-  mBlobImpls = blobSet.GetBlobImpls();
+  // We expect to get a path to represent as a File object or
+  // Blob object, an nsIFile, or an nsIDOMFile.
+  nsCOMPtr<nsIFile> file;
+  nsCOMPtr<nsIDOMBlob> blob;
+  if (!aArgv[0].isString()) {
+    // Lets see if it's an nsIFile
+    if (!aArgv[0].isObject()) {
+      return NS_ERROR_UNEXPECTED; // We're not interested
+    }
 
-  SetLengthAndModifiedDate();
-}
+    JSObject* obj = &aArgv[0].toObject();
+
+    nsISupports* supports =
+      nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
+    if (!supports) {
+      return NS_ERROR_UNEXPECTED;
+    }
 
-void
-MultipartFileImpl::InitializeChromeFile(nsPIDOMWindow* aWindow,
-                                        nsIFile* aFile,
-                                        const ChromeFilePropertyBag& aBag,
-                                        bool aIsFromNsIFile,
-                                        ErrorResult& aRv)
-{
-  NS_ASSERTION(!mImmutable, "Something went wrong ...");
-  if (mImmutable) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
+    blob = do_QueryInterface(supports);
+    file = do_QueryInterface(supports);
+    if (!blob && !file) {
+      return NS_ERROR_UNEXPECTED;
+    }
 
-  MOZ_ASSERT(nsContentUtils::IsCallerChrome());
+    mIsFromNsiFile = true;
+  } else {
+    // It's a string
+    JSString* str = JS::ToString(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[0]));
+    NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
 
-  mName = aBag.mName;
-  mContentType = aBag.mType;
-  mIsFromNsIFile = aIsFromNsIFile;
+    nsAutoJSString xpcomStr;
+    if (!xpcomStr.init(aCx, str)) {
+      return NS_ERROR_XPC_BAD_CONVERT_JS;
+    }
 
-  bool exists;
-  aRv = aFile->Exists(&exists);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
+    rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(file));
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  if (!exists) {
-    aRv.Throw(NS_ERROR_FILE_NOT_FOUND);
-    return;
-  }
+  if (file) {
+    bool exists;
+    rv = file->Exists(&exists);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
 
-  bool isDir;
-  aRv = aFile->IsDirectory(&isDir);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  if (isDir) {
-    aRv.Throw(NS_ERROR_FILE_IS_DIRECTORY);
-    return;
-  }
+    bool isDir;
+    rv = file->IsDirectory(&isDir);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_FALSE(isDir, NS_ERROR_FILE_IS_DIRECTORY);
 
-  if (mName.IsEmpty()) {
-    aFile->GetLeafName(mName);
-  }
+    if (mName.IsEmpty()) {
+      file->GetLeafName(mName);
+    }
 
-  nsRefPtr<File> blob = File::CreateFromFile(aWindow, aFile);
+    nsRefPtr<DOMFile> domFile = DOMFile::CreateFromFile(file);
 
-  // Pre-cache size.
-  uint64_t unused;
-  aRv = blob->GetSize(&unused);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
+    // Pre-cache size.
+    uint64_t unused;
+    rv = domFile->GetSize(&unused);
+    NS_ENSURE_SUCCESS(rv, rv);
 
-  // Pre-cache modified date.
-  aRv = blob->GetMozLastModifiedDate(&unused);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
+    // Pre-cache modified date.
+    rv = domFile->GetMozLastModifiedDate(&unused);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    blob = domFile.forget();
   }
 
   // XXXkhuey this is terrible
   if (mContentType.IsEmpty()) {
     blob->GetType(mContentType);
   }
 
   BlobSet blobSet;
-  blobSet.AppendBlobImpl(static_cast<File*>(blob.get())->Impl());
+  blobSet.AppendBlobImpl(static_cast<DOMFile*>(blob.get())->Impl());
   mBlobImpls = blobSet.GetBlobImpls();
 
   SetLengthAndModifiedDate();
+
+  return NS_OK;
+}
+
+nsresult
+DOMMultipartFileImpl::InitFile(JSContext* aCx,
+                               uint32_t aArgc,
+                               JS::Value* aArgv)
+{
+  NS_ASSERTION(!mImmutable, "Something went wrong ...");
+  NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED);
+
+  if (aArgc < 2) {
+    return NS_ERROR_TYPE_ERR;
+  }
+
+  // File name
+  JSString* str = JS::ToString(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[1]));
+  NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
+
+  nsAutoJSString xpcomStr;
+  if (!xpcomStr.init(aCx, str)) {
+    return NS_ERROR_XPC_BAD_CONVERT_JS;
+  }
+
+  mName = xpcomStr;
+
+  // Optional params
+  bool nativeEOL = false;
+  if (aArgc > 2) {
+    BlobPropertyBag d;
+    if (!d.Init(aCx, JS::Handle<JS::Value>::fromMarkedLocation(&aArgv[2]))) {
+      return NS_ERROR_TYPE_ERR;
+    }
+    mContentType = d.mType;
+    nativeEOL = d.mEndings == EndingTypes::Native;
+  }
+
+  return ParseBlobArrayArgument(aCx, aArgv[0], nativeEOL, GetXPConnectNative);
 }
 
-void
-MultipartFileImpl::InitializeChromeFile(nsPIDOMWindow* aWindow,
-                                        const nsAString& aData,
-                                        const ChromeFilePropertyBag& aBag,
-                                        ErrorResult& aRv)
+nsresult
+BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
 {
-  nsCOMPtr<nsIFile> file;
-  aRv = NS_NewLocalFile(aData, false, getter_AddRefs(file));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
+  NS_ENSURE_ARG_POINTER(aData);
+
+  uint64_t offset = mDataLen;
+
+  if (!ExpandBufferSize(aLength))
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  memcpy((char*)mData + offset, aData, aLength);
+  return NS_OK;
+}
+
+nsresult
+BlobSet::AppendString(JSString* aString, bool nativeEOL, JSContext* aCx)
+{
+  nsAutoJSString xpcomStr;
+  if (!xpcomStr.init(aCx, aString)) {
+    return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
 
-  InitializeChromeFile(aWindow, file, aBag, false, aRv);
+  nsCString utf8Str = NS_ConvertUTF16toUTF8(xpcomStr);
+
+  if (nativeEOL) {
+    if (utf8Str.FindChar('\r') != kNotFound) {
+      utf8Str.ReplaceSubstring("\r\n", "\n");
+      utf8Str.ReplaceSubstring("\r", "\n");
+    }
+#ifdef XP_WIN
+    utf8Str.ReplaceSubstring("\n", "\r\n");
+#endif
+  }
+
+  return AppendVoidPtr((void*)utf8Str.Data(),
+                       utf8Str.Length());
 }
+
+nsresult
+BlobSet::AppendBlobImpl(DOMFileImpl* aBlobImpl)
+{
+  NS_ENSURE_ARG_POINTER(aBlobImpl);
+
+  Flush();
+  mBlobImpls.AppendElement(aBlobImpl);
+
+  return NS_OK;
+}
+
+nsresult
+BlobSet::AppendBlobImpls(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls)
+{
+  Flush();
+  mBlobImpls.AppendElements(aBlobImpls);
+
+  return NS_OK;
+}
+
+nsresult
+BlobSet::AppendArrayBuffer(JSObject* aBuffer)
+{
+  return AppendVoidPtr(JS_GetArrayBufferData(aBuffer),
+                       JS_GetArrayBufferByteLength(aBuffer));
+}
rename from content/base/src/MultipartFileImpl.h
rename to content/base/src/nsDOMBlobBuilder.h
--- a/content/base/src/MultipartFileImpl.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -1,123 +1,198 @@
 /* -*- Mode: C++; 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/. */
 
-#ifndef mozilla_dom_MultipartFileImpl_h
-#define mozilla_dom_MultipartFileImpl_h
+#ifndef nsDOMBlobBuilder_h
+#define nsDOMBlobBuilder_h
 
-#include "mozilla/Attributes.h"
+#include "nsDOMFile.h"
+
 #include "mozilla/CheckedInt.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/BlobBinding.h"
-#include "mozilla/dom/FileBinding.h"
+#include "mozilla/Attributes.h"
 #include <algorithm>
 
-using namespace mozilla;
+#define NS_DOMMULTIPARTBLOB_CID { 0x47bf0b43, 0xf37e, 0x49ef, \
+  { 0x81, 0xa0, 0x18, 0xba, 0xc0, 0x57, 0xb5, 0xcc } }
+#define NS_DOMMULTIPARTBLOB_CONTRACTID "@mozilla.org/dom/multipart-blob;1"
+
+#define NS_DOMMULTIPARTFILE_CID { 0xc3361f77, 0x60d1, 0x4ea9, \
+  { 0x94, 0x96, 0xdf, 0x5d, 0x6f, 0xcd, 0xd7, 0x8f } }
+#define NS_DOMMULTIPARTFILE_CONTRACTID "@mozilla.org/dom/multipart-file;1"
+
 using namespace mozilla::dom;
 
-class MultipartFileImpl MOZ_FINAL : public FileImplBase
+class DOMMultipartFileImpl MOZ_FINAL : public DOMFileImplBase
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // Create as a file
-  MultipartFileImpl(const nsTArray<nsRefPtr<FileImpl>>& aBlobImpls,
-                    const nsAString& aName,
-                    const nsAString& aContentType)
-    : FileImplBase(aName, aContentType, UINT64_MAX),
+  DOMMultipartFileImpl(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls,
+                       const nsAString& aName,
+                       const nsAString& aContentType)
+    : DOMFileImplBase(aName, aContentType, UINT64_MAX),
       mBlobImpls(aBlobImpls),
-      mIsFromNsIFile(false)
+      mIsFromNsiFile(false)
   {
     SetLengthAndModifiedDate();
   }
 
   // Create as a blob
-  MultipartFileImpl(const nsTArray<nsRefPtr<FileImpl>>& aBlobImpls,
-                    const nsAString& aContentType)
-    : FileImplBase(aContentType, UINT64_MAX),
+  DOMMultipartFileImpl(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls,
+                       const nsAString& aContentType)
+    : DOMFileImplBase(aContentType, UINT64_MAX),
       mBlobImpls(aBlobImpls),
-      mIsFromNsIFile(false)
+      mIsFromNsiFile(false)
   {
     SetLengthAndModifiedDate();
   }
 
   // Create as a file to be later initialized
-  explicit MultipartFileImpl(const nsAString& aName)
-    : FileImplBase(aName, EmptyString(), UINT64_MAX),
-      mIsFromNsIFile(false)
+  explicit DOMMultipartFileImpl(const nsAString& aName)
+    : DOMFileImplBase(aName, EmptyString(), UINT64_MAX),
+      mIsFromNsiFile(false)
   {
   }
 
   // Create as a blob to be later initialized
-  MultipartFileImpl()
-    : FileImplBase(EmptyString(), UINT64_MAX),
-      mIsFromNsIFile(false)
+  DOMMultipartFileImpl()
+    : DOMFileImplBase(EmptyString(), UINT64_MAX),
+      mIsFromNsiFile(false)
   {
   }
 
-  void InitializeBlob();
-
-  void InitializeBlob(
-       JSContext* aCx,
-       const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
-       const nsAString& aContentType,
-       bool aNativeEOL,
-       ErrorResult& aRv);
-
-  void InitializeChromeFile(File& aData,
-                            const ChromeFilePropertyBag& aBag,
-                            ErrorResult& aRv);
+  virtual nsresult
+  Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
+             const JS::CallArgs& aArgs) MOZ_OVERRIDE;
 
-  void InitializeChromeFile(nsPIDOMWindow* aWindow,
-                            const nsAString& aData,
-                            const ChromeFilePropertyBag& aBag,
-                            ErrorResult& aRv);
+  typedef nsIDOMBlob* (*UnwrapFuncPtr)(JSContext*, JSObject*);
+  nsresult InitBlob(JSContext* aCx,
+                    uint32_t aArgc,
+                    JS::Value* aArgv,
+                    UnwrapFuncPtr aUnwrapFunc);
+  nsresult InitFile(JSContext* aCx,
+                    uint32_t aArgc,
+                    JS::Value* aArgv);
+  nsresult InitChromeFile(JSContext* aCx,
+                          uint32_t aArgc,
+                          JS::Value* aArgv);
 
-  void InitializeChromeFile(nsPIDOMWindow* aWindow,
-                            nsIFile* aData,
-                            const ChromeFilePropertyBag& aBag,
-                            bool aIsFromNsIFile,
-                            ErrorResult& aRv);
-
-  virtual already_AddRefed<FileImpl>
+  virtual already_AddRefed<DOMFileImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType,
-              ErrorResult& aRv) MOZ_OVERRIDE;
+              const nsAString& aContentType) MOZ_OVERRIDE;
 
-  virtual uint64_t GetSize(ErrorResult& aRv) MOZ_OVERRIDE
-  {
-    return mLength;
-  }
+  virtual nsresult GetSize(uint64_t* aSize) MOZ_OVERRIDE;
 
   virtual nsresult GetInternalStream(nsIInputStream** aInputStream) MOZ_OVERRIDE;
 
-  virtual const nsTArray<nsRefPtr<FileImpl>>* GetSubBlobImpls() const MOZ_OVERRIDE
+  static nsresult NewFile(const nsAString& aName, nsISupports** aNewObject);
+
+  // DOMClassInfo constructor (for Blob([b1, "foo"], { type: "image/png" }))
+  static nsresult NewBlob(nsISupports* *aNewObject);
+
+  // DOMClassInfo constructor (for File([b1, "foo"], { type: "image/png",
+  //                                                   name: "foo.png" }))
+  inline static nsresult NewFile(nsISupports** aNewObject)
+  {
+    // Initialization will set the filename, so we can pass in an empty string
+    // for now.
+    return NewFile(EmptyString(), aNewObject);
+  }
+
+  virtual const nsTArray<nsRefPtr<DOMFileImpl>>* GetSubBlobImpls() const MOZ_OVERRIDE
   {
     return &mBlobImpls;
   }
 
-  virtual void GetMozFullPathInternal(nsAString& aFullPath,
-                                      ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual nsresult GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
+
+protected:
+  virtual ~DOMMultipartFileImpl() {}
+
+  nsresult ParseBlobArrayArgument(JSContext* aCx, JS::Value& aValue,
+                                  bool aNativeEOL, UnwrapFuncPtr aUnwrapFunc);
+
+  void SetLengthAndModifiedDate();
 
-  void SetName(const nsAString& aName)
+  nsTArray<nsRefPtr<DOMFileImpl>> mBlobImpls;
+  bool mIsFromNsiFile;
+};
+
+class BlobSet {
+public:
+  BlobSet()
+    : mData(nullptr), mDataLen(0), mDataBufferLen(0)
+  {}
+
+  ~BlobSet()
   {
-    mName = aName;
+    moz_free(mData);
   }
 
-  void SetFromNsIFile(bool aValue)
+  nsresult AppendVoidPtr(const void* aData, uint32_t aLength);
+  nsresult AppendString(JSString* aString, bool nativeEOL, JSContext* aCx);
+  nsresult AppendBlobImpl(DOMFileImpl* aBlobImpl);
+  nsresult AppendArrayBuffer(JSObject* aBuffer);
+  nsresult AppendBlobImpls(const nsTArray<nsRefPtr<DOMFileImpl>>& aBlobImpls);
+
+  nsTArray<nsRefPtr<DOMFileImpl>>& GetBlobImpls() { Flush(); return mBlobImpls; }
+
+  already_AddRefed<nsIDOMBlob>
+  GetBlobInternal(const nsACString& aContentType)
   {
-    mIsFromNsIFile = aValue;
+    nsCOMPtr<nsIDOMBlob> blob = new DOMFile(
+      new DOMMultipartFileImpl(GetBlobImpls(), NS_ConvertASCIItoUTF16(aContentType)));
+    return blob.forget();
   }
 
 protected:
-  virtual ~MultipartFileImpl() {}
+  bool ExpandBufferSize(uint64_t aSize)
+  {
+    using mozilla::CheckedUint32;
+
+    if (mDataBufferLen >= mDataLen + aSize) {
+      mDataLen += aSize;
+      return true;
+    }
+
+    // Start at 1 or we'll loop forever.
+    CheckedUint32 bufferLen =
+      std::max<uint32_t>(static_cast<uint32_t>(mDataBufferLen), 1);
+    while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize)
+      bufferLen *= 2;
+
+    if (!bufferLen.isValid())
+      return false;
+
+    void* data = moz_realloc(mData, bufferLen.value());
+    if (!data)
+      return false;
 
-  void SetLengthAndModifiedDate();
+    mData = data;
+    mDataBufferLen = bufferLen.value();
+    mDataLen += aSize;
+    return true;
+  }
+
+  void Flush() {
+    if (mData) {
+      // If we have some data, create a blob for it
+      // and put it on the stack
 
-  nsTArray<nsRefPtr<FileImpl>> mBlobImpls;
-  bool mIsFromNsIFile;
+      nsRefPtr<DOMFileImpl> blobImpl =
+        new DOMFileImplMemory(mData, mDataLen, EmptyString());
+      mBlobImpls.AppendElement(blobImpl);
+      mData = nullptr; // The nsDOMMemoryFile takes ownership of the buffer
+      mDataLen = 0;
+      mDataBufferLen = 0;
+    }
+  }
+
+  nsTArray<nsRefPtr<DOMFileImpl>> mBlobImpls;
+  void* mData;
+  uint64_t mDataLen;
+  uint64_t mDataBufferLen;
 };
 
-#endif // mozilla_dom_MultipartFileImpl_h
+#endif
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -17,28 +17,29 @@
 extern PRLogModuleInfo* GetDataChannelLog();
 #endif
 #undef LOG
 #define LOG(args) PR_LOG(GetDataChannelLog(), PR_LOG_DEBUG, args)
 
 
 #include "nsDOMDataChannelDeclarations.h"
 #include "nsDOMDataChannel.h"
+#include "nsIDOMFile.h"
 #include "nsIDOMDataChannel.h"
 #include "nsIDOMMessageEvent.h"
 #include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 #include "nsError.h"
 #include "nsAutoPtr.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsNetUtil.h"
+#include "nsDOMFile.h"
 
 #include "DataChannel.h"
 
 // Since we've moved the windows.h include down here, we have to explicitly
 // undef GetBinaryType, otherwise we'll get really odd conflicts
 #ifdef GetBinaryType
 #undef GetBinaryType
 #endif
@@ -266,29 +267,29 @@ nsDOMDataChannel::Close()
 void
 nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv)
 {
   NS_ConvertUTF16toUTF8 msgString(aData);
   Send(nullptr, msgString, msgString.Length(), false, aRv);
 }
 
 void
-nsDOMDataChannel::Send(File& aData, ErrorResult& aRv)
+nsDOMDataChannel::Send(nsIDOMBlob* aData, ErrorResult& aRv)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   nsCOMPtr<nsIInputStream> msgStream;
-  nsresult rv = aData.GetInternalStream(getter_AddRefs(msgStream));
+  nsresult rv = aData->GetInternalStream(getter_AddRefs(msgStream));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   uint64_t msgLength;
-  rv = aData.GetSize(&msgLength);
+  rv = aData->GetSize(&msgLength);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   if (msgLength > UINT32_MAX) {
     aRv.Throw(NS_ERROR_FILE_TOO_BIG);
     return;
@@ -387,17 +388,17 @@ nsDOMDataChannel::DoOnMessageAvailable(c
     return NS_ERROR_FAILURE;
   }
   JSContext* cx = jsapi.cx();
 
   JS::Rooted<JS::Value> jsData(cx);
 
   if (aBinary) {
     if (mBinaryType == DC_BINARY_TYPE_BLOB) {
-      rv = nsContentUtils::CreateBlobBuffer(cx, GetOwner(), aData, &jsData);
+      rv = nsContentUtils::CreateBlobBuffer(cx, aData, &jsData);
       NS_ENSURE_SUCCESS(rv, rv);
     } else if (mBinaryType == DC_BINARY_TYPE_ARRAYBUFFER) {
       JS::Rooted<JSObject*> arrayBuf(cx);
       rv = nsContentUtils::CreateArrayBuffer(cx, aData, arrayBuf.address());
       NS_ENSURE_SUCCESS(rv, rv);
       jsData = OBJECT_TO_JSVAL(arrayBuf);
     } else {
       NS_RUNTIMEABORT("Unknown binary type!");
--- a/content/base/src/nsDOMDataChannel.h
+++ b/content/base/src/nsDOMDataChannel.h
@@ -12,20 +12,16 @@
 #include "mozilla/dom/DataChannelBinding.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/net/DataChannelListener.h"
 #include "nsIDOMDataChannel.h"
 #include "nsIInputStream.h"
 
 
 namespace mozilla {
-namespace dom {
-class File;
-}
-
 class DataChannel;
 };
 
 class nsDOMDataChannel : public mozilla::DOMEventTargetHelper,
                          public nsIDOMDataChannel,
                          public mozilla::DataChannelListener
 {
 public:
@@ -65,17 +61,17 @@ public:
       static_cast<int>(mBinaryType));
   }
   void SetBinaryType(mozilla::dom::RTCDataChannelType aType)
   {
     mBinaryType = static_cast<DataChannelBinaryType>(
       static_cast<int>(aType));
   }
   void Send(const nsAString& aData, mozilla::ErrorResult& aRv);
-  void Send(mozilla::dom::File& aData, mozilla::ErrorResult& aRv);
+  void Send(nsIDOMBlob* aData, mozilla::ErrorResult& aRv);
   void Send(const mozilla::dom::ArrayBuffer& aData, mozilla::ErrorResult& aRv);
   void Send(const mozilla::dom::ArrayBufferView& aData,
             mozilla::ErrorResult& aRv);
 
   // Uses XPIDL GetProtocol.
   bool Ordered() const;
   uint16_t Id() const;
   uint16_t Stream() const; // deprecated
rename from content/base/src/File.cpp
rename to content/base/src/nsDOMFile.cpp
--- a/content/base/src/File.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -1,22 +1,23 @@
 /* -*- Mode: C++; tab-width: 2; 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 "mozilla/dom/File.h"
+#include "nsDOMFile.h"
 
-#include "MultipartFileImpl.h"
 #include "nsCExternalHandlerService.h"
 #include "nsContentCID.h"
 #include "nsContentUtils.h"
+#include "nsDOMClassInfoID.h"
 #include "nsError.h"
 #include "nsICharsetDetector.h"
+#include "nsIClassInfo.h"
 #include "nsIConverterInputStream.h"
 #include "nsIDocument.h"
 #include "nsIFileStreams.h"
 #include "nsIInputStream.h"
 #include "nsIIPCSerializableInputStream.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMIMEService.h"
 #include "nsISeekableStream.h"
@@ -29,38 +30,36 @@
 #include "nsHostObjectProtocolHandler.h"
 #include "nsStringStream.h"
 #include "nsJSUtils.h"
 #include "nsPrintfCString.h"
 #include "mozilla/SHA1.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/BlobBinding.h"
-#include "mozilla/dom/BlobSet.h"
-#include "mozilla/dom/DOMError.h"
-#include "mozilla/dom/FileBinding.h"
-#include "mozilla/dom/WorkerPrivate.h"
 #include "nsThreadUtils.h"
 
 #include "mozilla/dom/FileListBinding.h"
 
+DOMCI_DATA(File, mozilla::dom::DOMFile)
+DOMCI_DATA(Blob, mozilla::dom::DOMFile)
+
 namespace mozilla {
 namespace dom {
 
-// XXXkhuey the input stream that we pass out of a File
-// can outlive the actual File object.  Thus, we must
+// XXXkhuey the input stream that we pass out of a DOMFile
+// can outlive the actual DOMFile object.  Thus, we must
 // ensure that the buffer underlying the stream we get
 // from NS_NewByteInputStream is held alive as long as the
 // stream is.  We do that by passing back this class instead.
 class DataOwnerAdapter MOZ_FINAL : public nsIInputStream,
                                    public nsISeekableStream,
                                    public nsIIPCSerializableInputStream
 {
-  typedef FileImplMemory::DataOwner DataOwner;
+  typedef DOMFileImplMemory::DataOwner DataOwner;
 public:
   static nsresult Create(DataOwner* aDataOwner,
                          uint32_t aStart,
                          uint32_t aLength,
                          nsIInputStream** _retval);
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
@@ -119,330 +118,252 @@ nsresult DataOwnerAdapter::Create(DataOw
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::File implementation
+// mozilla::dom::DOMFile implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(File)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMFile)
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(File)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMFile)
   MOZ_ASSERT(tmp->mImpl);
   tmp->mImpl->Unlink();
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(File)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMFile)
   MOZ_ASSERT(tmp->mImpl);
   tmp->mImpl->Traverse(cb);
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(File)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(File)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMFile)
   // This class should not receive any nsIRemoteBlob QI!
   MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsIRemoteBlob)));
 
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
   NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, IsFile())
   NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
   NS_INTERFACE_MAP_ENTRY(nsIMutable)
+  NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, IsFile())
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !(IsFile()))
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(File)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(File)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMFile)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMFile)
 
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aName,
-             const nsAString& aContentType, uint64_t aLength,
-             uint64_t aLastModifiedDate)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::Create(const nsAString& aName, const nsAString& aContentType,
+                uint64_t aLength, uint64_t aLastModifiedDate)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplBase(aName, aContentType, aLength, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aName,
-             const nsAString& aContentType, uint64_t aLength)
-{
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplBase(aName, aContentType, aLength));
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplBase(aName, aContentType, aLength, aLastModifiedDate));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aContentType,
-             uint64_t aLength)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::Create(const nsAString& aName, const nsAString& aContentType,
+                uint64_t aLength)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplBase(aContentType, aLength));
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplBase(aName, aContentType, aLength));
+  return file.forget();
+}
+
+/* static */ already_AddRefed<DOMFile>
+DOMFile::Create(const nsAString& aContentType, uint64_t aLength)
+{
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplBase(aContentType, aLength));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aContentType,
-             uint64_t aStart, uint64_t aLength)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::Create(const nsAString& aContentType, uint64_t aStart,
+                uint64_t aLength)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplBase(aContentType, aStart, aLength));
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplBase(aContentType, aStart, aLength));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aName,
-                       const nsAString& aContentType,
-                       uint64_t aLastModifiedDate)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateMemoryFile(void* aMemoryBuffer, uint64_t aLength,
+                          const nsAString& aName,
+                          const nsAString& aContentType,
+                          uint64_t aLastModifiedDate)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplMemory(aMemoryBuffer, aLength, aName,
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplMemory(aMemoryBuffer, aLength, aName,
                           aContentType, aLastModifiedDate));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aContentType)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateMemoryFile(void* aMemoryBuffer, uint64_t aLength,
+                          const nsAString& aContentType)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplMemory(aMemoryBuffer, aLength, aContentType));
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplMemory(aMemoryBuffer, aLength, aContentType));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::CreateTemporaryFileBlob(nsISupports* aParent, PRFileDesc* aFD,
-                              uint64_t aStartPos, uint64_t aLength,
-                              const nsAString& aContentType)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateTemporaryFileBlob(PRFileDesc* aFD, uint64_t aStartPos,
+                                 uint64_t aLength,
+                                      const nsAString& aContentType)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplTemporaryFileBlob(aFD, aStartPos, aLength, aContentType));
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplTemporaryFileBlob(aFD, aStartPos, aLength, aContentType));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateFromFile(nsIFile* aFile)
 {
-  nsRefPtr<File> file = new File(aParent, new FileImplFile(aFile));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, const nsAString& aContentType,
-                     uint64_t aLength, nsIFile* aFile,
-                     indexedDB::FileInfo* aFileInfo)
-{
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplFile(aContentType, aLength, aFile, aFileInfo));
+  nsRefPtr<DOMFile> file = new DOMFile(new DOMFileImplFile(aFile));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, const nsAString& aName,
-                     const nsAString& aContentType,
-                     uint64_t aLength, nsIFile* aFile,
-                     indexedDB::FileInfo* aFileInfo)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateFromFile(const nsAString& aContentType, uint64_t aLength,
+                        nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplFile(aName, aContentType, aLength, aFile, aFileInfo));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                        indexedDB::FileInfo* aFileInfo)
-{
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplFile(aFile, aFileInfo));
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplFile(aContentType, aLength, aFile, aFileInfo));
   return file.forget();
 }
 
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                     const nsAString& aName, const nsAString& aContentType)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateFromFile(const nsAString& aName,
+                        const nsAString& aContentType,
+                        uint64_t aLength, nsIFile* aFile,
+                        indexedDB::FileInfo* aFileInfo)
 {
-  nsRefPtr<File> file = new File(aParent,
-    new FileImplFile(aFile, aName, aContentType));
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplFile(aName, aContentType, aLength, aFile, aFileInfo));
   return file.forget();
 }
 
-File::File(nsISupports* aParent, FileImpl* aImpl)
-  : mImpl(aImpl)
-  , mParent(aParent)
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateFromFile(nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
 {
-  MOZ_ASSERT(mImpl);
-
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aParent);
-    if (win) {
-      MOZ_ASSERT(win->IsInnerWindow());
-    }
-  }
-#endif
+  nsRefPtr<DOMFile> file = new DOMFile(new DOMFileImplFile(aFile, aFileInfo));
+  return file.forget();
 }
 
-const nsTArray<nsRefPtr<FileImpl>>*
-File::GetSubBlobImpls() const
+/* static */ already_AddRefed<DOMFile>
+DOMFile::CreateFromFile(nsIFile* aFile, const nsAString& aName,
+                        const nsAString& aContentType)
+{
+  nsRefPtr<DOMFile> file = new DOMFile(
+    new DOMFileImplFile(aFile, aName, aContentType));
+  return file.forget();
+}
+
+const nsTArray<nsRefPtr<DOMFileImpl>>*
+DOMFile::GetSubBlobImpls() const
 {
   return mImpl->GetSubBlobImpls();
 }
 
 bool
-File::IsSizeUnknown() const
+DOMFile::IsSizeUnknown() const
 {
   return mImpl->IsSizeUnknown();
 }
 
 bool
-File::IsDateUnknown() const
+DOMFile::IsDateUnknown() const
 {
   return mImpl->IsDateUnknown();
 }
 
 bool
-File::IsFile() const
+DOMFile::IsFile() const
 {
   return mImpl->IsFile();
 }
 
 void
-File::SetLazyData(const nsAString& aName, const nsAString& aContentType,
-                  uint64_t aLength, uint64_t aLastModifiedDate)
+DOMFile::SetLazyData(const nsAString& aName, const nsAString& aContentType,
+                     uint64_t aLength, uint64_t aLastModifiedDate)
 {
   return mImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate);
 }
 
-already_AddRefed<File>
-File::CreateSlice(uint64_t aStart, uint64_t aLength,
-                  const nsAString& aContentType,
-                  ErrorResult& aRv)
+already_AddRefed<nsIDOMBlob>
+DOMFile::CreateSlice(uint64_t aStart, uint64_t aLength,
+                     const nsAString& aContentType)
 {
-  nsRefPtr<FileImpl> impl = mImpl->CreateSlice(aStart, aLength,
-                                               aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  nsRefPtr<File> file = new File(mParent, impl);
-  return file.forget();
+  nsRefPtr<DOMFileImpl> impl =
+    mImpl->CreateSlice(aStart, aLength, aContentType);
+  nsRefPtr<DOMFile> slice = new DOMFile(impl);
+  return slice.forget();
 }
 
 NS_IMETHODIMP
-File::GetName(nsAString& aFileName)
+DOMFile::Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
+                    const JS::CallArgs& aArgs)
 {
-  mImpl->GetName(aFileName);
-  return NS_OK;
+  return mImpl->Initialize(aOwner, aCx, aObj, aArgs);
 }
 
 NS_IMETHODIMP
-File::GetPath(nsAString& aPath)
+DOMFile::GetName(nsAString& aFileName)
+{
+  return mImpl->GetName(aFileName);
+}
+
+NS_IMETHODIMP
+DOMFile::GetPath(nsAString& aPath)
 {
   return mImpl->GetPath(aPath);
 }
 
 NS_IMETHODIMP
-File::GetLastModifiedDate(JSContext* aCx,
+DOMFile::GetLastModifiedDate(JSContext* aCx,
                              JS::MutableHandle<JS::Value> aDate)
 {
-  ErrorResult rv;
-  Date value = GetLastModifiedDate(rv);
-  if (rv.Failed()) {
-    return rv.ErrorCode();
-  }
-
-  if (!value.ToDateObject(aCx, aDate)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  return NS_OK;
+  return mImpl->GetLastModifiedDate(aCx, aDate);
 }
 
-Date
-File::GetLastModifiedDate(ErrorResult& aRv)
+NS_IMETHODIMP
+DOMFile::GetMozFullPath(nsAString &aFileName)
 {
-  int64_t value = GetLastModified(aRv);
-  if (aRv.Failed()) {
-    return Date();
-  }
-
-  return Date(value);
-}
-
-int64_t
-File::GetLastModified(ErrorResult& aRv)
-{
-  return mImpl->GetLastModified(aRv);
+  return mImpl->GetMozFullPath(aFileName);
 }
 
 NS_IMETHODIMP
-File::GetMozFullPath(nsAString& aFileName)
-{
-  ErrorResult rv;
-  GetMozFullPath(aFileName, rv);
-  return rv.ErrorCode();
-}
-
-void
-File::GetMozFullPath(nsAString& aFilename, ErrorResult& aRv)
+DOMFile::GetMozFullPathInternal(nsAString &aFileName)
 {
-  mImpl->GetMozFullPath(aFilename, aRv);
-}
-
-NS_IMETHODIMP
-File::GetMozFullPathInternal(nsAString& aFileName)
-{
-  ErrorResult rv;
-  mImpl->GetMozFullPathInternal(aFileName, rv);
-  return rv.ErrorCode();
+  return mImpl->GetMozFullPathInternal(aFileName);
 }
 
 NS_IMETHODIMP
-File::GetSize(uint64_t* aSize)
+DOMFile::GetSize(uint64_t* aSize)
 {
-  MOZ_ASSERT(aSize);
-
-  ErrorResult rv;
-  *aSize = GetSize(rv);
-  return rv.ErrorCode();
-}
-
-uint64_t
-File::GetSize(ErrorResult& aRv)
-{
-  return mImpl->GetSize(aRv);
+  return mImpl->GetSize(aSize);
 }
 
 NS_IMETHODIMP
-File::GetType(nsAString &aType)
+DOMFile::GetType(nsAString &aType)
 {
-  mImpl->GetType(aType);
-  return NS_OK;
+  return mImpl->GetType(aType);
 }
 
 NS_IMETHODIMP
-File::GetMozLastModifiedDate(uint64_t* aDate)
+DOMFile::GetMozLastModifiedDate(uint64_t* aDate)
 {
-  MOZ_ASSERT(aDate);
-
-  ErrorResult rv;
-  *aDate = GetLastModified(rv);
-  return rv.ErrorCode();
+  return mImpl->GetMozLastModifiedDate(aDate);
 }
 
 // Makes sure that aStart and aEnd is less then or equal to aSize and greater
 // than 0
 static void
 ParseSize(int64_t aSize, int64_t& aStart, int64_t& aEnd)
 {
   CheckedInt64 newStartOffset = aStart;
@@ -473,339 +394,224 @@ ParseSize(int64_t aSize, int64_t& aStart
   }
   else {
     aStart = newStartOffset.value();
     aEnd = newEndOffset.value();
   }
 }
 
 NS_IMETHODIMP
-File::Slice(int64_t aStart, int64_t aEnd,
-            const nsAString& aContentType, uint8_t aArgc,
-            nsIDOMBlob **aBlob)
+DOMFile::Slice(int64_t aStart, int64_t aEnd,
+               const nsAString& aContentType, uint8_t aArgc,
+               nsIDOMBlob **aBlob)
 {
-  Optional<int64_t> start;
-  if (aArgc > 0) {
-    start.Construct(aStart);
+  MOZ_ASSERT(mImpl);
+  nsRefPtr<DOMFileImpl> impl;
+  nsresult rv = mImpl->Slice(aStart, aEnd, aContentType, aArgc,
+                             getter_AddRefs(impl));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
   }
 
-  Optional<int64_t> end;
-  if (aArgc > 1) {
-    end.Construct(aEnd);
-  }
+  nsRefPtr<DOMFile> blob = new DOMFile(impl);
+  blob.forget(aBlob);
 
-  ErrorResult rv;
-  nsRefPtr<File> file = Slice(start, end, aContentType, rv);
-  if (rv.Failed()) {
-    return rv.ErrorCode();
-  }
-
-  file.forget(aBlob);
   return NS_OK;
 }
 
-already_AddRefed<File>
-File::Slice(const Optional<int64_t>& aStart,
-            const Optional<int64_t>& aEnd,
-            const nsAString& aContentType,
-            ErrorResult& aRv)
+NS_IMETHODIMP
+DOMFile::GetInternalStream(nsIInputStream** aStream)
 {
-  nsRefPtr<FileImpl> impl =
-    mImpl->Slice(aStart, aEnd, aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  nsRefPtr<File> file = new File(mParent, impl);
-  return file.forget();
-}
-
-NS_IMETHODIMP
-File::GetInternalStream(nsIInputStream** aStream)
-{
-  return mImpl->GetInternalStream(aStream);
+ return mImpl->GetInternalStream(aStream);
 }
 
 NS_IMETHODIMP_(int64_t)
-File::GetFileId()
+DOMFile::GetFileId()
 {
   return mImpl->GetFileId();
 }
 
 NS_IMETHODIMP_(void)
-File::AddFileInfo(indexedDB::FileInfo* aFileInfo)
+DOMFile::AddFileInfo(indexedDB::FileInfo* aFileInfo)
 {
   mImpl->AddFileInfo(aFileInfo);
 }
 
 indexedDB::FileInfo*
-File::GetFileInfo(indexedDB::FileManager* aFileManager)
+DOMFile::GetFileInfo(indexedDB::FileManager* aFileManager)
 {
   return mImpl->GetFileInfo(aFileManager);
 }
 
 NS_IMETHODIMP
-File::GetSendInfo(nsIInputStream** aBody,
-                  uint64_t* aContentLength,
-                  nsACString& aContentType,
-                  nsACString& aCharset)
+DOMFile::GetSendInfo(nsIInputStream** aBody,
+                     uint64_t* aContentLength,
+                     nsACString& aContentType,
+                     nsACString& aCharset)
 {
   return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
 }
 
 NS_IMETHODIMP
-File::GetMutable(bool* aMutable)
+DOMFile::GetMutable(bool* aMutable)
 {
   return mImpl->GetMutable(aMutable);
 }
 
 NS_IMETHODIMP
-File::SetMutable(bool aMutable)
+DOMFile::SetMutable(bool aMutable)
 {
   return mImpl->SetMutable(aMutable);
 }
 
 NS_IMETHODIMP_(bool)
-File::IsMemoryFile()
+DOMFile::IsMemoryFile()
 {
   return mImpl->IsMemoryFile();
 }
 
-JSObject*
-File::WrapObject(JSContext* aCx)
-{
-  return IsFile() ? FileBinding::Wrap(aCx, this)
-                  : BlobBinding::Wrap(aCx, this);
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
-{
-  nsRefPtr<MultipartFileImpl> impl = new MultipartFileImpl();
-
-  impl->InitializeBlob();
-  MOZ_ASSERT(!impl->IsFile());
-
-  nsRefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(
-        const GlobalObject& aGlobal,
-        const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
-        const BlobPropertyBag& aBag,
-        ErrorResult& aRv)
-{
-  nsRefPtr<MultipartFileImpl> impl = new MultipartFileImpl();
+////////////////////////////////////////////////////////////////////////////
+// mozilla::dom::DOMFileImpl implementation
 
-  impl->InitializeBlob(aGlobal.Context(), aData, aBag.mType,
-                       aBag.mEndings == EndingTypes::Native, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(!impl->IsFile());
-
-  nsRefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(
-        const GlobalObject& aGlobal,
-        const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
-        const nsAString& aName,
-        const FilePropertyBag& aBag,
-        ErrorResult& aRv)
+nsresult
+DOMFileImpl::Slice(int64_t aStart, int64_t aEnd,
+                   const nsAString& aContentType, uint8_t aArgc,
+                   DOMFileImpl** aBlobImpl)
 {
-  nsRefPtr<MultipartFileImpl> impl = new MultipartFileImpl(aName);
-
-  impl->InitializeBlob(aGlobal.Context(), aData, aBag.mType, false, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
+  *aBlobImpl = nullptr;
 
-  nsRefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
-  return file.forget();
-}
+  // Truncate aStart and aEnd so that we stay within this file.
+  uint64_t thisLength;
+  nsresult rv = GetSize(&thisLength);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  File& aData,
-                  const ChromeFilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  if (!nsContentUtils::IsCallerChrome()) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
+  if (aArgc < 2) {
+    aEnd = (int64_t)thisLength;
   }
 
-  nsRefPtr<MultipartFileImpl> impl = new MultipartFileImpl(EmptyString());
-  impl->InitializeChromeFile(aData, aBag, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
+  ParseSize((int64_t)thisLength, aStart, aEnd);
 
-  nsRefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
-  return domFile.forget();
-}
+  nsRefPtr<DOMFileImpl> impl =
+    CreateSlice((uint64_t)aStart, (uint64_t)(aEnd - aStart), aContentType);
 
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  nsIFile* aData,
-                  const ChromeFilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  if (!nsContentUtils::IsCallerChrome()) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
+  if (!impl) {
+    return NS_ERROR_UNEXPECTED;
   }
 
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
-
-  nsRefPtr<MultipartFileImpl> impl = new MultipartFileImpl(EmptyString());
-  impl->InitializeChromeFile(window, aData, aBag, true, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
-
-  nsRefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
-  return domFile.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  const nsAString& aData,
-                  const ChromeFilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  if (!nsContentUtils::IsCallerChrome()) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
-
-  nsRefPtr<MultipartFileImpl> impl = new MultipartFileImpl(EmptyString());
-  impl->InitializeChromeFile(window, aData, aBag, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
-
-  nsRefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
-  return domFile.forget();
+  impl.forget(aBlobImpl);
+  return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::FileImpl implementation
+// DOMFileImpl implementation
 
-already_AddRefed<FileImpl>
-FileImpl::Slice(const Optional<int64_t>& aStart,
-                const Optional<int64_t>& aEnd,
-                const nsAString& aContentType,
-                ErrorResult& aRv)
-{
-  // Truncate aStart and aEnd so that we stay within this file.
-  uint64_t thisLength = GetSize(aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  int64_t start = aStart.WasPassed() ? aStart.Value() : 0;
-  int64_t end = aEnd.WasPassed() ? aEnd.Value() : (int64_t)thisLength;
-
-  ParseSize((int64_t)thisLength, start, end);
-
-  return CreateSlice((uint64_t)start, (uint64_t)(end - start),
-                     aContentType, aRv);
-}
+NS_IMPL_ISUPPORTS(DOMFileImpl, PIDOMFileImpl)
 
 ////////////////////////////////////////////////////////////////////////////
-// FileImpl implementation
-
-NS_IMPL_ISUPPORTS(FileImpl, PIFileImpl)
+// DOMFileImplFile implementation
 
-////////////////////////////////////////////////////////////////////////////
-// FileImplFile implementation
+NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplFile, DOMFileImpl)
 
-NS_IMPL_ISUPPORTS_INHERITED0(FileImplFile, FileImpl)
-
-void
-FileImplBase::GetName(nsAString& aName)
+nsresult
+DOMFileImplBase::GetName(nsAString& aName)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   aName = mName;
+  return NS_OK;
 }
 
 nsresult
-FileImplBase::GetPath(nsAString& aPath)
+DOMFileImplBase::GetPath(nsAString& aPath)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   aPath = mPath;
   return NS_OK;
 }
 
-void
-FileImplBase::GetMozFullPath(nsAString& aFileName, ErrorResult& aRv)
+nsresult
+DOMFileImplBase::GetLastModifiedDate(JSContext* aCx,
+                                     JS::MutableHandle<JS::Value> aDate)
+{
+  JS::Rooted<JSObject*> date(aCx, JS_NewDateObjectMsec(aCx, JS_Now() / PR_USEC_PER_MSEC));
+  if (!date) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  aDate.setObject(*date);
+  return NS_OK;
+}
+
+nsresult
+DOMFileImplBase::GetMozFullPath(nsAString &aFileName)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
 
-  aFileName.Truncate();
+  // It is unsafe to call IsCallerChrome on a non-main thread. If
+  // you hit the following assertion you need to figure out some other way to
+  // determine privileges and call GetMozFullPathInternal.
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  if (NS_IsMainThread()) {
-    if (nsContentUtils::IsCallerChrome()) {
-      GetMozFullPathInternal(aFileName, aRv);
-    }
-
-    return;
+  if (nsContentUtils::IsCallerChrome()) {
+    return GetMozFullPathInternal(aFileName);
   }
-
-  workers::WorkerPrivate* workerPrivate =
-    workers::GetCurrentThreadWorkerPrivate();
-  MOZ_ASSERT(workerPrivate);
-
-  if (workerPrivate->UsesSystemPrincipal()) {
-    GetMozFullPathInternal(aFileName, aRv);
-  }
+  aFileName.Truncate();
+  return NS_OK;
 }
 
-void
-FileImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv)
+nsresult
+DOMFileImplBase::GetMozFullPathInternal(nsAString& aFileName)
 {
   if (!mIsFile) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
+    return NS_ERROR_FAILURE;
   }
 
   aFileName.Truncate();
+  return NS_OK;
+}
+
+nsresult
+DOMFileImplBase::GetSize(uint64_t* aSize)
+{
+  *aSize = mLength;
+  return NS_OK;
 }
 
-void
-FileImplBase::GetType(nsAString& aType)
+nsresult
+DOMFileImplBase::GetType(nsAString& aType)
 {
   aType = mContentType;
+  return NS_OK;
 }
 
-int64_t
-FileImplBase::GetLastModified(ErrorResult& aRv)
+nsresult
+DOMFileImplBase::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   if (IsDateUnknown()) {
     mLastModificationDate = PR_Now();
   }
+  *aLastModifiedDate = mLastModificationDate;
+  return NS_OK;
+}
 
-  return mLastModificationDate / PR_USEC_PER_MSEC;
+already_AddRefed<DOMFileImpl>
+DOMFileImplBase::CreateSlice(uint64_t aStart, uint64_t aLength,
+                             const nsAString& aContentType)
+{
+  return nullptr;
+}
+
+nsresult
+DOMFileImplBase::GetInternalStream(nsIInputStream** aStream)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 int64_t
-FileImplBase::GetFileId()
+DOMFileImplBase::GetFileId()
 {
   int64_t id = -1;
 
   if (IsStoredFile() && IsWholeFile() && !IsSnapshot()) {
     if (!indexedDB::IndexedDatabaseManager::IsClosed()) {
       indexedDB::IndexedDatabaseManager::FileMutex().Lock();
     }
 
@@ -821,17 +627,17 @@ FileImplBase::GetFileId()
       indexedDB::IndexedDatabaseManager::FileMutex().Unlock();
     }
   }
 
   return id;
 }
 
 void
-FileImplBase::AddFileInfo(indexedDB::FileInfo* aFileInfo)
+DOMFileImplBase::AddFileInfo(indexedDB::FileInfo* aFileInfo)
 {
   if (indexedDB::IndexedDatabaseManager::IsClosed()) {
     NS_ERROR("Shouldn't be called after shutdown!");
     return;
   }
 
   nsRefPtr<indexedDB::FileInfo> fileInfo = aFileInfo;
 
@@ -840,17 +646,17 @@ FileImplBase::AddFileInfo(indexedDB::Fil
   NS_ASSERTION(!mFileInfos.Contains(aFileInfo),
                "Adding the same file info agan?!");
 
   nsRefPtr<indexedDB::FileInfo>* element = mFileInfos.AppendElement();
   element->swap(fileInfo);
 }
 
 indexedDB::FileInfo*
-FileImplBase::GetFileInfo(indexedDB::FileManager* aFileManager)
+DOMFileImplBase::GetFileInfo(indexedDB::FileManager* aFileManager)
 {
   if (indexedDB::IndexedDatabaseManager::IsClosed()) {
     NS_ERROR("Shouldn't be called after shutdown!");
     return nullptr;
   }
 
   // A slice created from a stored file must keep the file info alive.
   // However, we don't support sharing of slices yet, so the slice must be
@@ -872,246 +678,263 @@ FileImplBase::GetFileInfo(indexedDB::Fil
       return fileInfo;
     }
   }
 
   return nullptr;
 }
 
 nsresult
-FileImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
-                          nsACString& aContentType, nsACString& aCharset)
+DOMFileImplBase::GetSendInfo(nsIInputStream** aBody,
+                             uint64_t* aContentLength,
+                             nsACString& aContentType,
+                             nsACString& aCharset)
 {
-  MOZ_ASSERT(aContentLength);
-
   nsresult rv;
 
   nsCOMPtr<nsIInputStream> stream;
-  rv = GetInternalStream(getter_AddRefs(stream));
+  rv = this->GetInternalStream(getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  ErrorResult error;
-  *aContentLength = GetSize(error);
-  if (NS_WARN_IF(error.Failed())) {
-    return error.ErrorCode();
-  }
+  rv = this->GetSize(aContentLength);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  nsAutoString contentType;
-  GetType(contentType);
+  nsString contentType;
+  rv = this->GetType(contentType);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   CopyUTF16toUTF8(contentType, aContentType);
 
   aCharset.Truncate();
 
   stream.forget(aBody);
   return NS_OK;
 }
 
 nsresult
-FileImplBase::GetMutable(bool* aMutable) const
+DOMFileImplBase::GetMutable(bool* aMutable) const
 {
   *aMutable = !mImmutable;
   return NS_OK;
 }
 
 nsresult
-FileImplBase::SetMutable(bool aMutable)
+DOMFileImplBase::SetMutable(bool aMutable)
 {
   nsresult rv = NS_OK;
 
   NS_ENSURE_ARG(!mImmutable || !aMutable);
 
   if (!mImmutable && !aMutable) {
     // Force the content type and size to be cached
-    nsAutoString dummyString;
-    GetType(dummyString);
+    nsString dummyString;
+    rv = this->GetType(dummyString);
+    NS_ENSURE_SUCCESS(rv, rv);
 
-    ErrorResult error;
-    GetSize(error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.ErrorCode();
-    }
+    uint64_t dummyInt;
+    rv = this->GetSize(&dummyInt);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   mImmutable = !aMutable;
   return rv;
 }
 
 ////////////////////////////////////////////////////////////////////////////
-// FileImplFile implementation
+// DOMFileImplFile implementation
 
-already_AddRefed<FileImpl>
-FileImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
-                          const nsAString& aContentType,
-                          ErrorResult& aRv)
+already_AddRefed<DOMFileImpl>
+DOMFileImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
+                             const nsAString& aContentType)
 {
-  nsRefPtr<FileImpl> impl =
-    new FileImplFile(this, aStart, aLength, aContentType);
+  nsRefPtr<DOMFileImpl> impl =
+    new DOMFileImplFile(this, aStart, aLength, aContentType);
   return impl.forget();
 }
 
-void
-FileImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv)
+nsresult
+DOMFileImplFile::GetMozFullPathInternal(nsAString& aFilename)
+{
+  NS_ASSERTION(mIsFile, "Should only be called on files");
+  return mFile->GetPath(aFilename);
+}
+
+nsresult
+DOMFileImplFile::GetLastModifiedDate(JSContext* aCx,
+                                     JS::MutableHandle<JS::Value> aLastModifiedDate)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
-  aRv = mFile->GetPath(aFilename);
+
+  PRTime msecs;
+  if (IsDateUnknown()) {
+    nsresult rv = mFile->GetLastModifiedTime(&msecs);
+    NS_ENSURE_SUCCESS(rv, rv);
+    mLastModificationDate = msecs;
+  } else {
+    msecs = mLastModificationDate;
+  }
+
+  JSObject* date = JS_NewDateObjectMsec(aCx, msecs);
+  if (date) {
+    aLastModifiedDate.setObject(*date);
+  }
+  else {
+    date = JS_NewDateObjectMsec(aCx, JS_Now() / PR_USEC_PER_MSEC);
+    aLastModifiedDate.setObject(*date);
+  }
+
+  return NS_OK;
 }
 
-uint64_t
-FileImplFile::GetSize(ErrorResult& aRv)
+nsresult
+DOMFileImplFile::GetSize(uint64_t* aFileSize)
 {
   if (IsSizeUnknown()) {
     NS_ASSERTION(mWholeFile,
                  "Should only use lazy size when using the whole file");
     int64_t fileSize;
-    aRv = mFile->GetFileSize(&fileSize);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return 0;
-    }
+    nsresult rv = mFile->GetFileSize(&fileSize);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if (fileSize < 0) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return 0;
+      return NS_ERROR_FAILURE;
     }
 
     mLength = fileSize;
   }
 
-  return mLength;
+  *aFileSize = mLength;
+
+  return NS_OK;
 }
 
-void
-FileImplFile::GetType(nsAString& aType)
+nsresult
+DOMFileImplFile::GetType(nsAString& aType)
 {
   if (mContentType.IsVoid()) {
     NS_ASSERTION(mWholeFile,
                  "Should only use lazy ContentType when using the whole file");
     nsresult rv;
     nsCOMPtr<nsIMIMEService> mimeService =
       do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      aType.Truncate();
-      return;
-    }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoCString mimeType;
     rv = mimeService->GetTypeFromFile(mFile, mimeType);
     if (NS_FAILED(rv)) {
       mimeType.Truncate();
     }
 
     AppendUTF8toUTF16(mimeType, mContentType);
     mContentType.SetIsVoid(false);
   }
 
   aType = mContentType;
+
+  return NS_OK;
 }
 
-int64_t
-FileImplFile::GetLastModified(ErrorResult& aRv)
+nsresult
+DOMFileImplFile::GetMozLastModifiedDate(uint64_t* aLastModifiedDate)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   if (IsDateUnknown()) {
     PRTime msecs;
-    aRv = mFile->GetLastModifiedTime(&msecs);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return 0;
-    }
-
+    nsresult rv = mFile->GetLastModifiedTime(&msecs);
+    NS_ENSURE_SUCCESS(rv, rv);
     mLastModificationDate = msecs;
   }
-
-  return mLastModificationDate;
+  *aLastModifiedDate = mLastModificationDate;
+  return NS_OK;
 }
 
 const uint32_t sFileStreamFlags =
   nsIFileInputStream::CLOSE_ON_EOF |
   nsIFileInputStream::REOPEN_ON_REWIND |
   nsIFileInputStream::DEFER_OPEN |
   nsIFileInputStream::SHARE_DELETE;
 
 nsresult
-FileImplFile::GetInternalStream(nsIInputStream** aStream)
+DOMFileImplFile::GetInternalStream(nsIInputStream** aStream)
 {
   return mWholeFile ?
     NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags) :
     NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
                                       -1, -1, sFileStreamFlags);
 }
 
 void
-FileImplFile::SetPath(const nsAString& aPath)
+DOMFileImplFile::SetPath(const nsAString& aPath)
 {
   MOZ_ASSERT(aPath.IsEmpty() ||
              aPath[aPath.Length() - 1] == char16_t('/'),
              "Path must end with a path separator");
   mPath = aPath;
 }
 
 ////////////////////////////////////////////////////////////////////////////
-// FileImplMemory implementation
+// DOMFileImplMemory implementation
 
-NS_IMPL_ISUPPORTS_INHERITED0(FileImplMemory, FileImpl)
+NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplMemory, DOMFileImpl)
 
-already_AddRefed<FileImpl>
-FileImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
+already_AddRefed<DOMFileImpl>
+DOMFileImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
+                               const nsAString& aContentType)
 {
-  nsRefPtr<FileImpl> impl =
-    new FileImplMemory(this, aStart, aLength, aContentType);
+  nsRefPtr<DOMFileImpl> impl =
+    new DOMFileImplMemory(this, aStart, aLength, aContentType);
   return impl.forget();
 }
 
 nsresult
-FileImplMemory::GetInternalStream(nsIInputStream** aStream)
+DOMFileImplMemory::GetInternalStream(nsIInputStream** aStream)
 {
   if (mLength > INT32_MAX)
     return NS_ERROR_FAILURE;
 
   return DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
 }
 
 /* static */ StaticMutex
-FileImplMemory::DataOwner::sDataOwnerMutex;
+DOMFileImplMemory::DataOwner::sDataOwnerMutex;
 
-/* static */ StaticAutoPtr<LinkedList<FileImplMemory::DataOwner>>
-FileImplMemory::DataOwner::sDataOwners;
+/* static */ StaticAutoPtr<LinkedList<DOMFileImplMemory::DataOwner>>
+DOMFileImplMemory::DataOwner::sDataOwners;
 
 /* static */ bool
-FileImplMemory::DataOwner::sMemoryReporterRegistered = false;
+DOMFileImplMemory::DataOwner::sMemoryReporterRegistered = false;
 
-MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
+MOZ_DEFINE_MALLOC_SIZE_OF(DOMMemoryFileDataOwnerMallocSizeOf)
 
-class FileImplMemoryDataOwnerMemoryReporter MOZ_FINAL
+class DOMFileImplMemoryDataOwnerMemoryReporter MOZ_FINAL
   : public nsIMemoryReporter
 {
-  ~FileImplMemoryDataOwnerMemoryReporter() {}
+  ~DOMFileImplMemoryDataOwnerMemoryReporter() {}
 
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCallback,
                             nsISupports *aClosure, bool aAnonymize)
   {
-    typedef FileImplMemory::DataOwner DataOwner;
+    typedef DOMFileImplMemory::DataOwner DataOwner;
 
     StaticMutexAutoLock lock(DataOwner::sDataOwnerMutex);
 
     if (!DataOwner::sDataOwners) {
       return NS_OK;
     }
 
     const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
     size_t smallObjectsTotal = 0;
 
     for (DataOwner *owner = DataOwner::sDataOwners->getFirst();
          owner; owner = owner->getNext()) {
 
-      size_t size = MemoryFileDataOwnerMallocSizeOf(owner->mData);
+      size_t size = DOMMemoryFileDataOwnerMallocSizeOf(owner->mData);
 
       if (size < LARGE_OBJECT_MIN_SIZE) {
         smallObjectsTotal += size;
       } else {
         SHA1Sum sha1;
         sha1.update(owner->mData, owner->mLength);
         uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
         sha1.finish(digest);
@@ -1152,156 +975,88 @@ public:
         aClosure);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     return NS_OK;
   }
 };
 
-NS_IMPL_ISUPPORTS(FileImplMemoryDataOwnerMemoryReporter, nsIMemoryReporter)
+NS_IMPL_ISUPPORTS(DOMFileImplMemoryDataOwnerMemoryReporter, nsIMemoryReporter)
 
 /* static */ void
-FileImplMemory::DataOwner::EnsureMemoryReporterRegistered()
+DOMFileImplMemory::DataOwner::EnsureMemoryReporterRegistered()
 {
   sDataOwnerMutex.AssertCurrentThreadOwns();
   if (sMemoryReporterRegistered) {
     return;
   }
 
-  RegisterStrongMemoryReporter(new FileImplMemoryDataOwnerMemoryReporter());
+  RegisterStrongMemoryReporter(new DOMFileImplMemoryDataOwnerMemoryReporter());
 
   sMemoryReporterRegistered = true;
 }
 
 ////////////////////////////////////////////////////////////////////////////
-// FileImplTemporaryFileBlob implementation
+// DOMFileImplTemporaryFileBlob implementation
 
-NS_IMPL_ISUPPORTS_INHERITED0(FileImplTemporaryFileBlob, FileImpl)
+NS_IMPL_ISUPPORTS_INHERITED0(DOMFileImplTemporaryFileBlob, DOMFileImpl)
 
-already_AddRefed<FileImpl>
-FileImplTemporaryFileBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                                       const nsAString& aContentType,
-                                       ErrorResult& aRv)
+already_AddRefed<DOMFileImpl>
+DOMFileImplTemporaryFileBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
+                                          const nsAString& aContentType)
 {
-  if (aStart + aLength > mLength) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
+  if (aStart + aLength > mLength)
     return nullptr;
-  }
 
-  nsRefPtr<FileImpl> impl =
-    new FileImplTemporaryFileBlob(this, aStart + mStartPos,
-                                  aLength, aContentType);
+  nsRefPtr<DOMFileImpl> impl =
+    new DOMFileImplTemporaryFileBlob(this, aStart + mStartPos, aLength,
+                                     aContentType);
   return impl.forget();
 }
 
 nsresult
-FileImplTemporaryFileBlob::GetInternalStream(nsIInputStream** aStream)
+DOMFileImplTemporaryFileBlob::GetInternalStream(nsIInputStream** aStream)
 {
   nsCOMPtr<nsIInputStream> stream =
     new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength);
   stream.forget(aStream);
   return NS_OK;
 }
 
-////////////////////////////////////////////////////////////////////////////
-// FileList implementation
+} // dom namespace
+} // mozilla namespace
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileList, mFiles)
+////////////////////////////////////////////////////////////////////////////
+// nsDOMFileList implementation
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileList)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsDOMFileList)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFileList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMFileList)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(FileList)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(FileList)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMFileList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMFileList)
 
 JSObject*
-FileList::WrapObject(JSContext *cx)
+nsDOMFileList::WrapObject(JSContext *cx)
 {
   return mozilla::dom::FileListBinding::Wrap(cx, this);
 }
 
 NS_IMETHODIMP
-FileList::GetLength(uint32_t* aLength)
+nsDOMFileList::GetLength(uint32_t* aLength)
 {
   *aLength = Length();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-FileList::Item(uint32_t aIndex, nsIDOMFile **aFile)
-{
-  nsRefPtr<File> file = Item(aIndex);
-  file.forget(aFile);
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobSet implementation
-
-already_AddRefed<File>
-BlobSet::GetBlobInternal(nsISupports* aParent, const nsACString& aContentType)
-{
-  nsRefPtr<File> blob = new File(aParent,
-    new MultipartFileImpl(GetBlobImpls(),
-                          NS_ConvertASCIItoUTF16(aContentType)));
-  return blob.forget();
-}
-
-nsresult
-BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
+nsDOMFileList::Item(uint32_t aIndex, nsIDOMFile **aFile)
 {
-  NS_ENSURE_ARG_POINTER(aData);
-
-  uint64_t offset = mDataLen;
-
-  if (!ExpandBufferSize(aLength))
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  memcpy((char*)mData + offset, aData, aLength);
-  return NS_OK;
-}
-
-nsresult
-BlobSet::AppendString(const nsAString& aString, bool nativeEOL, JSContext* aCx)
-{
-  nsCString utf8Str = NS_ConvertUTF16toUTF8(aString);
-
-  if (nativeEOL) {
-    if (utf8Str.FindChar('\r') != kNotFound) {
-      utf8Str.ReplaceSubstring("\r\n", "\n");
-      utf8Str.ReplaceSubstring("\r", "\n");
-    }
-#ifdef XP_WIN
-    utf8Str.ReplaceSubstring("\n", "\r\n");
-#endif
-  }
-
-  return AppendVoidPtr((void*)utf8Str.Data(),
-                       utf8Str.Length());
-}
-
-nsresult
-BlobSet::AppendBlobImpl(FileImpl* aBlobImpl)
-{
-  NS_ENSURE_ARG_POINTER(aBlobImpl);
-
-  Flush();
-  mBlobImpls.AppendElement(aBlobImpl);
+  NS_IF_ADDREF(*aFile = Item(aIndex));
 
   return NS_OK;
 }
-
-nsresult
-BlobSet::AppendBlobImpls(const nsTArray<nsRefPtr<FileImpl>>& aBlobImpls)
-{
-  Flush();
-  mBlobImpls.AppendElements(aBlobImpls);
-
-  return NS_OK;
-}
-
-} // dom namespace
-} // mozilla namespace
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -3,28 +3,28 @@
  * 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 "nsDOMFileReader.h"
 
 #include "nsContentCID.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
+#include "nsDOMFile.h"
 #include "nsError.h"
 #include "nsIFile.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 
 #include "nsXPCOM.h"
 #include "nsIDOMEventListener.h"
 #include "nsJSEnvironment.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Base64.h"
 #include "mozilla/dom/EncodingUtils.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/FileReaderBinding.h"
 #include "xpcpublic.h"
 #include "nsDOMJSUtils.h"
 
 #include "jsfriendapi.h"
 
 #include "nsITransport.h"
 #include "nsIStreamTransportService.h"
@@ -181,49 +181,45 @@ nsDOMFileReader::GetError(nsISupports** 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aFile, JSContext* aCx)
 {
   NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
   ErrorResult rv;
-  nsRefPtr<File> file = static_cast<File*>(aFile);
-  ReadAsArrayBuffer(aCx, *file, rv);
+  ReadAsArrayBuffer(aCx, aFile, rv);
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::ReadAsBinaryString(nsIDOMBlob* aFile)
 {
   NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
   ErrorResult rv;
-  nsRefPtr<File> file = static_cast<File*>(aFile);
-  ReadAsBinaryString(*file, rv);
+  ReadAsBinaryString(aFile, rv);
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::ReadAsText(nsIDOMBlob* aFile,
                             const nsAString &aCharset)
 {
   NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
   ErrorResult rv;
-  nsRefPtr<File> file = static_cast<File*>(aFile);
-  ReadAsText(*file, aCharset, rv);
+  ReadAsText(aFile, aCharset, rv);
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::ReadAsDataURL(nsIDOMBlob* aFile)
 {
   NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
   ErrorResult rv;
-  nsRefPtr<File> file = static_cast<File*>(aFile);
-  ReadAsDataURL(*file, rv);
+  ReadAsDataURL(aFile, rv);
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsDOMFileReader::Abort()
 {
   ErrorResult rv;
   FileIOObject::Abort(rv);
@@ -365,31 +361,33 @@ nsDOMFileReader::DoReadData(nsIAsyncInpu
   mDataLen += aCount;
   return NS_OK;
 }
 
 // Helper methods
 
 void
 nsDOMFileReader::ReadFileContent(JSContext* aCx,
-                                 File& aFile,
+                                 nsIDOMBlob* aFile,
                                  const nsAString &aCharset,
                                  eDataFormat aDataFormat,
                                  ErrorResult& aRv)
 {
+  MOZ_ASSERT(aFile);
+
   //Implicit abort to clear any other activity going on
   Abort();
   mError = nullptr;
   SetDOMStringToNull(mResult);
   mTransferred = 0;
   mTotal = 0;
   mReadyState = nsIDOMFileReader::EMPTY;
   FreeFileData();
 
-  mFile = &aFile;
+  mFile = aFile;
   mDataFormat = aDataFormat;
   CopyUTF16toUTF8(aCharset, mCharset);
 
   nsresult rv;
 
   nsCOMPtr<nsIStreamTransportService> sts =
     do_GetService(kStreamTransportServiceCID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/content/base/src/nsDOMFileReader.h
+++ b/content/base/src/nsDOMFileReader.h
@@ -14,36 +14,30 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsJSUtils.h"
 #include "nsTArray.h"
 #include "nsIJSNativeInitializer.h"
 #include "prtime.h"
 #include "nsITimer.h"
 #include "nsIAsyncInputStream.h"
 
+#include "nsIDOMFile.h"
 #include "nsIDOMFileReader.h"
 #include "nsIDOMFileList.h"
 #include "nsCOMPtr.h"
 
 #include "FileIOObject.h"
 
-namespace mozilla {
-namespace dom {
-class File;
-}
-}
-
 class nsDOMFileReader : public mozilla::dom::FileIOObject,
                         public nsIDOMFileReader,
                         public nsIInterfaceRequestor,
                         public nsSupportsWeakReference
 {
   typedef mozilla::ErrorResult ErrorResult;
   typedef mozilla::dom::GlobalObject GlobalObject;
-  typedef mozilla::dom::File File;
 public:
   nsDOMFileReader();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOMFILEREADER
 
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper)
@@ -63,28 +57,31 @@ public:
   {
     return GetOwner();
   }
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // WebIDL
   static already_AddRefed<nsDOMFileReader>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
-  void ReadAsArrayBuffer(JSContext* aCx, File& aBlob, ErrorResult& aRv)
+  void ReadAsArrayBuffer(JSContext* aCx, nsIDOMBlob* aBlob, ErrorResult& aRv)
   {
+    MOZ_ASSERT(aBlob);
     ReadFileContent(aCx, aBlob, EmptyString(), FILE_AS_ARRAYBUFFER, aRv);
   }
 
-  void ReadAsText(File& aBlob, const nsAString& aLabel, ErrorResult& aRv)
+  void ReadAsText(nsIDOMBlob* aBlob, const nsAString& aLabel, ErrorResult& aRv)
   {
+    MOZ_ASSERT(aBlob);
     ReadFileContent(nullptr, aBlob, aLabel, FILE_AS_TEXT, aRv);
   }
 
-  void ReadAsDataURL(File& aBlob, ErrorResult& aRv)
+  void ReadAsDataURL(nsIDOMBlob* aBlob, ErrorResult& aRv)
   {
+    MOZ_ASSERT(aBlob);
     ReadFileContent(nullptr, aBlob, EmptyString(), FILE_AS_DATAURL, aRv);
   }
 
   using FileIOObject::Abort;
 
   // Inherited ReadyState().
 
   void GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
@@ -97,18 +94,19 @@ public:
   using FileIOObject::SetOnprogress;
   IMPL_EVENT_HANDLER(load)
   using FileIOObject::GetOnabort;
   using FileIOObject::SetOnabort;
   using FileIOObject::GetOnerror;
   using FileIOObject::SetOnerror;
   IMPL_EVENT_HANDLER(loadend)
 
-  void ReadAsBinaryString(File& aBlob, ErrorResult& aRv)
+  void ReadAsBinaryString(nsIDOMBlob* aBlob, ErrorResult& aRv)
   {
+    MOZ_ASSERT(aBlob);
     ReadFileContent(nullptr, aBlob, EmptyString(), FILE_AS_BINARY, aRv);
   }
 
 
   nsresult Init();
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMFileReader,
                                                          FileIOObject)
@@ -119,17 +117,17 @@ protected:
 
   enum eDataFormat {
     FILE_AS_ARRAYBUFFER,
     FILE_AS_BINARY,
     FILE_AS_TEXT,
     FILE_AS_DATAURL
   };
 
-  void ReadFileContent(JSContext* aCx, File& aBlob,
+  void ReadFileContent(JSContext* aCx, nsIDOMBlob* aBlob,
                        const nsAString &aCharset, eDataFormat aDataFormat,
                        ErrorResult& aRv);
   nsresult GetAsText(nsIDOMBlob *aFile, const nsACString &aCharset,
                      const char *aFileData, uint32_t aDataLen, nsAString &aResult);
   nsresult GetAsDataURL(nsIDOMBlob *aFile, const char *aFileData, uint32_t aDataLen, nsAString &aResult);
 
   void FreeFileData() {
     moz_free(mFileData);
--- a/content/base/src/nsFormData.cpp
+++ b/content/base/src/nsFormData.cpp
@@ -1,60 +1,34 @@
 /* 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 "nsFormData.h"
 #include "nsIVariant.h"
 #include "nsIInputStream.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/File.h"
+#include "nsIDOMFile.h"
 #include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/FormDataBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsFormData::nsFormData(nsISupports* aOwner)
   : nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"), nullptr)
   , mOwner(aOwner)
 {
 }
 
 // -------------------------------------------------------------------------
 // nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormData)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormData)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
-
-  for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
-    ImplCycleCollectionUnlink(tmp->mFormData[i].fileValue);
-  }
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormData)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
-
-  for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
-   ImplCycleCollectionTraverse(cb,tmp->mFormData[i].fileValue,
-                               "mFormData[i].fileValue", 0);
-  }
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsFormData)
-
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFormData, mOwner)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormData)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormData)
-
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFormData)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMFormData)
   NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFormData)
 NS_INTERFACE_MAP_END
 
 // -------------------------------------------------------------------------
@@ -69,26 +43,26 @@ nsFormData::GetEncodedSubmission(nsIURI*
 
 void
 nsFormData::Append(const nsAString& aName, const nsAString& aValue)
 {
   AddNameValuePair(aName, aValue);
 }
 
 void
-nsFormData::Append(const nsAString& aName, File& aBlob,
+nsFormData::Append(const nsAString& aName, nsIDOMBlob* aBlob,
                    const Optional<nsAString>& aFilename)
 {
   nsString filename;
   if (aFilename.WasPassed()) {
     filename = aFilename.Value();
   } else {
     filename.SetIsVoid(true);
   }
-  AddNameFilePair(aName, &aBlob, filename);
+  AddNameFilePair(aName, aBlob, filename);
 }
 
 // -------------------------------------------------------------------------
 // nsIDOMFormData
 
 NS_IMETHODIMP
 nsFormData::Append(const nsAString& aName, nsIVariant* aValue)
 {
@@ -101,20 +75,19 @@ nsFormData::Append(const nsAString& aNam
     nsCOMPtr<nsISupports> supports;
     nsID *iid;
     rv = aValue->GetAsInterface(&iid, getter_AddRefs(supports));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsMemory::Free(iid);
 
     nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports);
-    nsRefPtr<File> blob = static_cast<File*>(domBlob.get());
     if (domBlob) {
       Optional<nsAString> temp;
-      Append(aName, *blob, temp);
+      Append(aName, domBlob, temp);
       return NS_OK;
     }
   }
 
   char16_t* stringData = nullptr;
   uint32_t stringLen = 0;
   rv = aValue->GetAsWStringWithSize(&stringLen, &stringData);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/nsFormData.h
+++ b/content/base/src/nsFormData.h
@@ -1,29 +1,31 @@
 /* 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 nsFormData_h__
 #define nsFormData_h__
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMFile.h"
 #include "nsIDOMFormData.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsFormSubmission.h"
 #include "nsWrapperCache.h"
 #include "nsTArray.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 
+class nsIDOMFile;
+
 namespace mozilla {
 class ErrorResult;
 
 namespace dom {
-class File;
 class HTMLFormElement;
 class GlobalObject;
 } // namespace dom
 } // namespace mozilla
 
 class nsFormData MOZ_FINAL : public nsIDOMFormData,
                              public nsIXHRSendable,
                              public nsFormSubmission,
@@ -50,17 +52,17 @@ public:
   {
     return mOwner;
   }
   static already_AddRefed<nsFormData>
   Constructor(const mozilla::dom::GlobalObject& aGlobal,
               const mozilla::dom::Optional<mozilla::dom::NonNull<mozilla::dom::HTMLFormElement> >& aFormElement,
               mozilla::ErrorResult& aRv);
   void Append(const nsAString& aName, const nsAString& aValue);
-  void Append(const nsAString& aName, mozilla::dom::File& aBlob,
+  void Append(const nsAString& aName, nsIDOMBlob* aBlob,
               const mozilla::dom::Optional<nsAString>& aFilename);
 
   // nsFormSubmission
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream) MOZ_OVERRIDE;
   virtual nsresult AddNameValuePair(const nsAString& aName,
                                     const nsAString& aValue) MOZ_OVERRIDE
   {
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -22,20 +22,20 @@
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIMemoryReporter.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIDOMClassInfo.h"
+#include "nsIDOMFile.h"
 #include "xpcpublic.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/Preferences.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/nsIContentParent.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/StructuredCloneUtils.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "JavaScriptChild.h"
 #include "JavaScriptParent.h"
@@ -199,17 +199,17 @@ template<ActorFlavorEnum Flavor>
 static bool
 BuildClonedMessageData(typename BlobTraits<Flavor>::ConcreteContentManagerType* aManager,
                        const StructuredCloneData& aData,
                        ClonedMessageData& aClonedData)
 {
   SerializedStructuredCloneBuffer& buffer = aClonedData.data();
   buffer.data = aData.mData;
   buffer.dataLength = aData.mDataLength;
-  const nsTArray<nsRefPtr<File>>& blobs = aData.mClosure.mBlobs;
+  const nsTArray<nsCOMPtr<nsIDOMBlob> >& blobs = aData.mClosure.mBlobs;
   if (!blobs.IsEmpty()) {
     typedef typename BlobTraits<Flavor>::ProtocolType ProtocolType;
     InfallibleTArray<ProtocolType*>& blobList = DataBlobs<Flavor>::Blobs(aClonedData);
     uint32_t length = blobs.Length();
     blobList.SetCapacity(length);
     for (uint32_t i = 0; i < length; ++i) {
       typename BlobTraits<Flavor>::BlobType* protocolActor =
         aManager->GetOrCreateActorForBlob(blobs[i]);
@@ -250,23 +250,18 @@ UnpackClonedMessageData(const ClonedMess
   cloneData.mDataLength = buffer.dataLength;
   if (!blobs.IsEmpty()) {
     uint32_t length = blobs.Length();
     cloneData.mClosure.mBlobs.SetCapacity(length);
     for (uint32_t i = 0; i < length; ++i) {
       auto* blob =
         static_cast<typename BlobTraits<Flavor>::BlobType*>(blobs[i]);
       MOZ_ASSERT(blob);
-
-      nsRefPtr<FileImpl> blobImpl = blob->GetBlobImpl();
-      MOZ_ASSERT(blobImpl);
-
-      // This object will be duplicated with a correct parent before being
-      // exposed to JS.
-      nsRefPtr<File> domBlob = new File(nullptr, blobImpl);
+      nsCOMPtr<nsIDOMBlob> domBlob = blob->GetBlob();
+      MOZ_ASSERT(domBlob);
       cloneData.mClosure.mBlobs.AppendElement(domBlob);
     }
   }
   return cloneData;
 }
 
 StructuredCloneData
 mozilla::dom::ipc::UnpackClonedMessageDataForParent(const ClonedMessageData& aData)
--- a/content/base/src/nsHostObjectProtocolHandler.cpp
+++ b/content/base/src/nsHostObjectProtocolHandler.cpp
@@ -5,25 +5,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsHostObjectProtocolHandler.h"
 #include "nsHostObjectURI.h"
 #include "nsError.h"
 #include "nsClassHashtable.h"
 #include "nsNetUtil.h"
 #include "nsIPrincipal.h"
+#include "nsDOMFile.h"
 #include "DOMMediaStream.h"
 #include "mozilla/dom/MediaSource.h"
 #include "nsIMemoryReporter.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/LoadInfo.h"
 
-using mozilla::dom::FileImpl;
-using mozilla::ErrorResult;
+using mozilla::dom::DOMFileImpl;
 using mozilla::LoadInfo;
 
 // -----------------------------------------------------------------------
 // Hash table
 struct DataInfo
 {
   // mObject is expected to be an nsIDOMBlob, DOMMediaStream, or MediaSource
   nsCOMPtr<nsISupports> mObject;
@@ -492,55 +491,55 @@ nsHostObjectProtocolHandler::NewChannel(
   uri->GetSpec(spec);
 
   DataInfo* info = GetDataInfo(spec);
 
   if (!info) {
     return NS_ERROR_DOM_BAD_URI;
   }
 
-  nsCOMPtr<PIFileImpl> blobImpl = do_QueryInterface(info->mObject);
+  nsCOMPtr<PIDOMFileImpl> blobImpl = do_QueryInterface(info->mObject);
   if (!blobImpl) {
     return NS_ERROR_DOM_BAD_URI;
   }
 
 #ifdef DEBUG
   {
     nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
     nsCOMPtr<nsIPrincipal> principal;
     uriPrinc->GetPrincipal(getter_AddRefs(principal));
     NS_ASSERTION(info->mPrincipal == principal, "Wrong principal!");
   }
 #endif
 
-  FileImpl* blob = static_cast<FileImpl*>(blobImpl.get());
+  DOMFileImpl* blob = static_cast<DOMFileImpl*>(blobImpl.get());
   nsCOMPtr<nsIInputStream> stream;
   nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
                                 uri,
                                 stream);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsString type;
-  blob->GetType(type);
+  rv = blob->GetType(type);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   if (blob->IsFile()) {
     nsString filename;
-    blob->GetName(filename);
+    rv = blob->GetName(filename);
+    NS_ENSURE_SUCCESS(rv, rv);
     channel->SetContentDispositionFilename(filename);
   }
 
-  ErrorResult error;
-  uint64_t size = blob->GetSize(error);
-  if (NS_WARN_IF(error.Failed())) {
-    return error.ErrorCode();
-  }
+  uint64_t size;
+  rv = blob->GetSize(&size);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoadInfo> loadInfo =
     new mozilla::LoadInfo(info->mPrincipal,
                           nullptr,
                           nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
                           nsIContentPolicy::TYPE_OTHER);
   channel->SetLoadInfo(loadInfo);
   channel->SetOriginalURI(uri);
@@ -591,22 +590,22 @@ nsFontTableProtocolHandler::GetScheme(ns
 
 nsresult
 NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
 {
   NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs");
 
   *aStream = nullptr;
 
-  nsCOMPtr<PIFileImpl> blobImpl = do_QueryInterface(GetDataObject(aURI));
+  nsCOMPtr<PIDOMFileImpl> blobImpl = do_QueryInterface(GetDataObject(aURI));
   if (!blobImpl) {
     return NS_ERROR_DOM_BAD_URI;
   }
 
-  FileImpl* blob = static_cast<FileImpl*>(blobImpl.get());
+  DOMFileImpl* blob = static_cast<DOMFileImpl*>(blobImpl.get());
   return blob->GetInternalStream(aStream);
 }
 
 nsresult
 NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream)
 {
   NS_ASSERTION(IsMediaStreamURI(aURI), "Only call this with mediastream URIs");
 
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -5,23 +5,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsXMLHttpRequest.h"
 
 #ifndef XP_WIN
 #include <unistd.h>
 #endif
 #include "mozilla/ArrayUtils.h"
-#include "mozilla/dom/BlobSet.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/XMLHttpRequestUploadBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/MemoryReporting.h"
+#include "nsDOMBlobBuilder.h"
 #include "nsIDOMDocument.h"
 #include "mozilla/dom/ProgressEvent.h"
 #include "nsIJARChannel.h"
 #include "nsIJARURI.h"
 #include "nsLayoutCID.h"
 #include "nsReadableUtils.h"
 
 #include "nsIURI.h"
@@ -52,16 +51,17 @@
 #include "nsIPromptFactory.h"
 #include "nsIWindowWatcher.h"
 #include "nsIConsoleService.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "nsStringBuffer.h"
+#include "nsDOMFile.h"
 #include "nsIFileChannel.h"
 #include "mozilla/Telemetry.h"
 #include "jsfriendapi.h"
 #include "GeckoProfiler.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "nsIUnicodeDecoder.h"
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "mozilla/Attributes.h"
@@ -779,34 +779,33 @@ nsXMLHttpRequest::CreatePartialBlob()
 {
   if (mDOMFile) {
     // Use progress info to determine whether load is complete, but use
     // mDataAvailable to ensure a slice is created based on the uncompressed
     // data count.
     if (mLoadTotal == mLoadTransferred) {
       mResponseBlob = mDOMFile;
     } else {
-      ErrorResult rv;
-      mResponseBlob = mDOMFile->CreateSlice(0, mDataAvailable,
-                                            EmptyString(), rv);
+      mResponseBlob =
+        mDOMFile->CreateSlice(0, mDataAvailable, EmptyString());
     }
     return;
   }
 
   // mBlobSet can be null if the request has been canceled
   if (!mBlobSet) {
     return;
   }
 
   nsAutoCString contentType;
   if (mLoadTotal == mLoadTransferred) {
     mChannel->GetContentType(contentType);
   }
 
-  mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType);
+  mResponseBlob = mBlobSet->GetBlobInternal(contentType);
 }
 
 /* attribute AString responseType; */
 NS_IMETHODIMP nsXMLHttpRequest::GetResponseType(nsAString& aResponseType)
 {
   switch (mResponseType) {
   case XML_HTTP_RESPONSE_TYPE_DEFAULT:
     aResponseType.Truncate();
@@ -1003,17 +1002,17 @@ nsXMLHttpRequest::GetResponse(JSContext*
       }
     }
 
     if (!mResponseBlob) {
       aResponse.setNull();
       return;
     }
 
-    WrapNewBindingObject(aCx, mResponseBlob, aResponse);
+    aRv = nsContentUtils::WrapNative(aCx, mResponseBlob, aResponse);
     return;
   }
   case XML_HTTP_RESPONSE_TYPE_DOCUMENT:
   {
     if (!(mState & XML_HTTP_REQUEST_DONE) || !mResponseXML) {
       aResponse.setNull();
       return;
     }
@@ -1893,18 +1892,19 @@ bool nsXMLHttpRequest::CreateDOMFile(nsI
   }
 
   if (!file)
     return false;
 
   nsAutoCString contentType;
   mChannel->GetContentType(contentType);
 
-  mDOMFile = File::CreateFromFile(GetOwner(), file, EmptyString(),
-                                  NS_ConvertASCIItoUTF16(contentType));
+  mDOMFile =
+    DOMFile::CreateFromFile(file, EmptyString(),
+                            NS_ConvertASCIItoUTF16(contentType));
 
   mBlobSet = nullptr;
   NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty");
   return true;
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::OnDataAvailable(nsIRequest *request,
@@ -2238,17 +2238,17 @@ nsXMLHttpRequest::OnStopRequest(nsIReque
       // and if the response length is zero.
       if (!mBlobSet) {
         mBlobSet = new BlobSet();
       }
       // Smaller files may be written in cache map instead of separate files.
       // Also, no-store response cannot be written in persistent cache.
       nsAutoCString contentType;
       mChannel->GetContentType(contentType);
-      mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType);
+      mResponseBlob = mBlobSet->GetBlobInternal(contentType);
       mBlobSet = nullptr;
     }
     NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty");
     NS_ASSERTION(mResponseText.IsEmpty(), "mResponseText should be empty");
   } else if (NS_SUCCEEDED(status) &&
              ((mResponseType == XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER &&
                !mIsMappedArrayBuffer) ||
               mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER)) {
@@ -2613,18 +2613,17 @@ nsXMLHttpRequest::GetRequestBody(nsIVari
       const ArrayBufferView* view = value.mArrayBufferView;
       view->ComputeLengthAndData();
       return ::GetRequestBody(view->Data(), view->Length(), aResult,
                               aContentLength, aContentType, aCharset);
     }
     case nsXMLHttpRequest::RequestBody::Blob:
     {
       nsresult rv;
-      nsCOMPtr<nsIDOMBlob> blob = value.mBlob;
-      nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(blob, &rv);
+      nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(value.mBlob, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       return ::GetRequestBody(sendable, aResult, aContentLength, aContentType, aCharset);
     }
     case nsXMLHttpRequest::RequestBody::Document:
     {
       nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(value.mDocument);
       return ::GetRequestBody(document, aResult, aContentLength, aContentType, aCharset);
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -36,27 +36,28 @@
 
 #ifdef Status
 /* Xlib headers insist on this for some reason... Nuke it because
    it'll override our member name */
 #undef Status
 #endif
 
 class AsyncVerifyRedirectCallbackForwarder;
+class BlobSet;
+class nsDOMFile;
 class nsFormData;
 class nsIJARChannel;
 class nsILoadGroup;
 class nsIUnicodeDecoder;
 class nsIJSID;
 
 namespace mozilla {
 
 namespace dom {
-class BlobSet;
-class File;
+class DOMFile;
 }
 
 // A helper for building up an ArrayBuffer object's data
 // before creating the ArrayBuffer itself.  Will do doubling
 // based reallocation, up to an optional maximum growth given.
 //
 // When all the data has been appended, call getArrayBuffer,
 // passing in the JSContext* for which the ArrayBuffer object
@@ -344,19 +345,19 @@ private:
     explicit RequestBody(const mozilla::dom::ArrayBuffer* aArrayBuffer) : mType(ArrayBuffer)
     {
       mValue.mArrayBuffer = aArrayBuffer;
     }
     explicit RequestBody(const mozilla::dom::ArrayBufferView* aArrayBufferView) : mType(ArrayBufferView)
     {
       mValue.mArrayBufferView = aArrayBufferView;
     }
-    explicit RequestBody(mozilla::dom::File& aBlob) : mType(Blob)
+    explicit RequestBody(nsIDOMBlob* aBlob) : mType(Blob)
     {
-      mValue.mBlob = &aBlob;
+      mValue.mBlob = aBlob;
     }
     explicit RequestBody(nsIDocument* aDocument) : mType(Document)
     {
       mValue.mDocument = aDocument;
     }
     explicit RequestBody(const nsAString& aString) : mType(DOMString)
     {
       mValue.mString = &aString;
@@ -378,17 +379,17 @@ private:
       Document,
       DOMString,
       FormData,
       InputStream
     };
     union Value {
       const mozilla::dom::ArrayBuffer* mArrayBuffer;
       const mozilla::dom::ArrayBufferView* mArrayBufferView;
-      mozilla::dom::File* mBlob;
+      nsIDOMBlob* mBlob;
       nsIDocument* mDocument;
       const nsAString* mString;
       nsFormData* mFormData;
       nsIInputStream* mStream;
     };
 
     Type GetType() const
     {
@@ -434,18 +435,19 @@ public:
   {
     aRv = Send(RequestBody(&aArrayBuffer));
   }
   void Send(const mozilla::dom::ArrayBufferView& aArrayBufferView,
             ErrorResult& aRv)
   {
     aRv = Send(RequestBody(&aArrayBufferView));
   }
-  void Send(mozilla::dom::File& aBlob, ErrorResult& aRv)
+  void Send(nsIDOMBlob* aBlob, ErrorResult& aRv)
   {
+    NS_ASSERTION(aBlob, "Null should go to string version");
     aRv = Send(RequestBody(aBlob));
   }
   void Send(nsIDocument& aDoc, ErrorResult& aRv)
   {
     aRv = Send(RequestBody(&aDoc));
   }
   void Send(const nsAString& aString, ErrorResult& aRv)
   {
@@ -665,23 +667,23 @@ protected:
   };
 
   void SetResponseType(nsXMLHttpRequest::ResponseTypeEnum aType, ErrorResult& aRv);
 
   ResponseTypeEnum mResponseType;
 
   // It is either a cached blob-response from the last call to GetResponse,
   // but is also explicitly set in OnStopRequest.
-  nsRefPtr<mozilla::dom::File> mResponseBlob;
+  nsCOMPtr<nsIDOMBlob> mResponseBlob;
   // Non-null only when we are able to get a os-file representation of the
   // response, i.e. when loading from a file.
-  nsRefPtr<mozilla::dom::File> mDOMFile;
+  nsRefPtr<mozilla::dom::DOMFile> mDOMFile;
   // We stream data to mBlobSet when response type is "blob" or "moz-blob"
   // and mDOMFile is null.
-  nsAutoPtr<mozilla::dom::BlobSet> mBlobSet;
+  nsAutoPtr<BlobSet> mBlobSet;
 
   nsString mOverrideMimeType;
 
   /**
    * The notification callbacks the channel had when Send() was
    * called.  We want to forward things here as needed.
    */
   nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
--- a/content/base/test/chrome/test_bug914381.html
+++ b/content/base/test/chrome/test_bug914381.html
@@ -28,21 +28,21 @@ function createFileWithData(fileData) {
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
                  0666, 0);
   outStream.write(fileData, fileData.length);
   outStream.close();
 
   return testFile;
 }
 
-/** Test for Bug 914381. File's created in JS using an nsIFile should allow mozGetFullPathInternal calls to succeed **/
+/** Test for Bug 914381. DOMFile's created in JS using an nsIFile should allow mozGetFullPathInternal calls to succeed **/
 var file = createFileWithData("Test bug 914381");
-var f = new File(file);
+var f = File(file);
 is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
 is(f.mozFullPath, file.path, "mozFullPath returns path if created with nsIFile");
 
-f = new File(file.path);
+f = File(file.path);
 is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
 is(f.mozFullPath, "", "mozFullPath returns blank if created with a string");
 </script>
 </pre>
 </body>
 </html>
--- a/content/base/test/test_blobconstructor.html
+++ b/content/base/test/test_blobconstructor.html
@@ -15,75 +15,75 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript;version=1.7">
 "use strict";
 /** Test for Bug 721569 **/
-var blob = new Blob();
+var blob = Blob();
 ok(blob, "Blob should exist");
 
 ok(blob.size !== undefined, "Blob should have a size property");
 ok(blob.type !== undefined, "Blob should have a type property");
 ok(blob.slice, "Blob should have a slice method");
 
-blob = new Blob([], {type: null});
+blob = Blob([], {type: null});
 ok(blob, "Blob should exist");
 is(blob.type, "null", "Blob type should be stringified");
 
-blob = new Blob([], {type: undefined});
+blob = Blob([], {type: undefined});
 ok(blob, "Blob should exist");
 is(blob.type, "", "Blob type should be treated as missing");
 
 try {
-blob = new Blob([]);
+blob = Blob([]);
 ok(true, "an empty blobParts argument should not throw");
 } catch(e) {
 ok(false, "NOT REACHED");
 }
 
 try {
-blob = new Blob(null);
+blob = Blob(null);
 ok(false, "NOT REACHED");
 } catch(e) {
 ok(true, "a null blobParts member should throw");
 }
 
 try {
-blob = new Blob([], null);
+blob = Blob([], null);
 ok(true, "a null options member should not throw");
 } catch(e) {
 ok(false, "NOT REACHED");
 }
 
 try {
-blob = new Blob([], undefined);
+blob = Blob([], undefined);
 ok(true, "an undefined options member should not throw");
 } catch(e) {
 ok(false, "NOT REACHED");
 }
 
 try {
-blob = new Blob([], false);
+blob = Blob([], false);
 ok(false, "NOT REACHED");
 } catch(e) {
 ok(true, "a boolean options member should throw");
 }
 
 try {
-blob = new Blob([], 0);
+blob = Blob([], 0);
 ok(false, "NOT REACHED");
 } catch(e) {
 ok(true, "a numeric options member should throw");
 }
 
 try {
-blob = new Blob([], "");
+blob = Blob([], "");
 ok(false, "NOT REACHED");
 } catch(e) {
 ok(true, "a string options member should throw");
 }
 
 /** Test for dictionary initialization order **/
 (function() {
   var o = {};
@@ -95,23 +95,23 @@ ok(true, "a string options member should
   }
   ["type", "endings"].forEach(function(n) {
     Object.defineProperty(o, n, { get: add_to_called.bind(null, n) });
   });
   var b = new Blob([], o);
   is(JSON.stringify(called), JSON.stringify(["endings", "type"]), "dictionary members should be get in lexicographical order");
 })();
 
-let blob1 = new Blob(["squiggle"]);
+let blob1 = Blob(["squiggle"]);
 ok(blob1 instanceof Blob, "Blob constructor should produce Blobs");
 ok(!(blob1 instanceof File), "Blob constructor should not produce Files");
 is(blob1.type, "", "Blob constructor with no options should return Blob with empty type");
 is(blob1.size, 8, "Blob constructor should return Blob with correct size");
 
-let blob2 = new Blob(["steak"], {type: "content/type"});
+let blob2 = Blob(["steak"], {type: "content/type"});
 ok(blob2 instanceof Blob, "Blob constructor should produce Blobs");
 ok(!(blob2 instanceof File), "Blob constructor should not produce Files");
 is(blob2.type, "content/type", "Blob constructor with a type option should return Blob with the type");
 is(blob2.size, 5, "Blob constructor should return Blob with correct size");
 
 
 let aB = new ArrayBuffer(16);
 var int8View = new Int8Array(aB);
--- a/content/base/test/test_bug403852.html
+++ b/content/base/test/test_bug403852.html
@@ -8,16 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=403852">Mozilla Bug 403852</a>
 <p id="display">
   <input id="fileList" type="file"></input>
+  <canvas id="canvas"></canvas>
 </p>
 <div id="content" style="display: none">
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 var testFile = SpecialPowers.Services.dirsvc.get("ProfD", SpecialPowers.Ci.nsIFile);
@@ -31,23 +32,19 @@ var domFile = fileList.files[0];
 
 is(domFile.name, "prefs.js", "fileName should be prefs.js");
 
 ok("lastModifiedDate" in domFile, "lastModifiedDate must be present");
 
 var d = new Date(testFile.lastModifiedTime);
 ok(d.getTime() == domFile.lastModifiedDate.getTime(), "lastModifiedDate should be the same.");
 
-var x = new Date();
+var cf = document.getElementById("canvas").mozGetAsFile("canvFile");
 
-// In our implementation of File object, lastModifiedDate is unknown only for new objects.
-// Using canvas or input[type=file] elements, we 'often' have a valid lastModifiedDate values.
-// For canvas we use memory files and the lastModifiedDate is now().
-var f = new File([new Blob(['test'], {type: 'text/plain'})], "test-name");
-
-var y = f.lastModifiedDate;
+var x = new Date();
+var y = cf.lastModifiedDate;
 var z = new Date();
 
 ok((x.getTime() <= y.getTime()) && (y.getTime() <= z.getTime()), "lastModifiedDate of file which does not have last modified date should be current time");
 
 </script>
 </pre>
 </body> </html>
--- a/content/html/content/public/HTMLCanvasElement.h
+++ b/content/html/content/public/HTMLCanvasElement.h
@@ -11,31 +11,31 @@
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsSize.h"
 #include "nsError.h"
 
 #include "mozilla/gfx/Rect.h"
 
 class nsICanvasRenderingContextInternal;
+class nsIDOMFile;
 class nsITimerCallback;
 
 namespace mozilla {
 
 namespace layers {
 class CanvasLayer;
 class LayerManager;
 }
 namespace gfx {
 class SourceSurface;
 }
 
 namespace dom {
 
-class File;
 class FileCallback;
 class HTMLCanvasPrintState;
 class PrintCallback;
 
 class HTMLCanvasElement MOZ_FINAL : public nsGenericHTMLElement,
                                     public nsIDOMHTMLCanvasElement
 {
   enum {
@@ -97,19 +97,19 @@ public:
   bool MozOpaque() const
   {
     return GetBoolAttr(nsGkAtoms::moz_opaque);
   }
   void SetMozOpaque(bool aValue, ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
   }
-  already_AddRefed<File> MozGetAsFile(const nsAString& aName,
-                                      const nsAString& aType,
-                                      ErrorResult& aRv);
+  already_AddRefed<nsIDOMFile> MozGetAsFile(const nsAString& aName,
+                                            const nsAString& aType,
+                                            ErrorResult& aRv);
   already_AddRefed<nsISupports> MozGetIPCContext(const nsAString& aContextId,
                                                  ErrorResult& aRv)
   {
     nsCOMPtr<nsISupports> context;
     aRv = MozGetIPCContext(aContextId, getter_AddRefs(context));
     return context.forget();
   }
   void MozFetchAsStream(nsIInputStreamCallback* aCallback,
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -7,28 +7,28 @@
 
 #include "ImageEncoder.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "Layers.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/HTMLCanvasElementBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
+#include "nsDOMFile.h"
 #include "nsDOMJSUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsITimer.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsIXPConnect.h"
 #include "nsJSUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsMathUtils.h"
@@ -544,31 +544,29 @@ HTMLCanvasElement::ToBlob(JSContext* aCx
   class EncodeCallback : public EncodeCompleteCallback
   {
   public:
     EncodeCallback(nsIGlobalObject* aGlobal, FileCallback* aCallback)
       : mGlobal(aGlobal)
       , mFileCallback(aCallback) {}
 
     // This is called on main thread.
-    nsresult ReceiveBlob(already_AddRefed<File> aBlob)
+    nsresult ReceiveBlob(already_AddRefed<DOMFile> aBlob)
     {
-      nsRefPtr<File> blob = aBlob;
+      nsRefPtr<DOMFile> blob = aBlob;
       uint64_t size;
       nsresult rv = blob->GetSize(&size);
       if (NS_SUCCEEDED(rv)) {
         AutoJSAPI jsapi;
         jsapi.Init(mGlobal);
         JS_updateMallocCounter(jsapi.cx(), size);
       }
 
-      nsRefPtr<File> newBlob = new File(mGlobal, blob->Impl());
-
       mozilla::ErrorResult error;
-      mFileCallback->Call(*newBlob, error);
+      mFileCallback->Call(blob, error);
 
       mGlobal = nullptr;
       mFileCallback = nullptr;
 
       return error.ErrorCode();
     }
 
     nsCOMPtr<nsIGlobalObject> mGlobal;
@@ -582,25 +580,24 @@ HTMLCanvasElement::ToBlob(JSContext* aCx
                                        params,
                                        usingCustomParseOptions,
                                        imageBuffer,
                                        format,
                                        GetSize(),
                                        callback);
 }
 
-already_AddRefed<File>
+already_AddRefed<nsIDOMFile>
 HTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                 const nsAString& aType,
                                 ErrorResult& aRv)
 {
   nsCOMPtr<nsIDOMFile> file;
   aRv = MozGetAsFile(aName, aType, getter_AddRefs(file));
-  nsRefPtr<File> tmp = static_cast<File*>(file.get());
-  return tmp.forget();
+  return file.forget();
 }
 
 NS_IMETHODIMP
 HTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                 const nsAString& aType,
                                 nsIDOMFile** aResult)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eMozGetAsFile);
@@ -633,22 +630,20 @@ HTMLCanvasElement::MozGetAsFileImpl(cons
   rv = NS_ReadInputStreamToBuffer(stream, &imgData, (uint32_t)imgSize);
   NS_ENSURE_SUCCESS(rv, rv);
 
   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 =
-    File::CreateMemoryFile(win, imgData, (uint32_t)imgSize, aName, type,
-                           PR_Now());
+  // The DOMFile takes ownership of the buffer
+  nsRefPtr<DOMFile> file =
+    DOMFile::CreateMemoryFile(imgData, (uint32_t)imgSize, aName, type,
+                              PR_Now());
 
   file.forget(aResult);
   return NS_OK;
 }
 
 nsresult
 HTMLCanvasElement::GetContextHelper(const nsAString& aContextId,
                                     nsICanvasRenderingContextInternal **aContext)
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -68,19 +68,19 @@
 
 #include "nsRuleData.h"
 #include <algorithm>
 
 // input type=radio
 #include "nsIRadioGroupContainer.h"
 
 // input type=file
-#include "mozilla/dom/File.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
+#include "nsDOMFile.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIContentPrefService.h"
 #include "nsIMIMEService.h"
 #include "nsIObserverService.h"
 #include "nsIPopupWindowManager.h"
 #include "nsGlobalWindow.h"
 
 // input type=image
@@ -231,36 +231,36 @@ class HTMLInputElementState MOZ_FINAL : 
     const nsString& GetValue() {
       return mValue;
     }
 
     void SetValue(const nsAString& aValue) {
       mValue = aValue;
     }
 
-    const nsTArray<nsRefPtr<File>>& GetFiles() {
+    const nsTArray<nsCOMPtr<nsIDOMFile> >& GetFiles() {
       return mFiles;
     }
 
-    void SetFiles(const nsTArray<nsRefPtr<File>>& aFiles) {
+    void SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles) {
       mFiles.Clear();
       mFiles.AppendElements(aFiles);
     }
 
     HTMLInputElementState()
       : mValue()
       , mChecked(false)
       , mCheckedSet(false)
     {};
 
   protected:
     ~HTMLInputElementState() {}
 
     nsString mValue;
-    nsTArray<nsRefPtr<File>> mFiles;
+    nsTArray<nsCOMPtr<nsIDOMFile> > mFiles;
     bool mChecked;
     bool mCheckedSet;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(HTMLInputElementState, NS_INPUT_ELEMENT_STATE_IID)
 
 NS_IMPL_ISUPPORTS(HTMLInputElementState, HTMLInputElementState)
 
@@ -311,17 +311,17 @@ UploadLastDir::ContentPrefCallback::Hand
   // HandleCompletion is always called (even with HandleError was called),
   // so we don't need to do anything special here.
   return NS_OK;
 }
 
 namespace {
 
 /**
- * This enumerator returns File objects after wrapping a single
+ * This enumerator returns nsDOMFileFile objects after wrapping a single
  * nsIFile representing a directory. It enumerates the files under that
  * directory and its subdirectories as a flat list of files, ignoring/skipping
  * over symbolic links.
  *
  * The enumeration involves I/O, so this class must NOT be used on the main
  * thread or else the main thread could be blocked for a very long time.
  *
  * This enumerator does not walk the directory tree breadth-first, but it also
@@ -369,32 +369,31 @@ public:
   {
     MOZ_ASSERT(!NS_IsMainThread(),
                "Walking the directory tree involves I/O, so using this "
                "enumerator can block a thread for a long time!");
 
     if (!mNextFile) {
       return NS_ERROR_FAILURE;
     }
-
-    // The parent for this object will be set on the main thread.
-    nsRefPtr<File> domFile = File::CreateFromFile(nullptr, mNextFile);
+    nsRefPtr<DOMFile> domFile = DOMFile::CreateFromFile(mNextFile);
     nsCString relDescriptor;
     nsresult rv =
       mNextFile->GetRelativeDescriptor(mTopDirsParent, relDescriptor);
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ConvertUTF8toUTF16 path(relDescriptor);
     nsAutoString leafName;
     mNextFile->GetLeafName(leafName);
     MOZ_ASSERT(leafName.Length() <= path.Length());
     int32_t length = path.Length() - leafName.Length();
     MOZ_ASSERT(length >= 0);
     if (length > 0) {
       // Note that we leave the trailing "/" on the path.
-      FileImplFile* fileImpl = static_cast<FileImplFile*>(domFile->Impl());
+      DOMFileImplFile* fileImpl =
+        static_cast<DOMFileImplFile*>(domFile->Impl());
       MOZ_ASSERT(fileImpl);
       fileImpl->SetPath(Substring(path, 0, uint32_t(length)));
     }
     *aResult = domFile.forget().downcast<nsIDOMFile>().take();
     LookupAndCacheNext();
     return NS_OK;
   }
 
@@ -508,26 +507,26 @@ public:
     , mInput(aInput)
     , mTopDir(aTopDir)
     , mFileListLength(0)
     , mCanceled(false)
   {}
 
   NS_IMETHOD Run() {
     if (!NS_IsMainThread()) {
-      // Build up list of File objects on this dedicated thread:
+      // Build up list of nsDOMFileFile 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()));
+        mFileList.AppendElement(domFile);
         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;
         }
       }
@@ -547,23 +546,16 @@ public:
 
     mInput->MaybeDispatchProgressEvent(true);        // Last progress event.
     mInput->mDirPickerFileListBuilderTask = nullptr; // Now null out.
 
     if (mCanceled) { // The last progress event may have canceled us
       return NS_OK;
     }
 
-    // Recreate File with the correct parent object.
-    nsCOMPtr<nsIGlobalObject> global = mInput->OwnerDoc()->GetScopeObject();
-    for (uint32_t i = 0; i < mFileList.Length(); ++i) {
-      MOZ_ASSERT(!mFileList[i]->GetParentObject());
-      mFileList[i] = new File(global, mFileList[i]->Impl());
-    }
-
     // The text control frame (if there is one) isn't going to send a change
     // event because it will think this is done by a script.
     // So, we can safely send one by ourself.
     mInput->SetFiles(mFileList, true);
     nsresult rv =
       nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
                                            static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
                                            NS_LITERAL_STRING("change"), true,
@@ -597,17 +589,17 @@ public:
    * we don't increase the size of HTMLInputElement for something that's rarely
    * used.
    */
   uint32_t mPreviousFileListLength;
 
 private:
   nsRefPtr<HTMLInputElement> mInput;
   nsCOMPtr<nsIFile> mTopDir;
-  nsTArray<nsRefPtr<File>> mFileList;
+  nsTArray<nsCOMPtr<nsIDOMFile> > mFileList;
 
   // We access the list length on both threads, so we need the indirection of
   // this atomic member to make the access thread safe:
   mozilla::Atomic<uint32_t> mFileListLength;
 
   mozilla::Atomic<bool> mCanceled;
 };
 
@@ -623,17 +615,17 @@ HTMLInputElement::nsFilePickerShownCallb
 
   mInput->CancelDirectoryPickerScanIfRunning();
 
   int16_t mode;
   mFilePicker->GetMode(&mode);
 
   if (mode == static_cast<int16_t>(nsIFilePicker::modeGetFolder)) {
     // Directory picking is different, since we still need to do more I/O to
-    // build up the list of File objects. Since this may block for a
+    // build up the list of nsDOMFileFile objects. Since this may block for a
     // long time, we need to build the list off on another dedicated thread to
     // avoid blocking any other activities that the browser is carrying out.
 
     // The user selected this directory, so we always save this dir, even if
     // no files are found under it.
     nsCOMPtr<nsIFile> pickedDir;
     mFilePicker->GetFile(getter_AddRefs(pickedDir));
 
@@ -658,42 +650,42 @@ HTMLInputElement::nsFilePickerShownCallb
     // dispatching the "change" event.
     mInput->mDirPickerFileListBuilderTask =
       new DirPickerFileListBuilderTask(mInput.get(), pickedDir.get());
     return target->Dispatch(mInput->mDirPickerFileListBuilderTask,
                             NS_DISPATCH_NORMAL);
   }
 
   // Collect new selected filenames
-  nsTArray<nsRefPtr<File>> newFiles;
+  nsTArray<nsCOMPtr<nsIDOMFile> > newFiles;
   if (mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)) {
     nsCOMPtr<nsISimpleEnumerator> iter;
     nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!iter) {
       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);
       MOZ_ASSERT(domFile);
-      newFiles.AppendElement(static_cast<File*>(domFile.get()));
+      newFiles.AppendElement(domFile);
     }
   } else {
     MOZ_ASSERT(mode == static_cast<int16_t>(nsIFilePicker::modeOpen));
     nsCOMPtr<nsIDOMFile> domFile;
     nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile));
     NS_ENSURE_SUCCESS(rv, rv);
     if (domFile) {
-      newFiles.AppendElement(static_cast<File*>(domFile.get()));
+      newFiles.AppendElement(domFile);
     }
   }
 
   if (newFiles.IsEmpty()) {
     return NS_OK;
   }
 
   // Store the last used directory using the content pref service:
@@ -939,17 +931,17 @@ HTMLInputElement::InitFilePicker(FilePic
     SetFilePickerFiltersFromAccept(filePicker);
   } else {
     filePicker->AppendFilters(nsIFilePicker::filterAll);
   }
 
   // Set default directry and filename
   nsAutoString defaultName;
 
-  const nsTArray<nsRefPtr<File>>& oldFiles = GetFilesInternal();
+  const nsTArray<nsCOMPtr<nsIDOMFile> >& oldFiles = GetFilesInternal();
 
   nsCOMPtr<nsIFilePickerShownCallback> callback =
     new HTMLInputElement::nsFilePickerShownCallback(this, filePicker);
 
   if (!oldFiles.IsEmpty() &&
       aType != FILE_PICKER_DIRECTORY) {
     nsString path;
 
@@ -1719,17 +1711,17 @@ HTMLInputElement::IsValueEmpty() const
   GetValueInternal(value);
 
   return value.IsEmpty();
 }
 
 void
 HTMLInputElement::ClearFiles(bool aSetValueChanged)
 {
-  nsTArray<nsRefPtr<File>> files;
+  nsTArray<nsCOMPtr<nsIDOMFile> > files;
   SetFiles(files, aSetValueChanged);
 }
 
 /* static */ Decimal
 HTMLInputElement::StringToDecimal(const nsAString& aValue)
 {
   if (!IsASCII(aValue)) {
     return Decimal::nan();
@@ -2313,17 +2305,17 @@ HTMLInputElement::MozGetFileNameArray(ui
   *aFileNames = ret;
 
   return NS_OK;
 }
 
 void
 HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
 {
-  nsTArray<nsRefPtr<File>> files;
+  nsTArray<nsCOMPtr<nsIDOMFile> > files;
   for (uint32_t i = 0; i < aFileNames.Length(); ++i) {
     nsCOMPtr<nsIFile> file;
 
     if (StringBeginsWith(aFileNames[i], NS_LITERAL_STRING("file:"),
                          nsASCIICaseInsensitiveStringComparator())) {
       // Converts the URL string into the corresponding nsIFile if possible
       // A local file will be created if the URL string begins with file://
       NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(aFileNames[i]),
@@ -2331,18 +2323,17 @@ HTMLInputElement::MozSetFileNameArray(co
     }
 
     if (!file) {
       // this is no "file://", try as local file
       NS_NewLocalFile(aFileNames[i], false, getter_AddRefs(file));
     }
 
     if (file) {
-      nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
-      nsRefPtr<File> domFile = File::CreateFromFile(global, file);
+      nsCOMPtr<nsIDOMFile> domFile = DOMFile::CreateFromFile(file);
       files.AppendElement(domFile);
     } else {
       continue; // Not much we can do if the file doesn't exist
     }
 
   }
 
   SetFiles(files, true);
@@ -2568,37 +2559,37 @@ HTMLInputElement::GetDisplayFileName(nsA
     nsContentUtils::FormatLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
                                           "XFilesSelected", params, value);
   }
 
   aValue = value;
 }
 
 void
-HTMLInputElement::SetFiles(const nsTArray<nsRefPtr<File>>& aFiles,
+HTMLInputElement::SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles,
                            bool aSetValueChanged)
 {
   mFiles.Clear();
   mFiles.AppendElements(aFiles);
 
   AfterSetFiles(aSetValueChanged);
 }
 
 void
 HTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
                            bool aSetValueChanged)
 {
-  nsRefPtr<FileList> files = static_cast<FileList*>(aFiles);
   mFiles.Clear();
 
   if (aFiles) {
     uint32_t listLength;
     aFiles->GetLength(&listLength);
     for (uint32_t i = 0; i < listLength; i++) {
-      nsRefPtr<File> file = files->Item(i);
+      nsCOMPtr<nsIDOMFile> file;
+      aFiles->Item(i, getter_AddRefs(file));
       mFiles.AppendElement(file);
     }
   }
 
   AfterSetFiles(aSetValueChanged);
 }
 
 void
@@ -2636,25 +2627,25 @@ HTMLInputElement::FireChangeEventIfNeede
   // Dispatch the change event.
   mFocusedValue = value;
   nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
                                        static_cast<nsIContent*>(this),
                                        NS_LITERAL_STRING("change"), true,
                                        false);
 }
 
-FileList*
+nsDOMFileList*
 HTMLInputElement::GetFiles()
 {
   if (mType != NS_FORM_INPUT_FILE) {
     return nullptr;
   }
 
   if (!mFileList) {
-    mFileList = new FileList(static_cast<nsIContent*>(this));
+    mFileList = new nsDOMFileList(static_cast<nsIContent*>(this));
     UpdateFileList();
   }
 
   return mFileList;
 }
 
 void
 HTMLInputElement::OpenDirectoryPicker(ErrorResult& aRv)
@@ -2788,17 +2779,17 @@ HTMLInputElement::DispatchProgressEvent(
 }
 
 nsresult
 HTMLInputElement::UpdateFileList()
 {
   if (mFileList) {
     mFileList->Clear();
 
-    const nsTArray<nsRefPtr<File>>& files = GetFilesInternal();
+    const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
     for (uint32_t i = 0; i < files.Length(); ++i) {
       if (!mFileList->Append(files[i])) {
         return NS_ERROR_FAILURE;
       }
     }
   }
 
   return NS_OK;
@@ -5371,17 +5362,17 @@ HTMLInputElement::SetSelectionEnd(int32_
   ErrorResult rv;
   SetSelectionEnd(aSelectionEnd, rv);
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 HTMLInputElement::GetFiles(nsIDOMFileList** aFileList)
 {
-  nsRefPtr<FileList> list = GetFiles();
+  nsRefPtr<nsDOMFileList> list = GetFiles();
   list.forget(aFileList);
   return NS_OK;
 }
 
 nsresult
 HTMLInputElement::GetSelectionRange(int32_t* aSelectionStart,
                                     int32_t* aSelectionEnd)
 {
@@ -5638,17 +5629,17 @@ HTMLInputElement::SubmitNamesValues(nsFo
   }
 
   //
   // Submit file if its input type=file and this encoding method accepts files
   //
   if (mType == NS_FORM_INPUT_FILE) {
     // Submit files
 
-    const nsTArray<nsRefPtr<File>>& files = GetFilesInternal();
+    const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
 
     for (uint32_t i = 0; i < files.Length(); ++i) {
       aFormSubmission->AddNameFilePair(name, files[i], NullString());
     }
 
     if (files.IsEmpty()) {
       // If no file was selected, pretend we had an empty file with an
       // empty filename.
@@ -5886,17 +5877,17 @@ HTMLInputElement::RestoreState(nsPresSta
       case VALUE_MODE_DEFAULT_ON:
         if (inputState->IsCheckedSet()) {
           restoredCheckedState = true;
           DoSetChecked(inputState->GetChecked(), true, true);
         }
         break;
       case VALUE_MODE_FILENAME:
         {
-          const nsTArray<nsRefPtr<File>>& files = inputState->GetFiles();
+          const nsTArray<nsCOMPtr<nsIDOMFile> >& files = inputState->GetFiles();
           SetFiles(files, true);
         }
         break;
       case VALUE_MODE_VALUE:
       case VALUE_MODE_DEFAULT:
         if (GetValueMode() == VALUE_MODE_DEFAULT &&
             mType != NS_FORM_INPUT_HIDDEN) {
           break;
@@ -6396,17 +6387,17 @@ HTMLInputElement::IsValueMissing() const
     return false;
   }
 
   switch (GetValueMode()) {
     case VALUE_MODE_VALUE:
       return IsValueEmpty();
     case VALUE_MODE_FILENAME:
     {
-      const nsTArray<nsRefPtr<File>>& files = GetFilesInternal();
+      const nsTArray<nsCOMPtr<nsIDOMFile> >& files = GetFilesInternal();
       return files.IsEmpty();
     }
     case VALUE_MODE_DEFAULT_ON:
       // This should not be used for type radio.
       // See the MOZ_ASSERT at the beginning of the method.
       return !mChecked;
     case VALUE_MODE_DEFAULT:
     default:
--- a/content/html/content/src/HTMLInputElement.h
+++ b/content/html/content/src/HTMLInputElement.h
@@ -19,31 +19,30 @@
 #include "mozilla/dom/HTMLFormElement.h" // for HasEverTriedInvalidSubmit()
 #include "mozilla/dom/HTMLInputElementBinding.h"
 #include "nsIFilePicker.h"
 #include "nsIContentPrefService2.h"
 #include "mozilla/Decimal.h"
 #include "nsContentUtils.h"
 #include "nsTextEditorState.h"
 
+class nsDOMFileList;
 class nsIRadioGroupContainer;
 class nsIRadioGroupVisitor;
 class nsIRadioVisitor;
 
 namespace mozilla {
 
 class EventChainPostVisitor;
 class EventChainPreVisitor;
 
 namespace dom {
 
 class Date;
 class DirPickerFileListBuilderTask;
-class File;
-class FileList;
 
 class UploadLastDir MOZ_FINAL : public nsIObserver, public nsSupportsWeakReference {
 
   ~UploadLastDir() {}
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
@@ -206,22 +205,22 @@ public:
   NS_IMETHOD_(void) UpdatePlaceholderVisibility(bool aNotify) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) GetPlaceholderVisibility() MOZ_OVERRIDE;
   NS_IMETHOD_(void) InitializeKeyboardEventListeners() MOZ_OVERRIDE;
   NS_IMETHOD_(void) OnValueChanged(bool aNotify) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) HasCachedSelection() MOZ_OVERRIDE;
 
   void GetDisplayFileName(nsAString& aFileName) const;
 
-  const nsTArray<nsRefPtr<File>>& GetFilesInternal() const
+  const nsTArray<nsCOMPtr<nsIDOMFile> >& GetFilesInternal() const
   {
     return mFiles;
   }
 
-  void SetFiles(const nsTArray<nsRefPtr<File>>& aFiles, bool aSetValueChanged);
+  void SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles, bool aSetValueChanged);
   void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
 
   // Called when a nsIFilePicker or a nsIColorPicker terminate.
   void PickerClosed();
 
   void SetCheckedChangedInternal(bool aCheckedChanged);
   bool GetCheckedChanged() const {
     return mCheckedChanged;
@@ -428,17 +427,17 @@ public:
 
   void SetDisabled(bool aValue,ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::disabled, aValue, aRv);
   }
 
   // XPCOM GetForm() is OK
 
-  FileList* GetFiles();
+  nsDOMFileList* GetFiles();
 
   void OpenDirectoryPicker(ErrorResult& aRv);
   void CancelDirectoryPickerScanIfRunning();
 
   void StartProgressEventTimer();
   void MaybeDispatchProgressEvent(bool aFinalProgress);
   void DispatchProgressEvent(const nsAString& aType,
                              bool aLengthComputable,
@@ -1247,19 +1246,19 @@ protected:
    * used when uploading a file. It is vital that this is kept separate from
    * mValue so that it won't be possible to 'leak' the value from a text-input
    * to a file-input. Additionally, the logic for this value is kept as simple
    * as possible to avoid accidental errors where the wrong filename is used.
    * Therefor the list of filenames is always owned by this member, never by
    * the frame. Whenever the frame wants to change the filename it has to call
    * SetFileNames to update this member.
    */
-  nsTArray<nsRefPtr<File>> mFiles;
+  nsTArray<nsCOMPtr<nsIDOMFile> >   mFiles;
 
-  nsRefPtr<FileList>  mFileList;
+  nsRefPtr<nsDOMFileList>  mFileList;
 
   nsRefPtr<DirPickerFileListBuilderTask> mDirPickerFileListBuilderTask;
 
   nsString mStaticDocFileList;
   
   /** 
    * The value of the input element when first initialized and it is updated
    * when the element is either changed through a script, focused or dispatches   
--- a/content/html/content/test/test_formData.html
+++ b/content/html/content/test/test_formData.html
@@ -47,22 +47,22 @@ function runTest() {
     }
 
     var file, blob = new Blob(['hey'], {type: 'text/plain'});
 
     var fd = new FormData();
     fd.append("empty", blob);
     fd.append("explicit", blob, "explicit-file-name");
     fd.append("explicit-empty", blob, "");
-    file = new File([blob], 'testname',  {type: 'text/plain'});
+    file = SpecialPowers.unwrap(SpecialPowers.wrap(window).File(blob, {name: 'testname'}));
     fd.append("file-name", file);
-    file = new File([blob], '',  {type: 'text/plain'});
+    file = SpecialPowers.unwrap(SpecialPowers.wrap(window).File(blob, {name: ''}));
     fd.append("empty-file-name", file);
-    file = new File([blob], 'testname',  {type: 'text/plain'});
+    file = SpecialPowers.unwrap(SpecialPowers.wrap(window).File(blob, {name: 'testname'}));
     fd.append("file-name-overwrite", file, "overwrite");
     xhr.responseType = 'json';
     xhr.send(fd);
 }
 
 runTest()
 </script>
 </body>
-</html>
+</html>
\ No newline at end of file
--- a/content/media/EncodedBufferCache.cpp
+++ b/content/media/EncodedBufferCache.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "EncodedBufferCache.h"
-#include "mozilla/dom/File.h"
 #include "nsAnonymousTemporaryFile.h"
+#include "nsDOMFile.h"
 #include "prio.h"
 
 namespace mozilla {
 
 void
 EncodedBufferCache::AppendBuffer(nsTArray<uint8_t> & aBuf)
 {
   MutexAutoLock lock(mMutex);
@@ -34,42 +34,40 @@ EncodedBufferCache::AppendBuffer(nsTArra
         NS_WARNING("Failed to write media cache block!");
       }
     }
     mEncodedBuffers.Clear();
   }
 
 }
 
-already_AddRefed<dom::File>
-EncodedBufferCache::ExtractBlob(nsISupports* aParent,
-                                const nsAString &aContentType)
+already_AddRefed<nsIDOMBlob>
+EncodedBufferCache::ExtractBlob(const nsAString &aContentType)
 {
   MutexAutoLock lock(mMutex);
-  nsRefPtr<dom::File> blob;
+  nsCOMPtr<nsIDOMBlob> blob;
   if (mTempFileEnabled) {
     // generate new temporary file to write
-    blob = dom::File::CreateTemporaryFileBlob(aParent, mFD, 0, mDataSize,
-                                              aContentType);
+    blob = dom::DOMFile::CreateTemporaryFileBlob(mFD, 0, mDataSize,
+                                                 aContentType);
     // fallback to memory blob
     mTempFileEnabled = false;
     mDataSize = 0;
     mFD = nullptr;
   } else {
     void* blobData = moz_malloc(mDataSize);
     NS_ASSERTION(blobData, "out of memory!!");
 
     if (blobData) {
       for (uint32_t i = 0, offset = 0; i < mEncodedBuffers.Length(); i++) {
         memcpy((uint8_t*)blobData + offset, mEncodedBuffers.ElementAt(i).Elements(),
                mEncodedBuffers.ElementAt(i).Length());
         offset += mEncodedBuffers.ElementAt(i).Length();
       }
-      blob = dom::File::CreateMemoryFile(aParent, blobData, mDataSize,
-                                         aContentType);
+      blob = dom::DOMFile::CreateMemoryFile(blobData, mDataSize, aContentType);
       mEncodedBuffers.Clear();
     } else
       return nullptr;
   }
   mDataSize = 0;
   return blob.forget();
 }
 
--- a/content/media/EncodedBufferCache.h
+++ b/content/media/EncodedBufferCache.h
@@ -11,20 +11,16 @@
 #include "nsTArray.h"
 #include "mozilla/Mutex.h"
 
 struct PRFileDesc;
 class nsIDOMBlob;
 
 namespace mozilla {
 
-namespace dom {
-class File;
-}
-
 class ReentrantMonitor;
 /**
  * Data is moved into a temporary file when it grows beyond
  * the maximal size passed in the Init function.
  * The AppendBuffer and ExtractBlob methods are thread-safe and can be called on
  * different threads at the same time.
  */
 class EncodedBufferCache
@@ -38,17 +34,17 @@ public:
     mTempFileEnabled(false) { }
   ~EncodedBufferCache()
   {
   }
   // Append buffers in cache, check if the queue is too large then switch to write buffer to file system
   // aBuf will append to mEncodedBuffers or temporary File, aBuf also be cleared
   void AppendBuffer(nsTArray<uint8_t> & aBuf);
   // Read all buffer from memory or file System, also Remove the temporary file or clean the buffers in memory.
-  already_AddRefed<dom::File> ExtractBlob(nsISupports* aParent, const nsAString &aContentType);
+  already_AddRefed<nsIDOMBlob> ExtractBlob(const nsAString &aContentType);
 
 private:
   //array for storing the encoded data.
   nsTArray<nsTArray<uint8_t> > mEncodedBuffers;
   // File handle for the temporary file
   PRFileDesc* mFD;
   // Used to protect the mEncodedBuffer for avoiding AppendBuffer/Consume on different thread at the same time.
   Mutex mMutex;
--- a/content/media/MediaRecorder.cpp
+++ b/content/media/MediaRecorder.cpp
@@ -10,21 +10,21 @@
 #include "DOMMediaStream.h"
 #include "EncodedBufferCache.h"
 #include "MediaEncoder.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/AudioStreamTrack.h"
 #include "mozilla/dom/BlobEvent.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/RecordErrorEvent.h"
 #include "mozilla/dom/VideoStreamTrack.h"
 #include "nsError.h"
 #include "nsIDocument.h"
+#include "nsIDOMFile.h"
 #include "nsIPrincipal.h"
 #include "nsMimeTypes.h"
 #include "nsProxyRelease.h"
 #include "nsTArray.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gMediaRecorderLog;
 #define LOG(type, msg) PR_LOG(gMediaRecorderLog, type, msg)
@@ -384,18 +384,17 @@ public:
     mTrackUnionStream->ChangeExplicitBlockerCount(-1);
 
     return NS_OK;
   }
 
   already_AddRefed<nsIDOMBlob> GetEncodedData()
   {
     MOZ_ASSERT(NS_IsMainThread());
-    return mEncodedBufferCache->ExtractBlob(mRecorder->GetParentObject(),
-                                            mMimeType);
+    return mEncodedBufferCache->ExtractBlob(mMimeType);
   }
 
   bool IsEncoderError()
   {
     if (mEncoder && mEncoder->HasError()) {
       return true;
     }
     return false;
@@ -916,20 +915,17 @@ MediaRecorder::CreateAndDispatchBlobEven
   if (!CheckPrincipal()) {
     // Media is not same-origin, don't allow the data out.
     nsRefPtr<nsIDOMBlob> blob = aBlob;
     return NS_ERROR_DOM_SECURITY_ERR;
   }
   BlobEventInit init;
   init.mBubbles = false;
   init.mCancelable = false;
-
-  nsCOMPtr<nsIDOMBlob> blob = aBlob;
-  init.mData = static_cast<File*>(blob.get());
-
+  init.mData = aBlob;
   nsRefPtr<BlobEvent> event =
     BlobEvent::Constructor(this,
                            NS_LITERAL_STRING("dataavailable"),
                            init);
   event->SetTrusted(true);
   return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 }
 
--- a/content/media/imagecapture/CaptureTask.cpp
+++ b/content/media/imagecapture/CaptureTask.cpp
@@ -10,30 +10,24 @@
 #include "mozilla/dom/ImageEncoder.h"
 #include "mozilla/dom/VideoStreamTrack.h"
 #include "gfxUtils.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 
 nsresult
-CaptureTask::TaskComplete(already_AddRefed<dom::File> aBlob, nsresult aRv)
+CaptureTask::TaskComplete(already_AddRefed<dom::DOMFile> aBlob, nsresult aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   DetachStream();
 
   nsresult rv;
-  nsRefPtr<dom::File> blob(aBlob);
-
-  // We have to set the parent because the blob has been generated with a valid one.
-  if (blob) {
-    blob = new dom::File(mImageCapture->GetParentObject(), blob->Impl());
-  }
-
+  nsRefPtr<dom::DOMFile> blob(aBlob);
   if (mPrincipalChanged) {
     aRv = NS_ERROR_DOM_SECURITY_ERR;
     IC_LOG("MediaStream principal should not change during TakePhoto().");
   }
 
   if (NS_SUCCEEDED(aRv)) {
     rv = mImageCapture->PostBlobEvent(blob);
   } else {
@@ -99,19 +93,19 @@ CaptureTask::NotifyQueuedTrackChanges(Me
   }
 
   // Callback for encoding complete, it calls on main thread.
   class EncodeComplete : public dom::EncodeCompleteCallback
   {
   public:
     explicit EncodeComplete(CaptureTask* aTask) : mTask(aTask) {}
 
-    nsresult ReceiveBlob(already_AddRefed<dom::File> aBlob) MOZ_OVERRIDE
+    nsresult ReceiveBlob(already_AddRefed<dom::DOMFile> aBlob) MOZ_OVERRIDE
     {
-      nsRefPtr<dom::File> blob(aBlob);
+      nsRefPtr<dom::DOMFile> blob(aBlob);
       mTask->TaskComplete(blob.forget(), NS_OK);
       mTask = nullptr;
       return NS_OK;
     }
 
   protected:
     nsRefPtr<CaptureTask> mTask;
   };
--- a/content/media/imagecapture/CaptureTask.h
+++ b/content/media/imagecapture/CaptureTask.h
@@ -8,18 +8,18 @@
 #define CAPTURETASK_H
 
 #include "DOMMediaStream.h"
 #include "MediaStreamGraph.h"
 
 namespace mozilla {
 
 namespace dom {
-class File;
 class ImageCapture;
+class DOMFile;
 }
 
 /**
  * CaptureTask retrieves image from MediaStream and encodes the image to jpeg in
  * ImageEncoder. The whole procedures start at AttachStream(), it will add this
  * class into MediaStream and retrieves an image in MediaStreamGraph thread.
  * Once the image is retrieved, it will be sent to ImageEncoder and the encoded
  * blob will be sent out via encoder callback in main thread.
@@ -46,17 +46,17 @@ public:
 
   // CaptureTask methods.
 
   // It is called when aBlob is ready to post back to script in company with
   // aRv == NS_OK. If aRv is not NS_OK, it will post an error event to script.
   //
   // Note:
   //   this function should be called on main thread.
-  nsresult TaskComplete(already_AddRefed<dom::File> aBlob, nsresult aRv);
+  nsresult TaskComplete(already_AddRefed<dom::DOMFile> aBlob, nsresult aRv);
 
   // Add listeners into MediaStream and PrincipalChangeObserver. It should be on
   // main thread only.
   void AttachStream();
 
   // Remove listeners from MediaStream and PrincipalChangeObserver. It should be
   // on main thread only.
   void DetachStream();
--- a/content/media/imagecapture/ImageCapture.cpp
+++ b/content/media/imagecapture/ImageCapture.cpp
@@ -2,21 +2,21 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "ImageCapture.h"
 #include "mozilla/dom/BlobEvent.h"
 #include "mozilla/dom/DOMException.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/ImageCaptureError.h"
 #include "mozilla/dom/ImageCaptureErrorEvent.h"
 #include "mozilla/dom/ImageCaptureErrorEventBinding.h"
 #include "mozilla/dom/VideoStreamTrack.h"
+#include "nsDOMFile.h"
 #include "nsIDocument.h"
 #include "CaptureTask.h"
 #include "MediaEngine.h"
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
 
@@ -97,19 +97,19 @@ ImageCapture::TakePhotoByMediaEngine()
       mStream->AddPrincipalChangeObserver(this);
     }
 
     void PrincipalChanged(DOMMediaStream* aMediaStream) MOZ_OVERRIDE
     {
       mPrincipalChanged = true;
     }
 
-    nsresult PhotoComplete(already_AddRefed<File> aBlob) MOZ_OVERRIDE
+    nsresult PhotoComplete(already_AddRefed<DOMFile> aBlob) MOZ_OVERRIDE
     {
-      nsRefPtr<File> blob = aBlob;
+      nsRefPtr<DOMFile> blob = aBlob;
 
       if (mPrincipalChanged) {
         return PhotoError(NS_ERROR_DOM_SECURITY_ERR);
       }
       return mImageCapture->PostBlobEvent(blob);
     }
 
     nsresult PhotoError(nsresult aRv) MOZ_OVERRIDE
@@ -167,17 +167,17 @@ ImageCapture::TakePhoto(ErrorResult& aRe
 
     // It adds itself into MediaStreamGraph, so ImageCapture doesn't need to hold
     // the reference.
     task->AttachStream();
   }
 }
 
 nsresult
-ImageCapture::PostBlobEvent(File* aBlob)
+ImageCapture::PostBlobEvent(nsIDOMBlob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!CheckPrincipal()) {
     // Media is not same-origin, don't allow the data out.
     return PostErrorEvent(ImageCaptureError::PHOTO_ERROR, NS_ERROR_DOM_SECURITY_ERR);
   }
 
   BlobEventInit init;
--- a/content/media/imagecapture/ImageCapture.h
+++ b/content/media/imagecapture/ImageCapture.h
@@ -27,17 +27,16 @@ PRLogModuleInfo* GetICLog();
 #ifndef IC_LOG
 #define IC_LOG(...)
 #endif
 
 #endif // PR_LOGGING
 
 namespace dom {
 
-class File;
 class VideoStreamTrack;
 
 /**
  *  Implementation of https://dvcs.w3.org/hg/dap/raw-file/default/media-stream-
  *  capture/ImageCapture.html.
  *  The ImageCapture accepts a VideoStreamTrack as input source. The image will
  *  be sent back as a JPG format via Blob event.
  *
@@ -75,17 +74,17 @@ public:
 
   static already_AddRefed<ImageCapture> Constructor(const GlobalObject& aGlobal,
                                                     VideoStreamTrack& aTrack,
                                                     ErrorResult& aRv);
 
   ImageCapture(VideoStreamTrack* aVideoStreamTrack, nsPIDOMWindow* aOwnerWindow);
 
   // Post a Blob event to script.
-  nsresult PostBlobEvent(File* aBlob);
+  nsresult PostBlobEvent(nsIDOMBlob* aBlob);
 
   // Post an error event to script.
   // aErrorCode should be one of error codes defined in ImageCaptureError.h.
   // aReason is the nsresult which maps to a error string in dom/base/domerr.msg.
   nsresult PostErrorEvent(uint16_t aErrorCode, nsresult aReason = NS_OK);
 
   bool CheckPrincipal();
 
--- a/content/media/webrtc/MediaEngine.h
+++ b/content/media/webrtc/MediaEngine.h
@@ -10,17 +10,17 @@
 #include "DOMMediaStream.h"
 #include "MediaStreamGraph.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "mozilla/dom/VideoStreamTrack.h"
 
 namespace mozilla {
 
 namespace dom {
-class File;
+class DOMFile;
 }
 
 struct VideoTrackConstraintsN;
 struct AudioTrackConstraintsN;
 
 /**
  * Abstract interface for managing audio and video devices. Each platform
  * must implement a concrete class that will map these classes and methods
@@ -145,17 +145,17 @@ public:
   // Callback interface for TakePhoto(). Either PhotoComplete() or PhotoError()
   // should be called.
   class PhotoCallback {
   public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PhotoCallback)
 
     // aBlob is the image captured by MediaEngineSource. It is
     // called on main thread.
-    virtual nsresult PhotoComplete(already_AddRefed<dom::File> aBlob) = 0;
+    virtual nsresult PhotoComplete(already_AddRefed<dom::DOMFile> aBlob) = 0;
 
     // It is called on main thread. aRv is the error code.
     virtual nsresult PhotoError(nsresult aRv) = 0;
 
   protected:
     virtual ~PhotoCallback() {}
   };
 
--- a/content/media/webrtc/MediaEngineDefault.cpp
+++ b/content/media/webrtc/MediaEngineDefault.cpp
@@ -1,16 +1,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 "MediaEngineDefault.h"
 
 #include "nsCOMPtr.h"
-#include "mozilla/dom/File.h"
+#include "nsDOMFile.h"
 #include "nsILocalFile.h"
 #include "Layers.h"
 #include "ImageContainer.h"
 #include "ImageTypes.h"
 #include "prmem.h"
 #include "nsContentUtils.h"
 
 #include "nsIFilePicker.h"
@@ -203,17 +203,17 @@ MediaEngineDefaultVideoSource::Snapshot(
   nsCOMPtr<nsIFile> localFile;
   filePicker->GetFile(getter_AddRefs(localFile));
 
   if (!localFile) {
     *aFile = nullptr;
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMFile> domFile = dom::File::CreateFromFile(nullptr, localFile);
+  nsCOMPtr<nsIDOMFile> domFile = dom::DOMFile::CreateFromFile(localFile);
   domFile.forget(aFile);
   return NS_OK;
 #endif
 }
 
 NS_IMETHODIMP
 MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
 {
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -5,20 +5,20 @@
 #ifndef MEDIAENGINEWEBRTC_H_
 #define MEDIAENGINEWEBRTC_H_
 
 #include "prcvar.h"
 #include "prthread.h"
 #include "nsIThread.h"
 #include "nsIRunnable.h"
 
-#include "mozilla/dom/File.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Monitor.h"
 #include "nsCOMPtr.h"
+#include "nsDOMFile.h"
 #include "nsThreadUtils.h"
 #include "DOMMediaStream.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsComponentManagerUtils.h"
 #include "nsRefPtrHashtable.h"
 
 #include "VideoUtils.h"
 #include "MediaEngine.h"
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -938,21 +938,21 @@ MediaEngineWebRTCVideoSource::OnTakePict
     {
       mCallbacks.SwapElements(aCallbacks);
       mPhoto.AppendElements(aData, aLength);
       mMimeType = aMimeType;
     }
 
     NS_IMETHOD Run()
     {
-      nsRefPtr<dom::File> blob =
-        dom::File::CreateMemoryFile(nullptr, mPhoto.Elements(), mPhoto.Length(), mMimeType);
+      nsRefPtr<dom::DOMFile> blob =
+        dom::DOMFile::CreateMemoryFile(mPhoto.Elements(), mPhoto.Length(), mMimeType);
       uint32_t callbackCounts = mCallbacks.Length();
       for (uint8_t i = 0; i < callbackCounts; i++) {
-        nsRefPtr<dom::File> tempBlob = blob;
+        nsRefPtr<dom::DOMFile> tempBlob = blob;
         mCallbacks[i]->PhotoComplete(tempBlob.forget());
       }
       // PhotoCallback needs to dereference on main thread.
       mCallbacks.Clear();
       return NS_OK;
     }
 
     nsTArray<nsRefPtr<PhotoCallback>> mCallbacks;
--- a/dom/archivereader/ArchiveEvent.cpp
+++ b/dom/archivereader/ArchiveEvent.cpp
@@ -125,17 +125,17 @@ ArchiveReaderEvent::ShareMainThread()
 
         // Just to be sure, if something goes wrong, the mimetype is an empty string:
         nsCString type;
         if (NS_SUCCEEDED(GetType(filename, type))) {
           item->SetType(type);
         }
       }
 
-      // This is a File:
+      // This is a nsDOMFile:
       nsRefPtr<nsIDOMFile> file = item->File(mArchiveReader);
       if (file) {
         fileList.AppendElement(file);
       }
     }
   }
 
   mArchiveReader->Ready(fileList, mStatus);
--- a/dom/archivereader/ArchiveEvent.h
+++ b/dom/archivereader/ArchiveEvent.h
@@ -4,19 +4,19 @@
  * 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_archivereader_domarchiveevent_h__
 #define mozilla_dom_archivereader_domarchiveevent_h__
 
 #include "ArchiveReader.h"
 
-#include "mozilla/dom/File.h"
 #include "nsISeekableStream.h"
 #include "nsIMIMEService.h"
+#include "nsDOMFile.h"
 
 #include "ArchiveReaderCommon.h"
 
 BEGIN_ARCHIVEREADER_NAMESPACE
 
 /**
  * This class contains all the info needed for a single item
  * It must contain the implementation of the File() method.
@@ -30,17 +30,17 @@ public:
 
   // Getter/Setter for the type
   nsCString GetType();
   void SetType(const nsCString& aType);
 
   // Getter for the filename
   virtual nsresult GetFilename(nsString& aFilename) = 0;
 
-  // Generate a File
+  // Generate a DOMFile
   virtual nsIDOMFile* File(ArchiveReader* aArchiveReader) = 0;
 
 protected:
   virtual ~ArchiveItem();
 
   nsCString mType;
 };
 
--- a/dom/archivereader/ArchiveReader.cpp
+++ b/dom/archivereader/ArchiveReader.cpp
@@ -9,30 +9,31 @@
 #include "ArchiveEvent.h"
 #include "ArchiveZipEvent.h"
 
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 
 #include "mozilla/dom/ArchiveReaderBinding.h"
 #include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/File.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/dom/EncodingUtils.h"
-#include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 USING_ARCHIVEREADER_NAMESPACE
 
 /* static */ already_AddRefed<ArchiveReader>
 ArchiveReader::Constructor(const GlobalObject& aGlobal,
-                           File& aBlob,
+                           nsIDOMBlob* aBlob,
                            const ArchiveReaderOptions& aOptions,
                            ErrorResult& aError)
 {
+  MOZ_ASSERT(aBlob);
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
   if (!window) {
     aError.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsAutoCString encoding;
   if (!EncodingUtils::FindEncodingForLabelNoReplacement(aOptions.mEncoding,
@@ -41,23 +42,24 @@ ArchiveReader::Constructor(const GlobalO
     return nullptr;
   }
 
   nsRefPtr<ArchiveReader> reader =
     new ArchiveReader(aBlob, window, encoding);
   return reader.forget();
 }
 
-ArchiveReader::ArchiveReader(File& aBlob, nsPIDOMWindow* aWindow,
+ArchiveReader::ArchiveReader(nsIDOMBlob* aBlob, nsPIDOMWindow* aWindow,
                              const nsACString& aEncoding)
-  : mBlob(&aBlob)
+  : mBlob(aBlob)
   , mWindow(aWindow)
   , mStatus(NOT_STARTED)
   , mEncoding(aEncoding)
 {
+  MOZ_ASSERT(aBlob);
   MOZ_ASSERT(aWindow);
 }
 
 ArchiveReader::~ArchiveReader()
 {
 }
 
 /* virtual */ JSObject*
--- a/dom/archivereader/ArchiveReader.h
+++ b/dom/archivereader/ArchiveReader.h
@@ -14,17 +14,16 @@
 #include "nsCOMArray.h"
 #include "nsIChannel.h"
 #include "nsIDOMFile.h"
 #include "mozilla/Attributes.h"
 
 namespace mozilla {
 namespace dom {
 struct ArchiveReaderOptions;
-class File;
 class GlobalObject;
 } // namespace dom
 } // namespace mozilla
 
 BEGIN_ARCHIVEREADER_NAMESPACE
 
 class ArchiveRequest;
 
@@ -34,20 +33,20 @@ class ArchiveRequest;
 class ArchiveReader MOZ_FINAL : public nsISupports,
                                 public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ArchiveReader)
 
   static already_AddRefed<ArchiveReader>
-  Constructor(const GlobalObject& aGlobal, File& aBlob,
+  Constructor(const GlobalObject& aGlobal, nsIDOMBlob* aBlob,
               const ArchiveReaderOptions& aOptions, ErrorResult& aError);
 
-  ArchiveReader(File& aBlob, nsPIDOMWindow* aWindow,
+  ArchiveReader(nsIDOMBlob* aBlob, nsPIDOMWindow* aWindow,
                 const nsACString& aEncoding);
 
   nsIDOMWindow* GetParentObject() const
   {
     return mWindow;
   }
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
@@ -71,17 +70,17 @@ private:
   already_AddRefed<ArchiveRequest> GenerateArchiveRequest();
 
   nsresult OpenArchive();
 
   void RequestReady(ArchiveRequest* aRequest);
 
 protected:
   // The archive blob/file
-  nsRefPtr<File> mBlob;
+  nsCOMPtr<nsIDOMBlob> mBlob;
 
   // The window is needed by the requests
   nsCOMPtr<nsPIDOMWindow> mWindow;
 
   // Are we ready to return data?
   enum {
     NOT_STARTED = 0,
     WORKING,
--- a/dom/archivereader/ArchiveZipEvent.cpp
+++ b/dom/archivereader/ArchiveZipEvent.cpp
@@ -69,27 +69,27 @@ ArchiveZipItem::GetFilename(nsString& aF
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   aFilename = mFilenameU;
   return NS_OK;
 }
 
-// From zipItem to File:
+// From zipItem to DOMFile:
 nsIDOMFile*
 ArchiveZipItem::File(ArchiveReader* aArchiveReader)
 {
   nsString filename;
 
   if (NS_FAILED(GetFilename(filename))) {
     return nullptr;
   }
 
-  return new dom::File(aArchiveReader,
+  return new DOMFile(
     new ArchiveZipFileImpl(filename,
                            NS_ConvertUTF8toUTF16(GetType()),
                            StrToInt32(mCentralStruct.orglen),
                            mCentralStruct, aArchiveReader));
 }
 
 uint32_t
 ArchiveZipItem::StrToInt32(const uint8_t* aStr)
--- a/dom/archivereader/ArchiveZipEvent.h
+++ b/dom/archivereader/ArchiveZipEvent.h
@@ -25,17 +25,17 @@ public:
                  const ZipCentral& aCentralStruct,
                  const nsACString& aEncoding);
 protected:
   virtual ~ArchiveZipItem();
 
 public:
   nsresult GetFilename(nsString& aFilename) MOZ_OVERRIDE;
 
-  // From zipItem to File:
+  // From zipItem to DOMFile:
   virtual nsIDOMFile* File(ArchiveReader* aArchiveReader) MOZ_OVERRIDE;
 
 public: // for the event
   static uint32_t StrToInt32(const uint8_t* aStr);
   static uint16_t StrToInt16(const uint8_t* aStr);
 
 private:
   nsresult ConvertFilename();
--- a/dom/archivereader/ArchiveZipFile.cpp
+++ b/dom/archivereader/ArchiveZipFile.cpp
@@ -5,19 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ArchiveZipFile.h"
 #include "ArchiveZipEvent.h"
 
 #include "nsIInputStream.h"
 #include "zlib.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/File.h"
 
-using namespace mozilla::dom;
 USING_ARCHIVEREADER_NAMESPACE
 
 #define ZIP_CHUNK 16384
 
 /**
  * Input stream object for zip files
  */
 class ArchiveInputStream MOZ_FINAL : public nsIInputStream,
@@ -393,21 +391,20 @@ ArchiveZipFileImpl::Unlink()
 
 void
 ArchiveZipFileImpl::Traverse(nsCycleCollectionTraversalCallback &cb)
 {
   ArchiveZipFileImpl* tmp = this;
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArchiveReader);
 }
 
-already_AddRefed<mozilla::dom::FileImpl>
+already_AddRefed<mozilla::dom::DOMFileImpl>
 ArchiveZipFileImpl::CreateSlice(uint64_t aStart,
                                 uint64_t aLength,
-                                const nsAString& aContentType,
-                                ErrorResult& aRv)
+                                const nsAString& aContentType)
 {
-  nsRefPtr<FileImpl> impl =
+  nsRefPtr<DOMFileImpl> impl =
     new ArchiveZipFileImpl(mFilename, mContentType, aStart, mLength, mCentral,
                            mArchiveReader);
   return impl.forget();
 }
 
-NS_IMPL_ISUPPORTS_INHERITED0(ArchiveZipFileImpl, FileImpl)
+NS_IMPL_ISUPPORTS_INHERITED0(ArchiveZipFileImpl, DOMFileImpl)
--- a/dom/archivereader/ArchiveZipFile.h
+++ b/dom/archivereader/ArchiveZipFile.h
@@ -3,54 +3,54 @@
 /* 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_archivereader_domarchivefile_h__
 #define mozilla_dom_archivereader_domarchivefile_h__
 
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/File.h"
+#include "nsDOMFile.h"
 
 #include "ArchiveReader.h"
 
 #include "ArchiveReaderCommon.h"
 #include "zipstruct.h"
 
 BEGIN_ARCHIVEREADER_NAMESPACE
 
 /**
- * ArchiveZipFileImpl to FileImpl
+ * ArchiveZipFileImpl to DOMFileImpl
  */
-class ArchiveZipFileImpl : public FileImplBase
+class ArchiveZipFileImpl : public DOMFileImplBase
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   ArchiveZipFileImpl(const nsAString& aName,
                      const nsAString& aContentType,
                      uint64_t aLength,
                      ZipCentral& aCentral,
                      ArchiveReader* aReader)
-  : FileImplBase(aName, aContentType, aLength),
+  : DOMFileImplBase(aName, aContentType, aLength),
     mCentral(aCentral),
     mArchiveReader(aReader),
     mFilename(aName)
   {
     NS_ASSERTION(mArchiveReader, "must have a reader");
     MOZ_COUNT_CTOR(ArchiveZipFileImpl);
   }
 
   ArchiveZipFileImpl(const nsAString& aName,
                      const nsAString& aContentType,
                      uint64_t aStart,
                      uint64_t aLength,
                      ZipCentral& aCentral,
                      ArchiveReader* aReader)
-  : FileImplBase(aContentType, aStart, aLength),
+  : DOMFileImplBase(aContentType, aStart, aLength),
     mCentral(aCentral),
     mArchiveReader(aReader),
     mFilename(aName)
   {
     NS_ASSERTION(mArchiveReader, "must have a reader");
     MOZ_COUNT_CTOR(ArchiveZipFileImpl);
   }
 
@@ -66,19 +66,19 @@ public:
   }
 
 protected:
   virtual ~ArchiveZipFileImpl()
   {
     MOZ_COUNT_DTOR(ArchiveZipFileImpl);
   }
 
-  virtual already_AddRefed<FileImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
-              ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual already_AddRefed<DOMFileImpl> CreateSlice(uint64_t aStart,
+                                                    uint64_t aLength,
+                                                    const nsAString& aContentType) MOZ_OVERRIDE;
 
 private: // Data
   ZipCentral mCentral;
   nsRefPtr<ArchiveReader> mArchiveReader;
 
   nsString mFilename;
 };
 
--- a/dom/base/ImageEncoder.cpp
+++ b/dom/base/ImageEncoder.cpp
@@ -83,20 +83,18 @@ public:
   {}
 
   NS_IMETHOD Run()
   {
     nsresult rv = NS_OK;
     MOZ_ASSERT(NS_IsMainThread());
 
     if (!mFailed) {
-      // The correct parentObject has to be set by the mEncodeCompleteCallback.
-      nsRefPtr<File> blob =
-        File::CreateMemoryFile(nullptr, mImgData, mImgSize, mType);
-      MOZ_ASSERT(blob);
+      nsRefPtr<DOMFile> blob =
+        DOMFile::CreateMemoryFile(mImgData, mImgSize, mType);
 
       rv = mEncodeCompleteCallback->ReceiveBlob(blob.forget());
     }
 
     mEncodeCompleteCallback = nullptr;
 
     mEncoderThread->Shutdown();
     return rv;
--- a/dom/base/ImageEncoder.h
+++ b/dom/base/ImageEncoder.h
@@ -2,18 +2,18 @@
 /* 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 ImageEncoder_h
 #define ImageEncoder_h
 
 #include "imgIEncoder.h"
+#include "nsDOMFile.h"
 #include "nsError.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/HTMLCanvasElementBinding.h"
 #include "nsLayoutUtils.h"
 #include "nsNetUtil.h"
 #include "nsSize.h"
 
 class nsICanvasRenderingContextInternal;
 
 namespace mozilla {
@@ -46,31 +46,27 @@ public:
   // fall back to a PNG encoder. aOptions are the options to be passed to the
   // encoder and aUsingCustomOptions specifies whether custom parse options were
   // used (i.e. by using -moz-parse-options). If there are any unrecognized
   // custom parse options, we fall back to the default values for the encoder
   // without any options at all. A return value of NS_OK only implies
   // successful dispatching of the extraction step to the encoding thread.
   // aEncodeCallback will be called on main thread when encoding process is
   // success.
-  // Note: The callback has to set a valid parent for content for the generated
-  // Blob object.
   static nsresult ExtractDataAsync(nsAString& aType,
                                    const nsAString& aOptions,
                                    bool aUsingCustomOptions,
                                    uint8_t* aImageBuffer,
                                    int32_t aFormat,
                                    const nsIntSize aSize,
                                    EncodeCompleteCallback* aEncodeCallback);
 
   // Extract an Image asynchronously. Its function is same as ExtractDataAsync
   // except for the parameters. aImage is the uncompressed data. aEncodeCallback
   // will be called on main thread when encoding process is success.
-  // Note: The callback has to set a valid parent for content for the generated
-  // Blob object.
   static nsresult ExtractDataFromLayersImageAsync(nsAString& aType,
                                                   const nsAString& aOptions,
                                                   bool aUsingCustomOptions,
                                                   layers::Image* aImage,
                                                   EncodeCompleteCallback* aEncodeCallback);
 
   // Gives you a stream containing the image represented by aImageBuffer.
   // The format is given in aFormat, for example
@@ -110,17 +106,17 @@ private:
  *  The callback interface of ExtractDataAsync and ExtractDataFromLayersImageAsync.
  *  ReceiveBlob() is called on main thread when encoding is complete.
  */
 class EncodeCompleteCallback
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(EncodeCompleteCallback)
 
-  virtual nsresult ReceiveBlob(already_AddRefed<File> aBlob) = 0;
+  virtual nsresult ReceiveBlob(already_AddRefed<DOMFile> aBlob) = 0;
 
 protected:
   virtual ~EncodeCompleteCallback() {}
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/base/MessagePort.cpp
+++ b/dom/base/MessagePort.cpp
@@ -1,28 +1,27 @@
 /* -*- Mode: C++; 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 "MessagePort.h"
 #include "MessageEvent.h"
-#include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/Event.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/MessageChannel.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/MessagePortList.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsPresContext.h"
 #include "ScriptSettings.h"
 
 #include "nsIDocument.h"
+#include "nsIDOMFile.h"
 #include "nsIDOMFileList.h"
 #include "nsIPresShell.h"
 
 namespace mozilla {
 namespace dom {
 
 class DispatchEventRunnable : public nsRunnable
 {
@@ -99,47 +98,17 @@ struct StructuredCloneInfo
 
 static JSObject*
 PostMessageReadStructuredClone(JSContext* cx,
                                JSStructuredCloneReader* reader,
                                uint32_t tag,
                                uint32_t data,
                                void* closure)
 {
-  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
-  NS_ASSERTION(scInfo, "Must have scInfo!");
-
-  if (tag == SCTAG_DOM_BLOB) {
-    NS_ASSERTION(!data, "Data should be empty");
-
-    // What we get back from the reader is a FileImpl.
-    // From that we create a new File.
-    FileImpl* blobImpl;
-    if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
-      MOZ_ASSERT(blobImpl);
-
-      // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
-      // called because the static analysis thinks dereferencing XPCOM objects
-      // can GC (because in some cases it can!), and a return statement with a
-      // JSObject* type means that JSObject* is on the stack as a raw pointer
-      // while destructors are running.
-      JS::Rooted<JS::Value> val(cx);
-      {
-        nsRefPtr<File> blob = new File(scInfo->mPort->GetParentObject(),
-                                             blobImpl);
-        if (!WrapNewBindingObject(cx, blob, &val)) {
-          return nullptr;
-        }
-      }
-
-      return &val.toObject();
-    }
-  }
-
-  if (tag == SCTAG_DOM_FILELIST) {
+  if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
     NS_ASSERTION(!data, "Data should be empty");
 
     nsISupports* supports;
     if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
       JS::Rooted<JS::Value> val(cx);
       if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val))) {
         return val.toObjectOrNull();
       }
@@ -160,36 +129,28 @@ static bool
 PostMessageWriteStructuredClone(JSContext* cx,
                                 JSStructuredCloneWriter* writer,
                                 JS::Handle<JSObject*> obj,
                                 void *closure)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  // See if this is a File/Blob object.
-  {
-    File* blob = nullptr;
-    if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
-      FileImpl* blobImpl = blob->Impl();
-      if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
-          JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
-        scInfo->mEvent->StoreISupports(blobImpl);
-        return true;
-      }
-    }
-  }
-
   nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
   nsContentUtils::XPConnect()->
     GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
   if (wrappedNative) {
     uint32_t scTag = 0;
     nsISupports* supports = wrappedNative->Native();
 
+    nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
+    if (blob) {
+      scTag = SCTAG_DOM_BLOB;
+    }
+
     nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
     if (list) {
       scTag = SCTAG_DOM_FILELIST;
     }
 
     if (scTag) {
       return JS_WriteUint32Pair(writer, scTag, 0) &&
              JS_WriteBytes(writer, &supports, sizeof(supports)) &&
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -8,17 +8,16 @@
 #include "base/basictypes.h"
 
 #include "Navigator.h"
 #include "nsIXULAppInfo.h"
 #include "nsPluginArray.h"
 #include "nsMimeTypeArray.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/DesktopNotification.h"
-#include "mozilla/dom/File.h"
 #include "nsGeolocation.h"
 #include "nsIHttpProtocolHandler.h"
 #include "nsIContentPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsISupportsPriority.h"
 #include "nsICachingChannel.h"
@@ -1151,24 +1150,24 @@ Navigator::SendBeacon(const nsAString& a
       if (NS_FAILED(rv)) {
         aRv.Throw(NS_ERROR_FAILURE);
         return false;
       }
       mimeType.AssignLiteral("application/octet-stream");
       in = strStream;
 
     } else if (aData.Value().IsBlob()) {
-      File& blob = aData.Value().GetAsBlob();
-      rv = blob.GetInternalStream(getter_AddRefs(in));
+      nsCOMPtr<nsIDOMBlob> blob = aData.Value().GetAsBlob();
+      rv = blob->GetInternalStream(getter_AddRefs(in));
       if (NS_FAILED(rv)) {
         aRv.Throw(NS_ERROR_FAILURE);
         return false;
       }
       nsAutoString type;
-      rv = blob.GetType(type);
+      rv = blob->GetType(type);
       if (NS_FAILED(rv)) {
         aRv.Throw(NS_ERROR_FAILURE);
         return false;
       }
       mimeType = NS_ConvertUTF16toUTF8(type);
 
     } else if (aData.Value().IsFormData()) {
       nsFormData& form = aData.Value().GetAsFormData();
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -20,16 +20,17 @@
 #include "nsTArray.h"
 
 class nsPluginArray;
 class nsMimeTypeArray;
 class nsPIDOMWindow;
 class nsIDOMNavigatorSystemMessages;
 class nsDOMCameraManager;
 class nsDOMDeviceStorage;
+class nsIDOMBlob;
 class nsIPrincipal;
 class nsIURI;
 
 namespace mozilla {
 namespace dom {
 class Geolocation;
 class systemMessageCallback;
 struct MediaStreamConstraints;
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; 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 "URL.h"
 
 #include "nsGlobalWindow.h"
+#include "nsDOMFile.h"
 #include "DOMMediaStream.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/MediaSource.h"
 #include "mozilla/dom/URLBinding.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIIOService.h"
 #include "nsEscape.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
@@ -106,22 +106,25 @@ URL::Constructor(const GlobalObject& aGl
   }
 
   nsRefPtr<URL> url = new URL(uri);
   return url.forget();
 }
 
 void
 URL::CreateObjectURL(const GlobalObject& aGlobal,
-                     File& aBlob,
+                     nsIDOMBlob* aBlob,
                      const objectURLOptions& aOptions,
                      nsString& aResult,
                      ErrorResult& aError)
 {
-  CreateObjectURLInternal(aGlobal, aBlob.Impl(),
+  DOMFile* blob = static_cast<DOMFile*>(aBlob);
+  MOZ_ASSERT(blob);
+
+  CreateObjectURLInternal(aGlobal, blob->Impl(),
                           NS_LITERAL_CSTRING(BLOBURI_SCHEME), aOptions, aResult,
                           aError);
 }
 
 void
 URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
                      const mozilla::dom::objectURLOptions& aOptions,
                      nsString& aResult,
--- a/dom/base/URL.h
+++ b/dom/base/URL.h
@@ -18,17 +18,16 @@ class nsIURI;
 
 namespace mozilla {
 
 class ErrorResult;
 class DOMMediaStream;
 
 namespace dom {
 
-class File;
 class MediaSource;
 class GlobalObject;
 struct objectURLOptions;
 
 namespace workers {
 class URLProxy;
 }
 
@@ -49,17 +48,17 @@ public:
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               URL& aBase, ErrorResult& aRv);
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               const nsAString& aBase, ErrorResult& aRv);
 
   static void CreateObjectURL(const GlobalObject& aGlobal,
-                              File& aBlob,
+                              nsIDOMBlob* aBlob,
                               const objectURLOptions& aOptions,
                               nsString& aResult,
                               ErrorResult& aError);
   static void CreateObjectURL(const GlobalObject& aGlobal,
                               DOMMediaStream& aStream,
                               const objectURLOptions& aOptions,
                               nsString& aResult,
                               ErrorResult& aError);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -30,16 +30,17 @@
 #include "nsCRTGlue.h"
 #include "nsICategoryManager.h"
 #include "nsIComponentRegistrar.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIXPConnect.h"
 #include "xptcall.h"
 #include "nsTArray.h"
+#include "nsDOMBlobBuilder.h"
 
 // General helper includes
 #include "nsGlobalWindow.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventListener.h"
@@ -95,16 +96,20 @@
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsITreeColumns.h"
 #endif
 #include "nsIDOMXPathNSResolver.h"
 
+// Drag and drop
+#include "nsIDOMFile.h"
+#include "nsDOMBlobBuilder.h" // nsDOMMultipartFile
+
 #include "nsIEventListenerService.h"
 #include "nsIMessageManager.h"
 
 #include "mozilla/dom/TouchEvent.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 
@@ -284,16 +289,21 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(XSLTProcessor, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(XPathNSResolver, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
+  NS_DEFINE_CLASSINFO_DATA(Blob, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
   NS_DEFINE_CLASSINFO_DATA(MozSmsMessage, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozMmsMessage, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozMobileMessageThread, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -357,16 +367,18 @@ struct nsConstructorFuncMapData
   nsDOMConstructorFunc mConstructorFunc;
 };
 
 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
   { eDOMClassInfo_##_class##_id, _func },
 
 static const nsConstructorFuncMapData kConstructorFuncMap[] =
 {
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Blob, DOMMultipartFileImpl::NewBlob)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, DOMMultipartFileImpl::NewFile)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XSLTProcessor, XSLTProcessorCtor)
 };
 #undef NS_DEFINE_CONSTRUCTOR_FUNC_DATA
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr;
 bool nsDOMClassInfo::sIsInitialized = false;
 
 
@@ -778,16 +790,25 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessor)
     DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessorPrivate)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(XPathNSResolver, nsIDOMXPathNSResolver)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathNSResolver)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(MozSmsMessage, nsIDOMMozSmsMessage)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsMessage)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozMmsMessage, nsIDOMMozMmsMessage)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMmsMessage)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -38,16 +38,19 @@ DOMCI_CLASS(CSSMozDocumentRule)
 DOMCI_CLASS(CSSSupportsRule)
 
 // XSLTProcessor
 DOMCI_CLASS(XSLTProcessor)
 
 // DOM Level 3 XPath objects
 DOMCI_CLASS(XPathNSResolver)
 
+DOMCI_CLASS(Blob)
+DOMCI_CLASS(File)
+
 DOMCI_CLASS(MozSmsMessage)
 DOMCI_CLASS(MozMmsMessage)
 DOMCI_CLASS(MozMobileMessageThread)
 
 // @font-face in CSS
 DOMCI_CLASS(CSSFontFaceRule)
 
 DOMCI_CLASS(ContentFrameMessageManager)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -43,21 +43,21 @@
 
 #include "nsViewManager.h"
 
 #include "nsIDOMHTMLCanvasElement.h"
 #include "nsLayoutUtils.h"
 #include "nsComputedDOMStyle.h"
 #include "nsIPresShell.h"
 #include "nsCSSProps.h"
+#include "nsDOMFile.h"
 #include "nsTArrayHelpers.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "mozilla/StyleAnimationValue.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/DOMRect.h"
 #include <algorithm>
 
 #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK)
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #endif
 
@@ -69,16 +69,17 @@
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/IDBFactoryBinding.h"
 #include "mozilla/dom/IDBMutableFileBinding.h"
 #include "mozilla/dom/indexedDB/IDBMutableFile.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "mozilla/dom/quota/QuotaManager.h"
+#include "nsDOMBlobBuilder.h"
 #include "nsPrintfCString.h"
 #include "nsViewportInfo.h"
 #include "nsIFormControl.h"
 #include "nsIScriptError.h"
 #include "nsIAppShell.h"
 #include "nsWidgetsCID.h"
 #include "FrameLayerBuilder.h"
 #include "nsDisplayList.h"
@@ -2847,25 +2848,17 @@ nsDOMWindowUtils::WrapDOMFile(nsIFile *a
                               nsIDOMFile **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);
+  nsRefPtr<DOMFile> file = DOMFile::CreateFromFile(aFile);
   file.forget(aDOMFile);
   return NS_OK;
 }
 
 #ifdef DEBUG
 static bool
 CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)
 {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -117,16 +117,17 @@
 #include "nsIContentViewer.h"
 #include "nsIScriptError.h"
 #include "nsIControllers.h"
 #include "nsIControllerContext.h"
 #include "nsGlobalWindowCommands.h"
 #include "nsAutoPtr.h"
 #include "nsContentUtils.h"
 #include "nsCSSProps.h"
+#include "nsIDOMFile.h"
 #include "nsIDOMFileList.h"
 #include "nsIURIFixup.h"
 #ifndef DEBUG
 #include "nsIAppStartup.h"
 #include "nsToolkitCompsCID.h"
 #endif
 #include "nsCDefaultURIFixup.h"
 #include "mozilla/EventDispatcher.h"
@@ -7872,42 +7873,28 @@ struct StructuredCloneInfo {
 
 static JSObject*
 PostMessageReadStructuredClone(JSContext* cx,
                                JSStructuredCloneReader* reader,
                                uint32_t tag,
                                uint32_t data,
                                void* closure)
 {
-  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
-  NS_ASSERTION(scInfo, "Must have scInfo!");
-
   if (tag == SCTAG_DOM_BLOB) {
     NS_ASSERTION(!data, "Data should be empty");
 
-    // What we get back from the reader is a FileImpl.
-    // From that we create a new File.
-    FileImpl* blobImpl;
-    if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
-      MOZ_ASSERT(blobImpl);
-
-      // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
-      // called because the static analysis thinks dereferencing XPCOM objects
-      // can GC (because in some cases it can!), and a return statement with a
-      // JSObject* type means that JSObject* is on the stack as a raw pointer
-      // while destructors are running.
+    // What we get back from the reader is a DOMFileImpl.
+    // From that we create a new DOMFile.
+    nsISupports* supports;
+    if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
+      nsCOMPtr<nsIDOMBlob> file = new DOMFile(static_cast<DOMFileImpl*>(supports));
       JS::Rooted<JS::Value> val(cx);
-      {
-        nsRefPtr<File> blob = new File(scInfo->window, blobImpl);
-        if (!WrapNewBindingObject(cx, blob, &val)) {
-          return nullptr;
-        }
-      }
-
-      return &val.toObject();
+      if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, file, &val))) {
+        return val.toObjectOrNull();
+      }
     }
   }
 
   if (tag == SCTAG_DOM_FILELIST) {
     NS_ASSERTION(!data, "Data should be empty");
 
     nsISupports* supports;
     if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
@@ -7932,36 +7919,30 @@ static bool
 PostMessageWriteStructuredClone(JSContext* cx,
                                 JSStructuredCloneWriter* writer,
                                 JS::Handle<JSObject*> obj,
                                 void *closure)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  // See if this is a File/Blob object.
-  {
-    File* blob = nullptr;
-    if (scInfo->subsumes && NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
-      FileImpl* blobImpl = blob->Impl();
-      if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
-          JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
-        scInfo->event->StoreISupports(blobImpl);
-        return true;
-      }
-    }
-  }
-
   nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
   nsContentUtils::XPConnect()->
     GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
   if (wrappedNative) {
     uint32_t scTag = 0;
     nsISupports* supports = wrappedNative->Native();
 
+    nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
+    if (blob && scInfo->subsumes) {
+      scTag = SCTAG_DOM_BLOB;
+      DOMFile* file = static_cast<DOMFile*>(blob.get());
+      supports = file->Impl();
+    }
+
     nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
     if (list && scInfo->subsumes)
       scTag = SCTAG_DOM_FILELIST;
 
     if (scTag)
       return JS_WriteUint32Pair(writer, scTag, 0) &&
              JS_WriteBytes(writer, &supports, sizeof(supports)) &&
              scInfo->event->StoreISupports(supports);
--- a/dom/base/test/file_url.jsm
+++ b/dom/base/test/file_url.jsm
@@ -1,12 +1,12 @@
 this.EXPORTED_SYMBOLS = ['checkFromJSM'];
 
 this.checkFromJSM = function checkFromJSM(ok, is) {
-  Components.utils.importGlobalProperties(['URL', 'Blob']);
+  Components.utils.importGlobalProperties(['URL']);
 
   var url = new URL('http://www.example.com');
   is(url.href, "http://www.example.com/", "JSM should have URL");
 
   var url2 = new URL('/foobar', url);
   is(url2.href, "http://www.example.com/foobar", "JSM should have URL - based on another URL");
 
   var blob = new Blob(['a']);
--- a/dom/base/test/test_messageChannel_post.html
+++ b/dom/base/test/test_messageChannel_post.html
@@ -45,21 +45,17 @@ https://bugzilla.mozilla.org/show_bug.cg
                   null,
                   undefined,
                   "hello world",
                   new Blob([]),
                   true ];
 
     a.port1.onmessage = function(evt) {
       ok(tests.length, "We are waiting for a message");
-      if (typeof(tests[0]) == 'object') {
-        is(typeof(tests[0]), typeof(evt.data), "Value ok: " + tests[0]);
-      } else {
-        is(tests[0], evt.data, "Value ok: " + tests[0]);
-      }
+      is(tests[0], evt.data, "Value ok: " + tests[0]);
       tests.shift();
       runTest();
     }
 
     function runTest() {
       if (!tests.length) {
         SimpleTest.finish();
         return;
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -131,20 +131,23 @@ DOMInterfaces = {
         'channelInterpretation': 'channelInterpretationValue',
     },
 },
 
 'BarProp': {
     'headerFile': 'mozilla/dom/BarProps.h',
 },
 
-'Blob': {
-    'nativeType': 'mozilla::dom::File',
-    'headerFile': 'mozilla/dom/File.h',
+'Blob': [
+{
+    'headerFile': 'nsIDOMFile.h',
 },
+{
+    'workers': True,
+}],
 
 'BatteryManager': {
     'nativeType': 'mozilla::dom::battery::BatteryManager',
     'headerFile': 'BatteryManager.h'
 },
 
 'BluetoothAdapter': {
     'nativeType': 'mozilla::dom::bluetooth::BluetoothAdapter',
@@ -396,17 +399,18 @@ DOMInterfaces = {
 'Exception': {
     'headerFile': 'mozilla/dom/DOMException.h',
     'binaryNames': {
         'message': 'messageMoz',
     },
 },
 
 'FileList': {
-    'headerFile': 'mozilla/dom/File.h',
+    'nativeType': 'nsDOMFileList',
+    'headerFile': 'nsDOMFile.h',
 },
 
 'FileReader': {
     'nativeType': 'nsDOMFileReader',
     'implicitJSContext': [ 'readAsArrayBuffer' ],
 },
 
 'FileReaderSync': {
@@ -1789,16 +1793,17 @@ def addExternalIface(iface, nativeType=N
         domInterface['headerFile'] = headerFile
     domInterface['notflattened'] = notflattened
     DOMInterfaces[iface] = domInterface
 
 addExternalIface('ApplicationCache', nativeType='nsIDOMOfflineResourceList')
 addExternalIface('Counter')
 addExternalIface('CSSRule')
 addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
+addExternalIface('File')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
 addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
 addExternalIface('MozControllers', nativeType='nsIControllers')
 addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
 addExternalIface('MozFrameRequestCallback', nativeType='nsIFrameRequestCallback',
@@ -1817,17 +1822,16 @@ addExternalIface('MozWakeLockListener', 
 addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
 addExternalIface('nsIBrowserDOMWindow', nativeType='nsIBrowserDOMWindow',
                  notflattened=True)
 addExternalIface('nsIControllers', nativeType='nsIControllers')
 addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
                  headerFile='Crypto.h')
 addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
                  headerFile='nsIAsyncInputStream.h')
-addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True)
 addExternalIface('nsIMessageBroadcaster', nativeType='nsIMessageBroadcaster',
                  headerFile='nsIMessageManager.h', notflattened=True)
 addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('nsIDocShell', nativeType='nsIDocShell', notflattened=True)
 addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
 addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True)
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -11,17 +11,16 @@
 #include "nsThreadUtils.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/BluetoothAdapterBinding.h"
 #include "mozilla/dom/BluetoothDeviceEvent.h"
 #include "mozilla/dom/BluetoothDiscoveryStateChangedEvent.h"
 #include "mozilla/dom/BluetoothStatusChangedEvent.h"
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/LazyIdleThread.h"
 
 #include "BluetoothAdapter.h"
 #include "BluetoothDevice.h"
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 #include "BluetoothUtils.h"
@@ -766,17 +765,17 @@ BluetoothAdapter::IsConnected(const uint
   }
   bs->IsConnected(aServiceUuid, results);
 
   return request.forget();
 }
 
 already_AddRefed<DOMRequest>
 BluetoothAdapter::SendFile(const nsAString& aDeviceAddress,
-                           File& aBlob, ErrorResult& aRv)
+                           nsIDOMBlob* aBlob, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
@@ -786,25 +785,25 @@ BluetoothAdapter::SendFile(const nsAStri
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     // In-process transfer
-    bs->SendFile(aDeviceAddress, &aBlob, results);
+    bs->SendFile(aDeviceAddress, aBlob, results);
   } else {
     ContentChild *cc = ContentChild::GetSingleton();
     if (!cc) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
-    BlobChild* actor = cc->GetOrCreateActorForBlob(&aBlob);
+    BlobChild* actor = cc->GetOrCreateActorForBlob(aBlob);
     if (!actor) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     bs->SendFile(aDeviceAddress, nullptr, actor, results);
   }
 
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -10,17 +10,16 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "BluetoothCommon.h"
 #include "BluetoothPropertyContainer.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace dom {
-class File;
 class DOMRequest;
 struct MediaMetaData;
 struct MediaPlayStatus;
 }
 }
 
 BEGIN_BLUETOOTH_NAMESPACE
 
@@ -129,17 +128,17 @@ public:
   already_AddRefed<DOMRequest>
     IsConnected(const uint16_t aServiceUuid,
                 ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
     GetConnectedDevices(uint16_t aServiceUuid, ErrorResult& aRv);
 
   already_AddRefed<DOMRequest>
-    SendFile(const nsAString& aDeviceAddress, File& aBlob,
+    SendFile(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob,
              ErrorResult& aRv);
   already_AddRefed<DOMRequest>
     StopSendingFile(const nsAString& aDeviceAddress, ErrorResult& aRv);
   already_AddRefed<DOMRequest>
     ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirmation,
                          ErrorResult& aRv);
 
   already_AddRefed<DOMRequest> ConnectSco(ErrorResult& aRv);
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
@@ -10,37 +10,36 @@
 #include "BluetoothService.h"
 #include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuid.h"
 #include "ObexBase.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/ipc/BlobParent.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
+#include "nsIDOMFile.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsIOutputStream.h"
 #include "nsIVolumeService.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 
 #define TARGET_SUBDIR "Download/Bluetooth/"
 
 USING_BLUETOOTH_NAMESPACE
 using namespace mozilla;
-using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 namespace {
 // Sending system message "bluetooth-opp-update-progress" every 50kb
 static const uint32_t kUpdateProgressBase = 50 * 1024;
 
 /*
  * The format of the header of an PUT request is
@@ -345,18 +344,17 @@ BluetoothOppManager::StartSendingNextFil
 }
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
                               BlobParent* aActor)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsRefPtr<FileImpl> impl = aActor->GetBlobImpl();
-  nsCOMPtr<nsIDOMBlob> blob = new File(nullptr, impl);
+  nsCOMPtr<nsIDOMBlob> blob = aActor->GetBlob();
 
   return SendFile(aDeviceAddress, blob.get());
 }
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
                               nsIDOMBlob* aBlob)
 {
--- a/dom/bluetooth/bluez/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothOppManager.cpp
@@ -9,38 +9,37 @@
 
 #include "BluetoothService.h"
 #include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuid.h"
 #include "ObexBase.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
+#include "nsIDOMFile.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsIOutputStream.h"
 #include "nsIVolumeService.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 
 #define TARGET_SUBDIR "Download/Bluetooth/"
 
 USING_BLUETOOTH_NAMESPACE
 using namespace mozilla;
-using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 
 namespace {
 // Sending system message "bluetooth-opp-update-progress" every 50kb
 static const uint32_t kUpdateProgressBase = 50 * 1024;
 
@@ -367,18 +366,17 @@ BluetoothOppManager::StartSendingNextFil
 }
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
                               BlobParent* aActor)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsRefPtr<FileImpl> impl = aActor->GetBlobImpl();
-  nsCOMPtr<nsIDOMBlob> blob = new File(nullptr, impl);
+  nsCOMPtr<nsIDOMBlob> blob = aActor->GetBlob();
 
   return SendFile(aDeviceAddress, blob.get());
 }
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
                               nsIDOMBlob* aBlob)
 {
--- a/dom/browser-element/BrowserElementParent.jsm
+++ b/dom/browser-element/BrowserElementParent.jsm
@@ -575,18 +575,17 @@ BrowserElementParent.prototype = {
 
     if ('successRv' in data.json) {
       debug("Successful gotDOMRequestResult.");
       let clientObj = Cu.cloneInto(data.json.successRv, this._window);
       Services.DOMRequest.fireSuccess(req, clientObj);
     }
     else {
       debug("Got error in gotDOMRequestResult.");
-      Services.DOMRequest.fireErrorAsync(req,
-        Cu.cloneInto(data.json.errorMsg, this._window));
+      Services.DOMRequest.fireErrorAsync(req, data.json.errorMsg);
     }
   },
 
   _setVisible: function(visible) {
     this._sendAsyncMsg('set-visible', {visible: visible});
     this._frameLoader.visible = visible;
   },
 
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -5,27 +5,27 @@
 #include "DOMCameraControl.h"
 #include "base/basictypes.h"
 #include "nsCOMPtr.h"
 #include "nsDOMClassInfo.h"
 #include "nsHashPropertyBag.h"
 #include "nsThread.h"
 #include "DeviceStorage.h"
 #include "DeviceStorageFileDescriptor.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/ipc/FileDescriptorUtils.h"
 #include "mozilla/MediaManager.h"
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "nsIAppsService.h"
 #include "nsIObserverService.h"
 #include "nsIDOMDeviceStorage.h"
 #include "nsIDOMEventListener.h"
 #include "nsIScriptSecurityManager.h"
+#include "nsDOMFile.h"
 #include "Navigator.h"
 #include "nsXULAppAPI.h"
 #include "DOMCameraManager.h"
 #include "DOMCameraCapabilities.h"
 #include "CameraCommon.h"
 #include "nsGlobalWindow.h"
 #include "CameraPreviewMediaStream.h"
 #include "mozilla/dom/CameraUtilBinding.h"
@@ -1432,35 +1432,33 @@ nsDOMCameraControl::OnFacesDetected(cons
 
   DispatchTrustedEvent(event);
 }
 
 void
 nsDOMCameraControl::OnTakePictureComplete(nsIDOMBlob* aPicture)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aPicture);
+  MOZ_ASSERT(aPicture != nullptr);
 
   nsRefPtr<Promise> promise = mTakePicturePromise.forget();
   if (promise) {
     nsCOMPtr<nsIDOMBlob> picture = aPicture;
     promise->MaybeResolve(picture);
   }
 
-  nsRefPtr<File> blob = static_cast<File*>(aPicture);
-
   nsRefPtr<CameraTakePictureCallback> cb = mTakePictureOnSuccessCb.forget();
   mTakePictureOnErrorCb = nullptr;
   if (cb) {
     ErrorResult ignored;
-    cb->Call(*blob, ignored);
+    cb->Call(aPicture, ignored);
   }
 
   BlobEventInit eventInit;
-  eventInit.mData = blob;
+  eventInit.mData = aPicture;
 
   nsRefPtr<BlobEvent> event = BlobEvent::Constructor(this,
                                                      NS_LITERAL_STRING("picture"),
                                                      eventInit);
 
   DispatchTrustedEvent(event);
 }
 
--- a/dom/camera/DOMCameraControlListener.cpp
+++ b/dom/camera/DOMCameraControlListener.cpp
@@ -1,19 +1,19 @@
 /* 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 "DOMCameraControlListener.h"
 #include "nsThreadUtils.h"
+#include "nsDOMFile.h"
 #include "CameraCommon.h"
 #include "DOMCameraControl.h"
 #include "CameraPreviewMediaStream.h"
 #include "mozilla/dom/CameraManagerBinding.h"
-#include "mozilla/dom/File.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 DOMCameraControlListener::DOMCameraControlListener(nsDOMCameraControl* aDOMCameraControl,
                                                    CameraPreviewMediaStream* aStream)
   : mDOMCameraControl(new nsMainThreadPtrHolder<nsDOMCameraControl>(aDOMCameraControl))
   , mStream(aStream)
@@ -343,20 +343,19 @@ DOMCameraControlListener::OnTakePictureC
       , mLength(aLength)
       , mMimeType(aMimeType)
     { }
 
     void
     RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
     {
       nsCOMPtr<nsIDOMBlob> picture =
-        File::CreateMemoryFile(mDOMCameraControl,
-                               static_cast<void*>(mData),
-                               static_cast<uint64_t>(mLength),
-                               mMimeType);
+        DOMFile::CreateMemoryFile(static_cast<void*>(mData),
+                                  static_cast<uint64_t>(mLength),
+                                  mMimeType);
       aDOMCameraControl->OnTakePictureComplete(picture);
     }
 
   protected:
     uint8_t* mData;
     uint32_t mLength;
     nsString mMimeType;
   };
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -85,19 +85,18 @@ ContactManager.prototype = {
     this.__DOM_IMPL__.setEventHandler("oncontactchange", aHandler);
   },
 
   get oncontactchange() {
     return this.__DOM_IMPL__.getEventHandler("oncontactchange");
   },
 
   _convertContact: function(aContact) {
-    let contact = Cu.cloneInto(aContact, this._window);
-    let newContact = new this._window.mozContact(contact.properties);
-    newContact.setMetadata(contact.id, contact.published, contact.updated);
+    let newContact = new this._window.mozContact(aContact.properties);
+    newContact.setMetadata(aContact.id, aContact.published, aContact.updated);
     return newContact;
   },
 
   _convertContacts: function(aContacts) {
     let contacts = new this._window.Array();
     for (let i in aContacts) {
       contacts.push(this._convertContact(aContacts[i]));
     }
--- a/dom/contacts/tests/test_contacts_blobs.html
+++ b/dom/contacts/tests/test_contacts_blobs.html
@@ -83,24 +83,24 @@ var properties2 = {
 };
 
 var sample_id1;
 var createResult1;
 var findResult1;
 
 function verifyBlob(blob1, blob2, isLast)
 {
-  is(blob1 instanceof Blob, true,
-     "blob1 is an instance of DOMBlob");
-  is(blob2 instanceof Blob, true,
-     "blob2 is an instance of DOMBlob");
-  isnot(blob1 instanceof File, true,
-     "blob1 is an instance of File");
-  isnot(blob2 instanceof File, true,
-     "blob2 is an instance of File");
+  is(blob1 instanceof SpecialPowers.Ci.nsIDOMBlob, true,
+     "blob1 is an instance of nsIDOMBlob");
+  is(blob2 instanceof SpecialPowers.Ci.nsIDOMBlob, true,
+     "blob2 is an instance of nsIDOMBlob");
+  isnot(blob1 instanceof SpecialPowers.Ci.nsIDOMFile, true,
+     "blob1 is an instance of nsIDOMFile");
+  isnot(blob2 instanceof SpecialPowers.Ci.nsIDOMFile, true,
+     "blob2 is an instance of nsIDOMFile");
   ise(blob1.size, blob2.size, "Same size");
   ise(blob1.type, blob2.type, "Same type");
 
   var buffer1;
   var buffer2;
 
   var reader1 = new FileReader();
   reader1.readAsArrayBuffer(blob2);
--- a/dom/devicestorage/DeviceStorageRequestChild.cpp
+++ b/dom/devicestorage/DeviceStorageRequestChild.cpp
@@ -2,17 +2,17 @@
 /* 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 "DeviceStorageRequestChild.h"
 #include "DeviceStorageFileDescriptor.h"
 #include "nsDeviceStorage.h"
-#include "mozilla/dom/File.h"
+#include "nsDOMFile.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 
 namespace mozilla {
 namespace dom {
 namespace devicestorage {
 
 DeviceStorageRequestChild::DeviceStorageRequestChild()
   : mCallback(nullptr)
@@ -98,25 +98,22 @@ DeviceStorageRequestChild::
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TBlobResponse:
     {
       BlobResponse r = aValue;
       BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
-      nsRefPtr<FileImpl> bloblImpl = actor->GetBlobImpl();
-      nsRefPtr<File> blob = new File(mRequest->GetParentObject(), bloblImpl);
-
-      AutoJSContext cx;
+      nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob();
 
-      JS::Rooted<JSObject*> obj(cx, blob->WrapObject(cx));
-      MOZ_ASSERT(obj);
-
-      JS::Rooted<JS::Value> result(cx, JS::ObjectValue(*obj));
+      nsCOMPtr<nsIDOMFile> file = do_QueryInterface(blob);
+      AutoJSContext cx;
+      JS::Rooted<JS::Value> result(cx,
+        InterfaceToJsval(window, file, &NS_GET_IID(nsIDOMFile)));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TFreeSpaceStorageResponse:
     {
       FreeSpaceStorageResponse r = aValue;
       AutoJSContext cx;
--- a/dom/devicestorage/DeviceStorageRequestParent.cpp
+++ b/dom/devicestorage/DeviceStorageRequestParent.cpp
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; 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 "DeviceStorageRequestParent.h"
+#include "nsDOMFile.h"
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "mozilla/unused.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "ContentParent.h"
 #include "nsProxyRelease.h"
 #include "AppProcessChecker.h"
 #include "mozilla/Preferences.h"
 #include "nsNetCID.h"
 
 namespace mozilla {
@@ -39,20 +39,20 @@ DeviceStorageRequestParent::Dispatch()
     case DeviceStorageParams::TDeviceStorageAddParams:
     {
       DeviceStorageAddParams p = mParams;
 
       nsRefPtr<DeviceStorageFile> dsf =
         new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
 
       BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
-      nsRefPtr<FileImpl> blobImpl = bp->GetBlobImpl();
+      nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob();
 
       nsCOMPtr<nsIInputStream> stream;
-      blobImpl->GetInternalStream(getter_AddRefs(stream));
+      blob->GetInternalStream(getter_AddRefs(stream));
 
       nsRefPtr<CancelableRunnable> r = new WriteFileEvent(this, dsf, stream,
                                                           DEVICE_STORAGE_REQUEST_CREATE);
 
       nsCOMPtr<nsIEventTarget> target
         = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       MOZ_ASSERT(target);
       target->Dispatch(r, NS_DISPATCH_NORMAL);
@@ -62,20 +62,20 @@ DeviceStorageRequestParent::Dispatch()
     case DeviceStorageParams::TDeviceStorageAppendParams:
     {
       DeviceStorageAppendParams p = mParams;
 
       nsRefPtr<DeviceStorageFile> dsf =
         new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
 
       BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
-      nsRefPtr<FileImpl> blobImpl = bp->GetBlobImpl();
+      nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob();
 
       nsCOMPtr<nsIInputStream> stream;
-      blobImpl->GetInternalStream(getter_AddRefs(stream));
+      blob->GetInternalStream(getter_AddRefs(stream));
 
       nsRefPtr<CancelableRunnable> r = new WriteFileEvent(this, dsf, stream,
                                                           DEVICE_STORAGE_REQUEST_APPEND);
 
       nsCOMPtr<nsIEventTarget> target
         = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       MOZ_ASSERT(target);
       target->Dispatch(r, NS_DISPATCH_NORMAL);
@@ -517,19 +517,19 @@ nsresult
 DeviceStorageRequestParent::PostBlobSuccessEvent::CancelableRun() {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsString mime;
   CopyASCIItoUTF16(mMimeType, mime);
 
   nsString fullPath;
   mFile->GetFullPath(fullPath);
-  nsRefPtr<File> blob = new File(nullptr,
-    new FileImplFile(fullPath, mime, mLength, mFile->mFile,
-                     mLastModificationDate));
+  nsCOMPtr<nsIDOMBlob> blob = new DOMFile(
+    new DOMFileImplFile(fullPath, mime, mLength, mFile->mFile,
+                        mLastModificationDate));
 
   ContentParent* cp = static_cast<ContentParent*>(mParent->Manager());
   BlobParent* actor = cp->GetOrCreateActorForBlob(blob);
   if (!actor) {
     ErrorResponse response(NS_LITERAL_STRING(POST_ERROR_EVENT_UNKNOWN));
     unused << mParent->Send__delete__(mParent, response);
     return NS_OK;
   }
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -31,16 +31,18 @@
 #include "nsArrayUtils.h"
 #include "nsAutoPtr.h"
 #include "nsGlobalWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIFile.h"
 #include "nsIDirectoryEnumerator.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
+#include "nsIDOMFile.h"
+#include "nsDOMBlobBuilder.h"
 #include "nsNetUtil.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIPrincipal.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsXULAppAPI.h"
 #include "DeviceStorageFileDescriptor.h"
 #include "DeviceStorageRequestChild.h"
@@ -1798,20 +1800,20 @@ nsIFileToJsval(nsPIDOMWindow* aWindow, D
   aFile->GetFullPath(fullPath);
 
   // This check is useful to know if somewhere the DeviceStorageFile
   // has not been properly set. Mimetype is not checked because it can be
   // empty.
   MOZ_ASSERT(aFile->mLength != UINT64_MAX);
   MOZ_ASSERT(aFile->mLastModifiedDate != UINT64_MAX);
 
-  nsCOMPtr<nsIDOMBlob> blob = new File(aWindow,
-    new FileImplFile(fullPath, aFile->mMimeType,
-                     aFile->mLength, aFile->mFile,
-                     aFile->mLastModifiedDate));
+  nsCOMPtr<nsIDOMBlob> blob = new DOMFile(
+    new DOMFileImplFile(fullPath, aFile->mMimeType,
+                        aFile->mLength, aFile->mFile,
+                        aFile->mLastModifiedDate));
   return InterfaceToJsval(aWindow, blob, &NS_GET_IID(nsIDOMBlob));
 }
 
 bool
 StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString,
               JS::MutableHandle<JS::Value> result)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -2473,17 +2475,17 @@ public:
 private:
   nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
   nsRefPtr<DOMRequest> mRequest;
 };
 
 class WriteFileEvent : public nsRunnable
 {
 public:
-  WriteFileEvent(FileImpl* aBlobImpl,
+  WriteFileEvent(DOMFileImpl* aBlobImpl,
                  DeviceStorageFile *aFile,
                  already_AddRefed<DOMRequest> aRequest,
                  int32_t aRequestType)
     : mBlobImpl(aBlobImpl)
     , mFile(aFile)
     , mRequest(aRequest)
     , mRequestType(aRequestType)
   {
@@ -2539,17 +2541,17 @@ public:
     nsString fullPath;
     mFile->GetFullPath(fullPath);
     nsCOMPtr<nsIRunnable> event =
       new PostResultEvent(mRequest.forget(), fullPath);
     return NS_DispatchToMainThread(event);
   }
 
 private:
-  nsRefPtr<FileImpl> mBlobImpl;
+  nsRefPtr<DOMFileImpl> mBlobImpl;
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
   int32_t mRequestType;
 };
 
 
 class ReadFileEvent : public nsRunnable
 {
@@ -2907,18 +2909,17 @@ public:
             !typeChecker->Check(mFile->mStorageType, mBlob)) {
           r = new PostErrorEvent(mRequest.forget(),
                                  POST_ERROR_EVENT_ILLEGAL_TYPE);
           return NS_DispatchToCurrentThread(r);
         }
 
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
           BlobChild* actor
-            = ContentChild::GetSingleton()->GetOrCreateActorForBlob(
-              static_cast<File*>(mBlob.get()));
+            = ContentChild::GetSingleton()->GetOrCreateActorForBlob(mBlob);
           if (!actor) {
             return NS_ERROR_FAILURE;
           }
 
           DeviceStorageAddParams params;
           params.blobChild() = actor;
           params.type() = mFile->mStorageType;
           params.storageName() = mFile->mStorageName;
@@ -2926,17 +2927,17 @@ public:
 
           PDeviceStorageRequestChild* child
             = new DeviceStorageRequestChild(mRequest, mFile);
           ContentChild::GetSingleton()
             ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
 
-        File* blob = static_cast<File*>(mBlob.get());
+        DOMFile* blob = static_cast<DOMFile*>(mBlob.get());
         r = new WriteFileEvent(blob->Impl(), mFile, mRequest.forget(),
                                mRequestType);
         break;
       }
 
       case DEVICE_STORAGE_REQUEST_APPEND:
       {
         if (!mBlob || !mFile->mFile) {
@@ -2953,18 +2954,17 @@ public:
             !typeChecker->Check(mFile->mStorageType, mBlob)) {
           r = new PostErrorEvent(mRequest.forget(),
                                  POST_ERROR_EVENT_ILLEGAL_TYPE);
           return NS_DispatchToCurrentThread(r);
         }
 
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
           BlobChild* actor
-            = ContentChild::GetSingleton()->GetOrCreateActorForBlob(
-              static_cast<File*>(mBlob.get()));
+            = ContentChild::GetSingleton()->GetOrCreateActorForBlob(mBlob);
           if (!actor) {
             return NS_ERROR_FAILURE;
           }
 
           DeviceStorageAppendParams params;
           params.blobChild() = actor;
           params.type() = mFile->mStorageType;
           params.storageName() = mFile->mStorageName;
@@ -2972,17 +2972,17 @@ public:
 
           PDeviceStorageRequestChild* child
             = new DeviceStorageRequestChild(mRequest, mFile);
           ContentChild::GetSingleton()
             ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
 
-        File* blob = static_cast<File*>(mBlob.get());
+        DOMFile* blob = static_cast<DOMFile*>(mBlob.get());
         r = new WriteFileEvent(blob->Impl(), mFile, mRequest.forget(),
                                mRequestType);
         break;
       }
 
       case DEVICE_STORAGE_REQUEST_READ:
       case DEVICE_STORAGE_REQUEST_WRITE:
       {
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -264,26 +264,26 @@ DataTransfer::SetEffectAllowedInt(uint32
 
 NS_IMETHODIMP
 DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
 {
   *aUserCancelled = MozUserCancelled();
   return NS_OK;
 }
 
-FileList*
+nsDOMFileList*
 DataTransfer::GetFiles(ErrorResult& aRv)
 {
   if (mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP &&
       mEventType != NS_PASTE) {
     return nullptr;
   }
 
   if (!mFiles) {
-    mFiles = new FileList(static_cast<nsIDOMDataTransfer*>(this));
+    mFiles = new nsDOMFileList(static_cast<nsIDOMDataTransfer*>(this));
 
     uint32_t count = mItems.Length();
 
     for (uint32_t i = 0; i < count; i++) {
       nsCOMPtr<nsIVariant> variant;
       aRv = MozGetDataAt(NS_ConvertUTF8toUTF16(kFileMime), i, getter_AddRefs(variant));
       if (aRv.Failed()) {
         return nullptr;
@@ -298,17 +298,17 @@ DataTransfer::GetFiles(ErrorResult& aRv)
       if (NS_FAILED(rv))
         continue;
 
       nsCOMPtr<nsIFile> file = do_QueryInterface(supports);
 
       if (!file)
         continue;
 
-      nsRefPtr<File> domFile = File::CreateFromFile(GetParentObject(), file);
+      nsRefPtr<DOMFile> domFile = DOMFile::CreateFromFile(file);
 
       if (!mFiles->Append(domFile)) {
         aRv.Throw(NS_ERROR_FAILURE);
         return nullptr;
       }
     }
   }
 
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -11,18 +11,18 @@
 #include "nsIVariant.h"
 #include "nsIPrincipal.h"
 #include "nsIDOMDataTransfer.h"
 #include "nsIDOMElement.h"
 #include "nsIDragService.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsAutoPtr.h"
+#include "nsDOMFile.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/File.h"
 
 class nsINode;
 class nsITransferable;
 class nsISupportsArray;
 class nsILoadContext;
 
 namespace mozilla {
 
@@ -138,17 +138,17 @@ public:
   void SetDragImage(Element& aElement, int32_t aX, int32_t aY,
                     ErrorResult& aRv);
   already_AddRefed<DOMStringList> Types();
   void GetData(const nsAString& aFormat, nsAString& aData, ErrorResult& aRv);
   void SetData(const nsAString& aFormat, const nsAString& aData,
                ErrorResult& aRv);
   void ClearData(const mozilla::dom::Optional<nsAString>& aFormat,
                  mozilla::ErrorResult& aRv);
-  FileList* GetFiles(mozilla::ErrorResult& aRv);
+  nsDOMFileList* GetFiles(mozilla::ErrorResult& aRv);
   void AddElement(Element& aElement, mozilla::ErrorResult& aRv);
   uint32_t MozItemCount()
   {
     return mItems.Length();
   }
   void GetMozCursor(nsString& aCursor)
   {
     if (mCursorState) {
@@ -273,17 +273,17 @@ protected:
   // Indicates which clipboard type to use for clipboard operations. Ignored for
   // drag and drop.
   int32_t mClipboardType;
 
   // array of items, each containing an array of format->data pairs
   nsTArray<nsTArray<TransferItem> > mItems;
 
   // array of files, containing only the files present in the dataTransfer
-  nsRefPtr<FileList> mFiles;
+  nsRefPtr<nsDOMFileList> mFiles;
 
   // the target of the drag. The drag and dragend events will fire at this.
   nsCOMPtr<mozilla::dom::Element> mDragTarget;
 
   // the custom drag image and coordinates within the image. If mDragImage is
   // null, the default image is created from the drag target.
   nsCOMPtr<mozilla::dom::Element> mDragImage;
   uint32_t mDragImageX;
--- a/dom/events/test/test_eventctors.html
+++ b/dom/events/test/test_eventctors.html
@@ -198,17 +198,17 @@ ok(ex, "Shouldn't be able to re-define t
 ex = false;
 ok(!e.isTrusted, "BlobEvent shouldn't be trusted!");
 
 ok(!e.bubbles, "Event shouldn't bubble!");
 ok(!e.cancelable, "Event shouldn't be cancelable!");
 document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
 
-var blob = new Blob();
+var blob = Blob();
 e = new BlobEvent("hello", { bubbles: true, cancelable: true, data: blob });
 is(e.type, "hello", "Wrong event type!");
 ok(!e.isTrusted, "Event shouldn't be trusted!");
 ok(e.bubbles, "Event should bubble!");
 ok(e.cancelable, "Event should be cancelable!");
 is(e.data, blob , "Wrong event.data!");
 document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -3,32 +3,33 @@
  * 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 "Request.h"
 
 #include "nsIUnicodeDecoder.h"
 #include "nsIURI.h"
 
+#include "nsDOMFile.h"
 #include "nsDOMString.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "nsStreamUtils.h"
 #include "nsStringStream.h"
 
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/EncodingUtils.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/Headers.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/URL.h"
 #include "mozilla/dom/workers/bindings/URL.h"
 
 // dom/workers
+#include "File.h"
 #include "WorkerPrivate.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner)
@@ -352,27 +353,36 @@ Request::ConsumeBody(ConsumeType aType, 
       // XXXnsm it is actually possible to avoid these duplicate allocations
       // for the Blob case by having the Blob adopt the stream's memory
       // directly, but I've not added a special case for now.
       //
       // This is similar to nsContentUtils::CreateBlobBuffer, but also deals
       // with worker wrapping.
       uint32_t blobLen = buffer.Length();
       void* blobData = moz_malloc(blobLen);
-      nsRefPtr<File> blob;
+      nsCOMPtr<nsIDOMBlob> blob;
       if (blobData) {
         memcpy(blobData, buffer.BeginReading(), blobLen);
-        blob = File::CreateMemoryFile(GetParentObject(), blobData, blobLen,
-                                      NS_ConvertUTF8toUTF16(mMimeType));
+        blob = DOMFile::CreateMemoryFile(blobData, blobLen,
+                                         NS_ConvertUTF8toUTF16(mMimeType));
       } else {
         aRv = NS_ERROR_OUT_OF_MEMORY;
         return nullptr;
       }
 
-      promise->MaybeResolve(blob);
+      JS::Rooted<JS::Value> jsBlob(cx);
+      if (NS_IsMainThread()) {
+        aRv = nsContentUtils::WrapNative(cx, blob, &jsBlob);
+        if (aRv.Failed()) {
+          return nullptr;
+        }
+      } else {
+        jsBlob.setObject(*workers::file::CreateBlob(cx, blob));
+      }
+      promise->MaybeResolve(cx, jsBlob);
       return promise.forget();
     }
     case CONSUME_JSON: {
       nsString decoded;
       aRv = DecodeUTF8(buffer, decoded);
       if (aRv.Failed()) {
         return nullptr;
       }
--- a/dom/filehandle/FileHandle.cpp
+++ b/dom/filehandle/FileHandle.cpp
@@ -8,21 +8,21 @@
 
 #include "AsyncHelper.h"
 #include "FileHelper.h"
 #include "FileRequest.h"
 #include "FileService.h"
 #include "FileStreamWrappers.h"
 #include "MemoryStreams.h"
 #include "mozilla/dom/EncodingUtils.h"
-#include "mozilla/dom/File.h"
 #include "MutableFile.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsError.h"
+#include "nsIDOMFile.h"
 #include "nsIEventTarget.h"
 #include "nsISeekableStream.h"
 #include "nsNetUtil.h"
 #include "nsString.h"
 #include "nsStringStream.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
@@ -617,27 +617,27 @@ FileHandleBase::GetInputStream(const Arr
   }
 
   *aInputLength = length;
   return stream.forget();
 }
 
 // static
 already_AddRefed<nsIInputStream>
-FileHandleBase::GetInputStream(const File& aValue, uint64_t* aInputLength,
+FileHandleBase::GetInputStream(nsIDOMBlob* aValue, uint64_t* aInputLength,
                                ErrorResult& aRv)
 {
-  File& file = const_cast<File&>(aValue);
-  uint64_t length = file.GetSize(aRv);
+  uint64_t length;
+  aRv = aValue->GetSize(&length);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   nsCOMPtr<nsIInputStream> stream;
-  aRv = file.GetInternalStream(getter_AddRefs(stream));
+  aRv = aValue->GetInternalStream(getter_AddRefs(stream));
   if (aRv.Failed()) {
     return nullptr;
   }
 
   *aInputLength = length;
   return stream.forget();
 }
 
--- a/dom/filehandle/FileHandle.h
+++ b/dom/filehandle/FileHandle.h
@@ -16,21 +16,21 @@
 #include "mozilla/ErrorResult.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIInputStream.h"
 #include "nsIRunnable.h"
 #include "nsTArray.h"
 
 class nsAString;
+class nsIDOMBlob;
 
 namespace mozilla {
 namespace dom {
 
-class File;
 class FileHelper;
 class FileRequestBase;
 class FileService;
 class FinishHelper;
 class MetadataHelper;
 class MutableFileBase;
 
 /**
@@ -235,18 +235,17 @@ protected:
   nsresult
   Finish();
 
   static already_AddRefed<nsIInputStream>
   GetInputStream(const ArrayBuffer& aValue, uint64_t* aInputLength,
                  ErrorResult& aRv);
 
   static already_AddRefed<nsIInputStream>
-  GetInputStream(const File& aValue, uint64_t* aInputLength,
-                 ErrorResult& aRv);
+  GetInputStream(nsIDOMBlob* aValue, uint64_t* aInputLength, ErrorResult& aRv);
 
   static already_AddRefed<nsIInputStream>
   GetInputStream(const nsAString& aValue, uint64_t* aInputLength,
                  ErrorResult& aRv);
 };
 
 class FinishHelper MOZ_FINAL : public nsIRunnable
 {
--- a/dom/filesystem/CreateFileTask.cpp
+++ b/dom/filesystem/CreateFileTask.cpp
@@ -5,34 +5,34 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CreateFileTask.h"
 
 #include <algorithm>
 
 #include "DOMError.h"
 #include "mozilla/Preferences.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/FileSystemBase.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/ipc/BlobParent.h"
+#include "nsDOMFile.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsStringGlue.h"
 
 namespace mozilla {
 namespace dom {
 
 uint32_t CreateFileTask::sOutputBufferSize = 0;
 
 CreateFileTask::CreateFileTask(FileSystemBase* aFileSystem,
                                const nsAString& aPath,
-                               File* aBlobData,
+                               nsIDOMBlob* aBlobData,
                                InfallibleTArray<uint8_t>& aArrayData,
                                bool replace,
                                ErrorResult& aRv)
   : FileSystemTaskBase(aFileSystem)
   , mTargetRealPath(aPath)
   , mReplace(replace)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
@@ -74,20 +74,19 @@ CreateFileTask::CreateFileTask(FileSyste
   auto& data = aParam.data();
 
   if (data.type() == FileSystemFileDataValue::TArrayOfuint8_t) {
     mArrayData = data;
     return;
   }
 
   BlobParent* bp = static_cast<BlobParent*>(static_cast<PBlobParent*>(data));
-  nsRefPtr<FileImpl> blobImpl = bp->GetBlobImpl();
-  MOZ_ASSERT(blobImpl, "blobData should not be null.");
-
-  nsresult rv = blobImpl->GetInternalStream(getter_AddRefs(mBlobStream));
+  nsCOMPtr<nsIDOMBlob> blobData = bp->GetBlob();
+  MOZ_ASSERT(blobData, "blobData should not be null.");
+  nsresult rv = blobData->GetInternalStream(getter_AddRefs(mBlobStream));
   NS_WARN_IF(NS_FAILED(rv));
 }
 
 CreateFileTask::~CreateFileTask()
 {
   MOZ_ASSERT((!mPromise && !mBlobData) || NS_IsMainThread(),
              "mPromise and mBlobData should be released on main thread!");
 
@@ -122,34 +121,34 @@ CreateFileTask::GetRequestParams(const n
   }
   return param;
 }
 
 FileSystemResponseValue
 CreateFileTask::GetSuccessRequestResult() const
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
-  nsRefPtr<File> file = new File(mFileSystem->GetWindow(),
-                                       mTargetFileImpl);
+  nsRefPtr<DOMFile> file = new DOMFile(mTargetFileImpl);
   BlobParent* actor = GetBlobParent(file);
   if (!actor) {
     return FileSystemErrorResponse(NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR);
   }
   FileSystemFileResponse response;
   response.blobParent() = actor;
   return response;
 }
 
 void
 CreateFileTask::SetSuccessRequestResult(const FileSystemResponseValue& aValue)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   FileSystemFileResponse r = aValue;
   BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
-  mTargetFileImpl = actor->GetBlobImpl();
+  nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob();
+  mTargetFileImpl = static_cast<DOMFile*>(blob.get())->Impl();
 }
 
 nsresult
 CreateFileTask::Work()
 {
   class AutoClose
   {
   public:
@@ -256,17 +255,17 @@ CreateFileTask::Work()
 
     mBlobStream->Close();
     mBlobStream = nullptr;
 
     if (mFileSystem->IsShutdown()) {
       return NS_ERROR_FAILURE;
     }
 
-    mTargetFileImpl = new FileImplFile(file);
+    mTargetFileImpl = new DOMFileImplFile(file);
     return NS_OK;
   }
 
   // Write file content from array data.
 
   uint32_t written;
   rv = bufferedOutputStream->Write(
     reinterpret_cast<char*>(mArrayData.Elements()),
@@ -275,17 +274,17 @@ CreateFileTask::Work()
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (mArrayData.Length() != written) {
     return NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR;
   }
 
-  mTargetFileImpl = new FileImplFile(file);
+  mTargetFileImpl = new DOMFileImplFile(file);
   return NS_OK;
 }
 
 void
 CreateFileTask::HandlerCallback()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   if (mFileSystem->IsShutdown()) {
@@ -298,17 +297,17 @@ CreateFileTask::HandlerCallback()
     nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
       mErrorValue);
     mPromise->MaybeRejectBrokenly(domError);
     mPromise = nullptr;
     mBlobData = nullptr;
     return;
   }
 
-  nsCOMPtr<nsIDOMFile> file = new File(mFileSystem->GetWindow(), mTargetFileImpl);
+  nsCOMPtr<nsIDOMFile> file = new DOMFile(mTargetFileImpl);
   mPromise->MaybeResolve(file);
   mPromise = nullptr;
   mBlobData = nullptr;
 }
 
 void
 CreateFileTask::GetPermissionAccessType(nsCString& aAccess) const
 {
--- a/dom/filesystem/CreateFileTask.h
+++ b/dom/filesystem/CreateFileTask.h
@@ -6,32 +6,32 @@
 
 #ifndef mozilla_dom_CreateFileTask_h
 #define mozilla_dom_CreateFileTask_h
 
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "nsAutoPtr.h"
 #include "mozilla/ErrorResult.h"
 
+class nsIDOMBlob;
 class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 
-class File;
-class FileImpl;
+class DOMFileImpl;
 class Promise;
 
 class CreateFileTask MOZ_FINAL
   : public FileSystemTaskBase
 {
 public:
   CreateFileTask(FileSystemBase* aFileSystem,
                  const nsAString& aPath,
-                 File* aBlobData,
+                 nsIDOMBlob* aBlobData,
                  InfallibleTArray<uint8_t>& aArrayData,
                  bool replace,
                  ErrorResult& aRv);
   CreateFileTask(FileSystemBase* aFileSystem,
                  const FileSystemCreateFileParams& aParam,
                  FileSystemRequestParent* aParent);
 
   virtual
@@ -63,23 +63,23 @@ private:
   void
   GetOutputBufferSize() const;
 
   static uint32_t sOutputBufferSize;
   nsRefPtr<Promise> mPromise;
   nsString mTargetRealPath;
 
   // Not thread-safe and should be released on main thread.
-  nsRefPtr<File> mBlobData;
+  nsCOMPtr<nsIDOMBlob> mBlobData;
 
   nsCOMPtr<nsIInputStream> mBlobStream;
   InfallibleTArray<uint8_t> mArrayData;
   bool mReplace;
 
-  // This cannot be a File because this object is created on a different
-  // thread and File is not thread-safe. Let's use the FileImpl instead.
-  nsRefPtr<FileImpl> mTargetFileImpl;
+  // This cannot be a DOMFile because this object is created on a different
+  // thread and DOMFile is not thread-safe. Let's use the DOMFileImpl instead.
+  nsRefPtr<DOMFileImpl> mTargetFileImpl;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_CreateFileTask_h
--- a/dom/filesystem/DeviceStorageFileSystem.cpp
+++ b/dom/filesystem/DeviceStorageFileSystem.cpp
@@ -4,21 +4,21 @@
  * 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 "mozilla/dom/DeviceStorageFileSystem.h"
 
 #include "DeviceStorage.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Directory.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsDeviceStorage.h"
+#include "nsDOMFile.h"
 #include "nsIFile.h"
 #include "nsPIDOMWindow.h"
 
 namespace mozilla {
 namespace dom {
 
 DeviceStorageFileSystem::DeviceStorageFileSystem(
   const nsAString& aStorageType,
@@ -109,28 +109,26 @@ DeviceStorageFileSystem::GetLocalFile(co
   nsresult rv = NS_NewLocalFile(localPath, false, getter_AddRefs(file));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return nullptr;
   }
   return file.forget();
 }
 
 bool
-DeviceStorageFileSystem::GetRealPath(FileImpl* aFile, nsAString& aRealPath) const
+DeviceStorageFileSystem::GetRealPath(DOMFileImpl* aFile, nsAString& aRealPath) const
 {
   MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
              "Should be on parent process!");
   MOZ_ASSERT(aFile, "aFile Should not be null.");
 
   aRealPath.Truncate();
 
   nsAutoString filePath;
-  ErrorResult rv;
-  aFile->GetMozFullPathInternal(filePath, rv);
-  if (NS_WARN_IF(rv.Failed())) {
+  if (NS_FAILED(aFile->GetMozFullPathInternal(filePath))) {
     return false;
   }
 
   return LocalPathToRealPath(filePath, aRealPath);
 }
 
 const nsAString&
 DeviceStorageFileSystem::GetRootName() const
--- a/dom/filesystem/DeviceStorageFileSystem.h
+++ b/dom/filesystem/DeviceStorageFileSystem.h
@@ -32,17 +32,17 @@ public:
 
   virtual nsPIDOMWindow*
   GetWindow() const MOZ_OVERRIDE;
 
   virtual already_AddRefed<nsIFile>
   GetLocalFile(const nsAString& aRealPath) const MOZ_OVERRIDE;
 
   virtual bool
-  GetRealPath(FileImpl* aFile, nsAString& aRealPath) const MOZ_OVERRIDE;
+  GetRealPath(DOMFileImpl* aFile, nsAString& aRealPath) const MOZ_OVERRIDE;
 
   virtual const nsAString&
   GetRootName() const MOZ_OVERRIDE;
 
   virtual bool
   IsSafeFile(nsIFile* aFile) const MOZ_OVERRIDE;
 
   virtual bool
--- a/dom/filesystem/Directory.cpp
+++ b/dom/filesystem/Directory.cpp
@@ -96,17 +96,17 @@ Directory::GetName(nsString& aRetval) co
 }
 
 already_AddRefed<Promise>
 Directory::CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions,
                       ErrorResult& aRv)
 {
   nsresult error = NS_OK;
   nsString realPath;
-  nsRefPtr<File> blobData;
+  nsRefPtr<nsIDOMBlob> blobData;
   InfallibleTArray<uint8_t> arrayData;
   bool replace = (aOptions.mIfExists == CreateIfExistsMode::Replace);
 
   // Get the file content.
   if (aOptions.mData.WasPassed()) {
     auto& data = aOptions.mData.Value();
     if (data.IsString()) {
       NS_ConvertUTF16toUTF8 str(data.GetAsString());
@@ -124,18 +124,18 @@ Directory::CreateFile(const nsAString& a
       blobData = data.GetAsBlob();
     }
   }
 
   if (!DOMPathToRealPath(aPath, realPath)) {
     error = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
   }
 
-  nsRefPtr<CreateFileTask> task =
-    new CreateFileTask(mFileSystem, realPath, blobData, arrayData, replace, aRv);
+  nsRefPtr<CreateFileTask> task = new CreateFileTask(mFileSystem, realPath,
+    blobData, arrayData, replace, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
   task->SetError(error);
   FileSystemPermissionRequest::RequestForTask(task);
   return task->GetPromise();
 }
 
@@ -188,22 +188,22 @@ Directory::RemoveDeep(const StringOrFile
 }
 
 already_AddRefed<Promise>
 Directory::RemoveInternal(const StringOrFileOrDirectory& aPath, bool aRecursive,
                           ErrorResult& aRv)
 {
   nsresult error = NS_OK;
   nsString realPath;
-  nsRefPtr<FileImpl> file;
+  nsRefPtr<DOMFileImpl> file;
 
   // Check and get the target path.
 
   if (aPath.IsFile()) {
-    file = aPath.GetAsFile().Impl();
+    file = static_cast<DOMFile*>(aPath.GetAsFile())->Impl();
     goto parameters_check_done;
   }
 
   if (aPath.IsString()) {
     if (!DOMPathToRealPath(aPath.GetAsString(), realPath)) {
       error = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
     }
     goto parameters_check_done;
--- a/dom/filesystem/Directory.h
+++ b/dom/filesystem/Directory.h
@@ -5,19 +5,19 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Directory_h
 #define mozilla_dom_Directory_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/File.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsDOMFile.h"
 #include "nsPIDOMWindow.h"
 #include "nsWrapperCache.h"
 
 // Resolve the name collision of Microsoft's API name with macros defined in
 // Windows header files. Undefine the macro of CreateDirectory to avoid
 // Directory#CreateDirectory being replaced by Directory#CreateDirectoryW.
 #ifdef CreateDirectory
 #undef CreateDirectory
--- a/dom/filesystem/FileSystemBase.h
+++ b/dom/filesystem/FileSystemBase.h
@@ -11,17 +11,17 @@
 #include "nsString.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class Directory;
-class FileImpl;
+class DOMFileImpl;
 
 class FileSystemBase
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileSystemBase)
 public:
 
   // Create file system object from its string representation.
   static already_AddRefed<FileSystemBase>
@@ -68,17 +68,17 @@ public:
   IsSafeDirectory(Directory* aDir) const;
 
   /*
    * Get the real path (absolute DOM path) of the DOM file in the file system.
    * If succeeded, returns true. Otherwise, returns false and set aRealPath to
    * empty string.
    */
   virtual bool
-  GetRealPath(FileImpl* aFile, nsAString& aRealPath) const = 0;
+  GetRealPath(DOMFileImpl* aFile, nsAString& aRealPath) const = 0;
 
   /*
    * Get the permission name required to access this file system.
    */
   const nsCString&
   GetPermission() const
   {
     return mPermission;
--- a/dom/filesystem/FileSystemTaskBase.cpp
+++ b/dom/filesystem/FileSystemTaskBase.cpp
@@ -3,24 +3,24 @@
 /* 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 "mozilla/dom/FileSystemTaskBase.h"
 
 #include "nsNetUtil.h" // Stream transport service.
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/FileSystemBase.h"
 #include "mozilla/dom/FileSystemRequestParent.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PContent.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/unused.h"
+#include "nsDOMFile.h"
 
 namespace mozilla {
 namespace dom {
 
 FileSystemTaskBase::FileSystemTaskBase(FileSystemBase* aFileSystem)
   : mErrorValue(NS_OK)
   , mFileSystem(aFileSystem)
 {
@@ -165,17 +165,17 @@ FileSystemTaskBase::GetBlobParent(nsIDOM
   nsString mimeType;
   aFile->GetType(mimeType);
   uint64_t fileSize;
   aFile->GetSize(&fileSize);
   uint64_t lastModifiedDate;
   aFile->GetMozLastModifiedDate(&lastModifiedDate);
 
   ContentParent* cp = static_cast<ContentParent*>(mRequestParent->Manager());
-  return cp->GetOrCreateActorForBlob(static_cast<File*>(aFile));
+  return cp->GetOrCreateActorForBlob(aFile);
 }
 
 void
 FileSystemTaskBase::SetError(const nsresult& aErrorValue)
 {
   uint16_t module = NS_ERROR_GET_MODULE(aErrorValue);
   if (module == NS_ERROR_MODULE_DOM_FILESYSTEM ||
       module == NS_ERROR_MODULE_DOM_FILE ||
--- a/dom/filesystem/GetFileOrDirectoryTask.cpp
+++ b/dom/filesystem/GetFileOrDirectoryTask.cpp
@@ -3,23 +3,22 @@
 /* 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 "GetFileOrDirectoryTask.h"
 
 #include "js/Value.h"
 #include "mozilla/dom/Directory.h"
-#include "mozilla/dom/DOMError.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/FileSystemBase.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/ipc/BlobParent.h"
+#include "nsDOMFile.h"
 #include "nsIFile.h"
 #include "nsStringGlue.h"
 
 namespace mozilla {
 namespace dom {
 
 GetFileOrDirectoryTask::GetFileOrDirectoryTask(
   FileSystemBase* aFileSystem,
@@ -77,17 +76,17 @@ GetFileOrDirectoryTask::GetRequestParams
 FileSystemResponseValue
 GetFileOrDirectoryTask::GetSuccessRequestResult() const
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   if (mIsDirectory) {
     return FileSystemDirectoryResponse(mTargetRealPath);
   }
 
-  nsRefPtr<File> file = new File(mFileSystem->GetWindow(), mTargetFileImpl);
+  nsRefPtr<DOMFile> file = new DOMFile(mTargetFileImpl);
   BlobParent* actor = GetBlobParent(file);
   if (!actor) {
     return FileSystemErrorResponse(NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR);
   }
   FileSystemFileResponse response;
   response.blobParent() = actor;
   return response;
 }
@@ -95,17 +94,18 @@ GetFileOrDirectoryTask::GetSuccessReques
 void
 GetFileOrDirectoryTask::SetSuccessRequestResult(const FileSystemResponseValue& aValue)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   switch (aValue.type()) {
     case FileSystemResponseValue::TFileSystemFileResponse: {
       FileSystemFileResponse r = aValue;
       BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
-      mTargetFileImpl = actor->GetBlobImpl();
+      nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob();
+      mTargetFileImpl = static_cast<DOMFile*>(blob.get())->Impl();
       mIsDirectory = false;
       break;
     }
     case FileSystemResponseValue::TFileSystemDirectoryResponse: {
       FileSystemDirectoryResponse r = aValue;
       mTargetRealPath = r.realPath();
       mIsDirectory = true;
       break;
@@ -180,17 +180,17 @@ GetFileOrDirectoryTask::Work()
     // Neither directory or file.
     return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
   }
 
   if (!mFileSystem->IsSafeFile(file)) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  mTargetFileImpl = new FileImplFile(file);
+  mTargetFileImpl = new DOMFileImplFile(file);
 
   return NS_OK;
 }
 
 void
 GetFileOrDirectoryTask::HandlerCallback()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
@@ -209,17 +209,17 @@ GetFileOrDirectoryTask::HandlerCallback(
 
   if (mIsDirectory) {
     nsRefPtr<Directory> dir = new Directory(mFileSystem, mTargetRealPath);
     mPromise->MaybeResolve(dir);
     mPromise = nullptr;
     return;
   }
 
-  nsRefPtr<File> file = new File(mFileSystem->GetWindow(), mTargetFileImpl);
+  nsCOMPtr<nsIDOMFile> file = new DOMFile(mTargetFileImpl);
   mPromise->MaybeResolve(file);
   mPromise = nullptr;
 }
 
 void
 GetFileOrDirectoryTask::GetPermissionAccessType(nsCString& aAccess) const
 {
   aAccess.AssignLiteral("read");
--- a/dom/filesystem/GetFileOrDirectoryTask.h
+++ b/dom/filesystem/GetFileOrDirectoryTask.h
@@ -9,17 +9,17 @@
 
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "nsAutoPtr.h"
 #include "mozilla/ErrorResult.h"
 
 namespace mozilla {
 namespace dom {
 
-class FileImpl;
+class DOMFileImpl;
 
 class GetFileOrDirectoryTask MOZ_FINAL
   : public FileSystemTaskBase
 {
 public:
   // If aDirectoryOnly is set, we should ensure that the target is a directory.
   GetFileOrDirectoryTask(FileSystemBase* aFileSystem,
                          const nsAString& aTargetPath,
@@ -54,17 +54,17 @@ protected:
   HandlerCallback() MOZ_OVERRIDE;
 
 private:
   nsRefPtr<Promise> mPromise;
   nsString mTargetRealPath;
   // Whether we get a directory.
   bool mIsDirectory;
 
-  // This cannot be a File bacause this object is created on a different
-  // thread and File is not thread-safe. Let's use the FileImpl instead.
-  nsRefPtr<FileImpl> mTargetFileImpl;
+  // This cannot be a DOMFile bacause this object is created on a different
+  // thread and DOMFile is not thread-safe. Let's use the DOMFileImpl instead.
+  nsRefPtr<DOMFileImpl> mTargetFileImpl;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_GetFileOrDirectory_h
--- a/dom/filesystem/RemoveTask.cpp
+++ b/dom/filesystem/RemoveTask.cpp
@@ -2,31 +2,31 @@
 /* vim: set ts=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 "RemoveTask.h"
 
 #include "DOMError.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/FileSystemBase.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/ipc/BlobParent.h"
+#include "nsDOMFile.h"
 #include "nsIFile.h"
 #include "nsStringGlue.h"
 
 namespace mozilla {
 namespace dom {
 
 RemoveTask::RemoveTask(FileSystemBase* aFileSystem,
                        const nsAString& aDirPath,
-                       FileImpl* aTargetFile,
+                       DOMFileImpl* aTargetFile,
                        const nsAString& aTargetPath,
                        bool aRecursive,
                        ErrorResult& aRv)
   : FileSystemTaskBase(aFileSystem)
   , mDirRealPath(aDirPath)
   , mTargetFileImpl(aTargetFile)
   , mTargetRealPath(aTargetPath)
   , mRecursive(aRecursive)
@@ -61,18 +61,19 @@ RemoveTask::RemoveTask(FileSystemBase* a
   const FileSystemPathOrFileValue& target = aParam.target();
 
   if (target.type() == FileSystemPathOrFileValue::TnsString) {
     mTargetRealPath = target;
     return;
   }
 
   BlobParent* bp = static_cast<BlobParent*>(static_cast<PBlobParent*>(target));
-  mTargetFileImpl = bp->GetBlobImpl();
-  MOZ_ASSERT(mTargetFileImpl);
+  nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob();
+  MOZ_ASSERT(blob);
+  mTargetFileImpl = static_cast<DOMFile*>(blob.get())->Impl();
 }
 
 RemoveTask::~RemoveTask()
 {
   MOZ_ASSERT(!mPromise || NS_IsMainThread(),
              "mPromise should be released on main thread!");
 }
 
@@ -87,17 +88,17 @@ FileSystemParams
 RemoveTask::GetRequestParams(const nsString& aFileSystem) const
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   FileSystemRemoveParams param;
   param.filesystem() = aFileSystem;
   param.directory() = mDirRealPath;
   param.recursive() = mRecursive;
   if (mTargetFileImpl) {
-    nsRefPtr<File> file = new File(mFileSystem->GetWindow(), mTargetFileImpl);
+    nsRefPtr<DOMFile> file = new DOMFile(mTargetFileImpl);
     BlobChild* actor
       = ContentChild::GetSingleton()->GetOrCreateActorForBlob(file);
     if (actor) {
       param.target() = actor;
     }
   } else {
     param.target() = mTargetRealPath;
   }
@@ -125,17 +126,17 @@ RemoveTask::Work()
   MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
              "Only call from parent process!");
   MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
 
   if (mFileSystem->IsShutdown()) {
     return NS_ERROR_FAILURE;
   }
 
-  // Get the DOM path if a File is passed as the target.
+  // Get the DOM path if a DOMFile is passed as the target.
   if (mTargetFileImpl) {
     if (!mFileSystem->GetRealPath(mTargetFileImpl, mTargetRealPath)) {
       return NS_ERROR_DOM_SECURITY_ERR;
     }
     if (!FileSystemUtils::IsDescendantPath(mDirRealPath, mTargetRealPath)) {
       return NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
     }
   }
--- a/dom/filesystem/RemoveTask.h
+++ b/dom/filesystem/RemoveTask.h
@@ -9,26 +9,26 @@
 
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "nsAutoPtr.h"
 #include "mozilla/ErrorResult.h"
 
 namespace mozilla {
 namespace dom {
 
-class FileImpl;
+class DOMFileImpl;
 class Promise;
 
 class RemoveTask MOZ_FINAL
   : public FileSystemTaskBase
 {
 public:
   RemoveTask(FileSystemBase* aFileSystem,
              const nsAString& aDirPath,
-             FileImpl* aTargetFile,
+             DOMFileImpl* aTargetFile,
              const nsAString& aTargetPath,
              bool aRecursive,
              ErrorResult& aRv);
   RemoveTask(FileSystemBase* aFileSystem,
              const FileSystemRemoveParams& aParam,
              FileSystemRequestParent* aParent);
 
   virtual
@@ -54,19 +54,19 @@ protected:
   Work() MOZ_OVERRIDE;
 
   virtual void
   HandlerCallback() MOZ_OVERRIDE;
 
 private:
   nsRefPtr<Promise> mPromise;
   nsString mDirRealPath;
-  // This cannot be a File because this object will be used on a different
-  // thread and File is not thread-safe. Let's use the FileImpl instead.
-  nsRefPtr<FileImpl> mTargetFileImpl;
+  // This cannot be a DOMFile because this object will be used on a different
+  // thread and DOMFile is not thread-safe. Let's use the DOMFileImpl instead.
+  nsRefPtr<DOMFileImpl> mTargetFileImpl;
   nsString mTargetRealPath;
   bool mRecursive;
   bool mReturnValue;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -519,20 +519,18 @@ ConvertActorsToBlobs(IDBDatabase* aDatab
 
   if (!blobs.IsEmpty()) {
     const uint32_t count = blobs.Length();
     aFiles.SetCapacity(count);
 
     for (uint32_t index = 0; index < count; index++) {
       BlobChild* actor = static_cast<BlobChild*>(blobs[index]);
 
-      nsRefPtr<FileImpl> blobImpl = actor->GetBlobImpl();
-      MOZ_ASSERT(blobImpl);
-
-      nsRefPtr<File> blob = new File(aDatabase->GetOwner(), blobImpl);
+      nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob();
+      MOZ_ASSERT(blob);
 
       nsRefPtr<FileInfo> fileInfo;
       if (!fileInfos.IsEmpty()) {
         fileInfo = dont_AddRef(reinterpret_cast<FileInfo*>(fileInfos[index]));
 
         MOZ_ASSERT(fileInfo);
         MOZ_ASSERT(fileInfo->Id() > 0);
 
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -24,17 +24,16 @@
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/storage.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/ContentParent.h"
-#include "mozilla/dom/File.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBCursorParent.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseParent.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseFileParent.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryParent.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryRequestParent.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBRequestParent.h"
@@ -52,20 +51,22 @@
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/InputStreamParams.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/PBackground.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsClassHashtable.h"
 #include "nsCOMPtr.h"
 #include "nsDataHashtable.h"
+#include "nsDOMFile.h"
 #include "nsEscape.h"
 #include "nsHashKeys.h"
 #include "nsNetUtil.h"
 #include "nsIAppsService.h"
+#include "nsIDOMFile.h"
 #include "nsIEventTarget.h"
 #include "nsIFile.h"
 #include "nsIFileURL.h"
 #include "nsIInputStream.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsInterfaceHashtable.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
@@ -3022,17 +3023,17 @@ private:
   RecvClose() MOZ_OVERRIDE;
 };
 
 class DatabaseFile MOZ_FINAL
   : public PBackgroundIDBDatabaseFileParent
 {
   friend class Database;
 
-  nsRefPtr<FileImpl> mBlobImpl;
+  nsRefPtr<DOMFileImpl> mBlobImpl;
   nsRefPtr<FileInfo> mFileInfo;
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::indexedDB::DatabaseFile);
 
   FileInfo*
   GetFileInfo() const
   {
@@ -3069,17 +3070,17 @@ private:
   explicit DatabaseFile(FileInfo* aFileInfo)
     : mFileInfo(aFileInfo)
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(aFileInfo);
   }
 
   // Called when receiving from the child.
-  DatabaseFile(FileImpl* aBlobImpl, FileInfo* aFileInfo)
+  DatabaseFile(DOMFileImpl* aBlobImpl, FileInfo* aFileInfo)
     : mBlobImpl(aBlobImpl)
     , mFileInfo(aFileInfo)
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(aBlobImpl);
     MOZ_ASSERT(aFileInfo);
   }
 
@@ -5007,21 +5008,21 @@ private:
     MOZ_ASSERT(!mWaitingFactoryOp ||
                !mWaitingFactoryOp->HasBlockedDatabases());
 
     MOZ_COUNT_DTOR(DatabaseActorInfo);
   }
 };
 
 class NonMainThreadHackBlobImpl MOZ_FINAL
-  : public FileImplFile
+  : public DOMFileImplFile
 {
 public:
   NonMainThreadHackBlobImpl(nsIFile* aFile, FileInfo* aFileInfo)
-    : FileImplFile(aFile, aFileInfo)
+    : DOMFileImplFile(aFile, aFileInfo)
   {
     // Getting the content type is not currently supported off the main thread.
     // This isn't a problem here because:
     //
     //   1. The real content type is stored in the structured clone data and
     //      that's all that the DOM will see. This blob's data will be updated
     //      during RecvSetMysteryBlobInfo().
     //   2. The nsExternalHelperAppService guesses the content type based only
@@ -5494,17 +5495,17 @@ ConvertBlobsToActors(PBackgroundParent* 
 
     MOZ_ASSERT(NS_SUCCEEDED(nativeFile->Exists(&exists)));
     MOZ_ASSERT(exists);
 
     DebugOnly<bool> isFile;
     MOZ_ASSERT(NS_SUCCEEDED(nativeFile->IsFile(&isFile)));
     MOZ_ASSERT(isFile);
 
-    nsRefPtr<FileImpl> impl =
+    nsRefPtr<DOMFileImpl> impl =
       new NonMainThreadHackBlobImpl(nativeFile, file.mFileInfo);
 
     PBlobParent* actor =
       BackgroundParent::GetOrCreateActorForBlobImpl(aBackgroundActor, impl);
     if (!actor) {
       // This can only fail if the child has crashed.
       IDB_REPORT_INTERNAL_ERR();
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -6234,17 +6235,17 @@ Database::ActorDestroy(ActorDestroyReaso
 }
 
 PBackgroundIDBDatabaseFileParent*
 Database::AllocPBackgroundIDBDatabaseFileParent(PBlobParent* aBlobParent)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aBlobParent);
 
-  nsRefPtr<FileImpl> blobImpl =
+  nsRefPtr<DOMFileImpl> blobImpl =
     static_cast<BlobParent*>(aBlobParent)->GetBlobImpl();
   MOZ_ASSERT(blobImpl);
 
   nsRefPtr<DatabaseFile> actor;
 
   if (nsRefPtr<FileInfo> fileInfo = blobImpl->GetFileInfo(mFileManager)) {
     // This blob was previously shared with the child.
     actor = new DatabaseFile(fileInfo);
--- a/dom/indexedDB/FileSnapshot.cpp
+++ b/dom/indexedDB/FileSnapshot.cpp
@@ -21,20 +21,20 @@ namespace indexedDB {
 
 // Create as a stored file
 FileImplSnapshot::FileImplSnapshot(const nsAString& aName,
                                    const nsAString& aContentType,
                                    MetadataParameters* aMetadataParams,
                                    nsIFile* aFile,
                                    IDBFileHandle* aFileHandle,
                                    FileInfo* aFileInfo)
-  : FileImplBase(aName,
-                 aContentType,
-                 aMetadataParams->Size(),
-                 aMetadataParams->LastModified())
+  : DOMFileImplBase(aName,
+                    aContentType,
+                    aMetadataParams->Size(),
+                    aMetadataParams->LastModified())
   , mFile(aFile)
   , mFileHandle(aFileHandle)
   , mWholeFile(true)
 {