Bug 1339871 - Splitting dom/file/File.{h,cpp}, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 16 Feb 2017 18:26:38 +0100
changeset 343401 e2a28ac246590211cb38491338e5371f58f04aea
parent 343400 c8b963f03d373a3040baa8cd0fa0851f776f28ae
child 343402 3f174ed8447c12e74cc9196d4e34dc0b2d2ae80e
push id31378
push usercbook@mozilla.com
push dateFri, 17 Feb 2017 12:25:19 +0000
treeherdermozilla-central@03fc0a686d3f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1339871
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1339871 - Splitting dom/file/File.{h,cpp}, r=smaug
dom/archivereader/ArchiveZipEvent.cpp
dom/archivereader/ArchiveZipFile.h
dom/base/nsContentUtils.cpp
dom/base/nsFrameMessageManager.cpp
dom/bindings/Bindings.conf
dom/devicestorage/DeviceStorageRequestParent.cpp
dom/devicestorage/nsDeviceStorage.cpp
dom/file/BaseBlobImpl.cpp
dom/file/BaseBlobImpl.h
dom/file/Blob.cpp
dom/file/Blob.h
dom/file/BlobImpl.cpp
dom/file/BlobImpl.h
dom/file/BlobSet.cpp
dom/file/EmptyBlobImpl.cpp
dom/file/EmptyBlobImpl.h
dom/file/File.cpp
dom/file/File.h
dom/file/FileBlobImpl.cpp
dom/file/FileBlobImpl.h
dom/file/MemoryBlobImpl.cpp
dom/file/MemoryBlobImpl.h
dom/file/MultipartBlobImpl.cpp
dom/file/MultipartBlobImpl.h
dom/file/MutableBlobStorage.cpp
dom/file/StreamBlobImpl.cpp
dom/file/StreamBlobImpl.h
dom/file/StringBlobImpl.cpp
dom/file/StringBlobImpl.h
dom/file/TemporaryBlobImpl.cpp
dom/file/TemporaryBlobImpl.h
dom/file/ipc/Blob.cpp
dom/file/moz.build
dom/file/nsHostObjectProtocolHandler.cpp
dom/filesystem/CreateFileTask.cpp
dom/filesystem/GetDirectoryListingTask.cpp
dom/filesystem/GetFileOrDirectoryTask.cpp
dom/filesystem/GetFilesHelper.cpp
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/ipc/FilePickerParent.cpp
dom/xhr/XMLHttpRequestMainThread.cpp
ipc/glue/InputStreamUtils.cpp
js/xpconnect/src/XPCJSContext.cpp
--- a/dom/archivereader/ArchiveZipEvent.cpp
+++ b/dom/archivereader/ArchiveZipEvent.cpp
@@ -6,16 +6,17 @@
 
 #include "ArchiveZipEvent.h"
 #include "ArchiveZipFile.h"
 
 #include "nsContentUtils.h"
 #include "nsCExternalHandlerService.h"
 
 #include "mozilla/UniquePtr.h"
+#include "nsIInputStream.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 USING_ARCHIVEREADER_NAMESPACE
 
 #ifndef PATH_MAX
 #  define PATH_MAX 65536 // The filename length is stored in 2 bytes
--- a/dom/archivereader/ArchiveZipFile.h
+++ b/dom/archivereader/ArchiveZipFile.h
@@ -4,53 +4,53 @@
  * 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/ErrorResult.h"
-#include "mozilla/dom/File.h"
+#include "mozilla/dom/BaseBlobImpl.h"
 
 #include "ArchiveReader.h"
 
 #include "ArchiveReaderCommon.h"
 #include "zipstruct.h"
 
 BEGIN_ARCHIVEREADER_NAMESPACE
 
 /**
  * ArchiveZipBlobImpl to BlobImpl
  */
-class ArchiveZipBlobImpl : public BlobImplBase
+class ArchiveZipBlobImpl : public BaseBlobImpl
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   ArchiveZipBlobImpl(const nsAString& aName,
                      const nsAString& aContentType,
                      uint64_t aLength,
                      ZipCentral& aCentral,
                      BlobImpl* aBlobImpl)
-  : BlobImplBase(aName, aContentType, aLength),
+  : BaseBlobImpl(aName, aContentType, aLength),
     mCentral(aCentral),
     mBlobImpl(aBlobImpl),
     mFilename(aName)
   {
     MOZ_ASSERT(mBlobImpl);
   }
 
   ArchiveZipBlobImpl(const nsAString& aName,
                      const nsAString& aContentType,
                      uint64_t aStart,
                      uint64_t aLength,
                      ZipCentral& aCentral,
                      BlobImpl* aBlobImpl)
-  : BlobImplBase(aContentType, aStart, aLength),
+  : BaseBlobImpl(aContentType, aStart, aLength),
     mCentral(aCentral),
     mBlobImpl(aBlobImpl),
     mFilename(aName)
   {
     MOZ_ASSERT(mBlobImpl);
   }
 
   // Overrides:
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -37,16 +37,17 @@
 #include "mozilla/CheckedInt.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/FileBlobImpl.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/HTMLContentElement.h"
 #include "mozilla/dom/HTMLShadowElement.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -7871,17 +7872,17 @@ nsContentUtils::TransferableToIPCTransfe
 
                 Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
                 item->data() = dataAsShmem;
               }
 
               continue;
             }
 
-            blobImpl = new BlobImplFile(file);
+            blobImpl = new FileBlobImpl(file);
 
             IgnoredErrorResult rv;
 
             // Ensure that file data is cached no that the content process
             // has this data available to it when passed over:
             blobImpl->GetSize(rv);
             if (NS_WARN_IF(rv.Failed())) {
               continue;
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -15,16 +15,17 @@
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsJSUtils.h"
 #include "nsJSPrincipals.h"
 #include "nsNetUtil.h"
 #include "nsScriptLoader.h"
 #include "nsFrameLoader.h"
+#include "nsIInputStream.h"
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIMemoryReporter.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIDOMClassInfo.h"
 #include "xpcpublic.h"
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -102,20 +102,16 @@ DOMInterfaces = {
 'BarProp': {
     'headerFile': 'mozilla/dom/BarProps.h',
 },
 
 'BaseAudioContext': {
     'nativeType': 'mozilla::dom::AudioContext',
 },
 
-'Blob': {
-    'headerFile': 'mozilla/dom/File.h',
-},
-
 'BatteryManager': {
     'nativeType': 'mozilla::dom::battery::BatteryManager',
     'headerFile': 'BatteryManager.h'
 },
 
 'BoxObject': {
     'resultNotAddRefed': ['element'],
 },
--- a/dom/devicestorage/DeviceStorageRequestParent.cpp
+++ b/dom/devicestorage/DeviceStorageRequestParent.cpp
@@ -3,17 +3,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 "DeviceStorageRequestParent.h"
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "mozilla/Unused.h"
-#include "mozilla/dom/File.h"
+#include "mozilla/dom/FileBlobImpl.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "ContentParent.h"
 #include "nsProxyRelease.h"
 #include "mozilla/Preferences.h"
 #include "nsNetCID.h"
 
 namespace mozilla {
 namespace dom {
@@ -276,17 +276,17 @@ DeviceStorageRequestParent::PostBlobSucc
   MOZ_ASSERT(NS_IsMainThread());
 
   nsString mime;
   CopyASCIItoUTF16(mMimeType, mime);
 
   nsString fullPath;
   mFile->GetFullPath(fullPath);
   RefPtr<BlobImpl> blob =
-    new BlobImplFile(fullPath, mime, mLength, mFile->mFile,
+    new FileBlobImpl(fullPath, mime, mLength, mFile->mFile,
                      mLastModificationDate);
 
   ContentParent* cp = static_cast<ContentParent*>(mParent->Manager());
   BlobParent* actor = cp->GetOrCreateActorForBlobImpl(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
@@ -10,16 +10,17 @@
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/DeviceStorageBinding.h"
 #include "mozilla/dom/DeviceStorageChangeEvent.h"
 #include "mozilla/dom/DeviceStorageFileSystem.h"
 #include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
 #include "mozilla/dom/Directory.h"
+#include "mozilla/dom/FileBlobImpl.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/PBrowserChild.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
@@ -29,16 +30,17 @@
 #include "mozilla/ipc/BackgroundUtils.h" // for PrincipalInfoToPrincipal
 
 #include "nsArrayUtils.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsGlobalWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIFile.h"
 #include "nsIDirectoryEnumerator.h"
+#include "nsIInputStream.h"
 #include "nsNetUtil.h"
 #include "nsIOutputStream.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIPrincipal.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsXULAppAPI.h"
 #include "DeviceStorageFileDescriptor.h"
@@ -3990,19 +3992,19 @@ DeviceStorageRequestManager::Resolve(uin
   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);
 
-  RefPtr<BlobImpl> blobImpl = new BlobImplFile(fullPath, aFile->mMimeType,
-                                                 aFile->mLength, aFile->mFile,
-                                                 aFile->mLastModifiedDate);
+  RefPtr<BlobImpl> blobImpl = new FileBlobImpl(fullPath, aFile->mMimeType,
+                                               aFile->mLength, aFile->mFile,
+                                               aFile->mLastModifiedDate);
 
   /* File should start out as mutable by default but we should turn
      that off if it wasn't requested. */
   bool editable;
   nsresult rv = blobImpl->GetMutable(&editable);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     DS_LOG_WARN("%u cannot query mutable", aId);
     return Reject(aId, POST_ERROR_EVENT_UNKNOWN);
copy from dom/file/File.cpp
copy to dom/file/BaseBlobImpl.cpp
--- a/dom/file/File.cpp
+++ b/dom/file/BaseBlobImpl.cpp
@@ -1,737 +1,93 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/File.h"
-
-#include "ipc/nsIRemoteBlob.h"
-#include "MultipartBlobImpl.h"
-#include "nsCExternalHandlerService.h"
-#include "nsContentCID.h"
-#include "nsContentUtils.h"
-#include "nsError.h"
-#include "nsICharsetDetector.h"
-#include "nsIConverterInputStream.h"
-#include "nsIDocument.h"
-#include "nsIFileStreams.h"
-#include "nsIInputStream.h"
-#include "nsIIPCSerializableInputStream.h"
-#include "nsIMIMEService.h"
-#include "nsISeekableStream.h"
-#include "nsIUnicharInputStream.h"
-#include "nsIUnicodeDecoder.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsIUUIDGenerator.h"
-#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/DOMError.h"
-#include "mozilla/dom/FileBinding.h"
-#include "mozilla/dom/FileCreatorHelper.h"
-#include "mozilla/dom/FileSystemUtils.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerRunnable.h"
-#include "nsThreadUtils.h"
-#include "nsStreamUtils.h"
-#include "SlicedInputStream.h"
+#include "mozilla/dom/BaseBlobImpl.h"
+#include "prtime.h"
 
 namespace mozilla {
 namespace dom {
 
-using namespace workers;
-
-// XXXkhuey the input stream that we pass out of a File
-// can outlive the actual File 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 final : public nsIInputStream,
-                               public nsISeekableStream,
-                               public nsIIPCSerializableInputStream
-{
-  typedef BlobImplMemory::DataOwner DataOwner;
-public:
-  static nsresult Create(DataOwner* aDataOwner,
-                         uint32_t aStart,
-                         uint32_t aLength,
-                         nsIInputStream** _retval);
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  // These are mandatory.
-  NS_FORWARD_NSIINPUTSTREAM(mStream->)
-  NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
-
-  // This is optional. We use a conditional QI to keep it from being called
-  // if the underlying stream doesn't support it.
-  NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
-
-private:
-  ~DataOwnerAdapter() {}
-
-  DataOwnerAdapter(DataOwner* aDataOwner,
-                   nsIInputStream* aStream)
-    : mDataOwner(aDataOwner), mStream(aStream),
-      mSeekableStream(do_QueryInterface(aStream)),
-      mSerializableInputStream(do_QueryInterface(aStream))
-  {
-    MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
-  }
-
-  RefPtr<DataOwner> mDataOwner;
-  nsCOMPtr<nsIInputStream> mStream;
-  nsCOMPtr<nsISeekableStream> mSeekableStream;
-  nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
-};
-
-NS_IMPL_ADDREF(DataOwnerAdapter)
-NS_IMPL_RELEASE(DataOwnerAdapter)
-
-NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
-  NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
-                                     mSerializableInputStream)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
-NS_INTERFACE_MAP_END
-
-nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
-                                  uint32_t aStart,
-                                  uint32_t aLength,
-                                  nsIInputStream** _retval)
-{
-  nsresult rv;
-  MOZ_ASSERT(aDataOwner, "Uh ...");
-
-  nsCOMPtr<nsIInputStream> stream;
-
-  rv = NS_NewByteInputStream(getter_AddRefs(stream),
-                             static_cast<const char*>(aDataOwner->mData) +
-                             aStart,
-                             (int32_t)aLength,
-                             NS_ASSIGNMENT_DEPEND);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
-
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::Blob implementation
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
-  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(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
-  // 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, nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
-  NS_INTERFACE_MAP_ENTRY(nsIMutable)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
-
-// A utility function that enforces the spec constraints on the type of a blob:
-// no codepoints outside the ASCII range (otherwise type becomes empty) and
-// lowercase ASCII only.  We can't just use our existing nsContentUtils
-// ASCII-related helpers because we need the "outside ASCII range" check, and we
-// can't use NS_IsAscii because its definition of "ASCII" (chars all <= 0x7E)
-// differs from the file API definition (which excludes control chars).
-static void
-MakeValidBlobType(nsAString& aType)
-{
-  char16_t* iter = aType.BeginWriting();
-  char16_t* end = aType.EndWriting();
-
-  for ( ; iter != end; ++iter) {
-    char16_t c = *iter;
-    if (c < 0x20 || c > 0x7E) {
-      // Non-ASCII char, bail out.
-      aType.Truncate();
-      return;
-    }
-
-    if (c >= 'A' && c <= 'Z') {
-      *iter = c + ('a' - 'A');
-    }
-  }
-}
-
-/* static */ Blob*
-Blob::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-
-  return aImpl->IsFile() ? new File(aParent, aImpl)
-                         : new Blob(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateStringBlob(nsISupports* aParent, const nsACString& aData,
-                       const nsAString& aContentType)
-{
-  RefPtr<BlobImpl> blobImpl = BlobImplString::Create(aData, aContentType);
-  RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
-                          uint64_t aStartPos, uint64_t aLength,
-                          const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplTemporaryBlob(aFD, aStartPos, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-Blob::Blob(nsISupports* aParent, BlobImpl* aImpl)
-  : mImpl(aImpl)
-  , mParent(aParent)
-{
-  MOZ_ASSERT(mImpl);
-
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aParent);
-    if (win) {
-      MOZ_ASSERT(win->IsInnerWindow());
-    }
-  }
-#endif
-}
-
-bool
-Blob::IsFile() const
-{
-  return mImpl->IsFile();
-}
-
-const nsTArray<RefPtr<BlobImpl>>*
-Blob::GetSubBlobImpls() const
-{
-  return mImpl->GetSubBlobImpls();
-}
-
-already_AddRefed<File>
-Blob::ToFile()
-{
-  if (!mImpl->IsFile()) {
-    return nullptr;
-  }
-
-  RefPtr<File> file;
-  if (HasFileInterface()) {
-    file = static_cast<File*>(this);
-  } else {
-    file = new File(mParent, mImpl);
-  }
-
-  return file.forget();
-}
-
-already_AddRefed<File>
-Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const
-{
-  AutoTArray<RefPtr<BlobImpl>, 1> blobImpls({mImpl});
-
-  nsAutoString contentType;
-  mImpl->GetType(contentType);
-
-  RefPtr<MultipartBlobImpl> impl =
-    MultipartBlobImpl::Create(Move(blobImpls), aName, contentType, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  RefPtr<File> file = new File(mParent, impl);
-  return file.forget();
-}
-
-already_AddRefed<Blob>
-Blob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                  const nsAString& aContentType,
-                  ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl = mImpl->CreateSlice(aStart, aLength,
-                                             aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-uint64_t
-Blob::GetSize(ErrorResult& aRv)
-{
-  return mImpl->GetSize(aRv);
-}
-
 void
-Blob::GetType(nsAString &aType)
-{
-  mImpl->GetType(aType);
-}
-
-already_AddRefed<Blob>
-Blob::Slice(const Optional<int64_t>& aStart,
-            const Optional<int64_t>& aEnd,
-            const nsAString& aContentType,
-            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    mImpl->Slice(aStart, aEnd, aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-NS_IMETHODIMP
-Blob::GetSendInfo(nsIInputStream** aBody,
-                  uint64_t* aContentLength,
-                  nsACString& aContentType,
-                  nsACString& aCharset)
-{
-  return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
-}
-
-NS_IMETHODIMP
-Blob::GetMutable(bool* aMutable)
-{
-  return mImpl->GetMutable(aMutable);
-}
-
-NS_IMETHODIMP
-Blob::SetMutable(bool aMutable)
-{
-  return mImpl->SetMutable(aMutable);
-}
-
-JSObject*
-Blob::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return BlobBinding::Wrap(aCx, this, aGivenProto);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::Constructor(const GlobalObject& aGlobal,
-                  const Optional<Sequence<BlobPart>>& aData,
-                  const BlobPropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();
-
-  if (aData.WasPassed()) {
-    nsAutoString type(aBag.mType);
-    MakeValidBlobType(type);
-    impl->InitializeBlob(aGlobal.Context(), aData.Value(), type,
-                         aBag.mEndings == EndingTypes::Native, aRv);
-  } else {
-    impl->InitializeBlob(aRv);
-  }
-
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  MOZ_ASSERT(!impl->IsFile());
-
-  RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
-  return blob.forget();
-}
-
-int64_t
-Blob::GetFileId()
-{
-  return mImpl->GetFileId();
-}
-
-bool
-Blob::IsMemoryFile() const
-{
-  return mImpl->IsMemoryFile();
-}
-
-void
-Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  mImpl->GetInternalStream(aStream, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::File implementation
-
-File::File(nsISupports* aParent, BlobImpl* aImpl)
-  : Blob(aParent, aImpl)
-{
-  MOZ_ASSERT(aImpl->IsFile());
-}
-
-/* static */ File*
-File::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-  MOZ_ASSERT(aImpl->IsFile());
-
-  return new File(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aName,
-             const nsAString& aContentType, uint64_t aLength,
-             int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aName,
-                       aContentType, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile)
-{
-  RefPtr<File> file = new File(aParent, new BlobImplFile(aFile));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                     const nsAString& aName, const nsAString& aContentType)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplFile(aFile, aName, aContentType));
-  return file.forget();
-}
-
-JSObject*
-File::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return FileBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-File::GetName(nsAString& aFileName) const
-{
-  mImpl->GetName(aFileName);
-}
-
-void
-File::GetRelativePath(nsAString& aPath) const
-{
-  aPath.Truncate();
-
-  nsAutoString path;
-  mImpl->GetDOMPath(path);
-
-  // WebkitRelativePath doesn't start with '/'
-  if (!path.IsEmpty()) {
-    MOZ_ASSERT(path[0] == FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
-    aPath.Assign(Substring(path, 1));
-  }
-}
-
-Date
-File::GetLastModifiedDate(ErrorResult& aRv)
-{
-  int64_t value = GetLastModified(aRv);
-  if (aRv.Failed()) {
-    return Date();
-  }
-
-  return Date(JS::TimeClip(value));
-}
-
-int64_t
-File::GetLastModified(ErrorResult& aRv)
-{
-  return mImpl->GetLastModified(aRv);
-}
-
-void
-File::GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPath(aFilename, aGuarantee, aRv);
-}
-
-void
-File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPathInternal(aFileName, aRv);
-}
-
-// 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;
-  if (aStart < -aSize) {
-    newStartOffset = 0;
-  }
-  else if (aStart < 0) {
-    newStartOffset += aSize;
-  }
-  else if (aStart > aSize) {
-    newStartOffset = aSize;
-  }
-
-  CheckedInt64 newEndOffset = aEnd;
-  if (aEnd < -aSize) {
-    newEndOffset = 0;
-  }
-  else if (aEnd < 0) {
-    newEndOffset += aSize;
-  }
-  else if (aEnd > aSize) {
-    newEndOffset = aSize;
-  }
-
-  if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
-      newStartOffset.value() >= newEndOffset.value()) {
-    aStart = aEnd = 0;
-  }
-  else {
-    aStart = newStartOffset.value();
-    aEnd = newEndOffset.value();
-  }
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  const Sequence<BlobPart>& aData,
-                  const nsAString& aName,
-                  const FilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  // Normalizing the filename
-  nsString name(aName);
-  name.ReplaceChar('/', ':');
-
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(name);
-
-  nsAutoString type(aBag.mType);
-  MakeValidBlobType(type);
-  impl->InitializeBlob(aGlobal.Context(), aData, type, false, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
-
-  if (aBag.mLastModified.WasPassed()) {
-    impl->SetLastModified(aBag.mLastModified.Value());
-  }
-
-  RefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
-  return file.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromNsIFile(const GlobalObject& aGlobal,
-                        nsIFile* aData,
-                        const ChromeFilePropertyBag& aBag,
-                        SystemCallerGuarantee aGuarantee,
-                        ErrorResult& aRv)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, aData, aBag, true, aRv);
-  return promise.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromFileName(const GlobalObject& aGlobal,
-                         const nsAString& aPath,
-                         const ChromeFilePropertyBag& aBag,
-                         SystemCallerGuarantee aGuarantee,
-                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIFile> file;
-  aRv = NS_NewLocalFile(aPath, false, getter_AddRefs(file));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, file, aBag, false, aRv);
-  return promise.forget();
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::BlobImpl implementation
-
-already_AddRefed<BlobImpl>
-BlobImpl::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);
-
-  nsAutoString type(aContentType);
-  MakeValidBlobType(type);
-  return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImpl implementation
-
-NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFile, BlobImpl)
-
-void
-BlobImplBase::GetName(nsAString& aName) const
+BaseBlobImpl::GetName(nsAString& aName) const
 {
   MOZ_ASSERT(mIsFile, "Should only be called on files");
   aName = mName;
 }
 
 void
-BlobImplBase::GetDOMPath(nsAString& aPath) const
+BaseBlobImpl::GetDOMPath(nsAString& aPath) const
 {
   MOZ_ASSERT(mIsFile, "Should only be called on files");
   aPath = mPath;
 }
 
 void
-BlobImplBase::SetDOMPath(const nsAString& aPath)
+BaseBlobImpl::SetDOMPath(const nsAString& aPath)
 {
   MOZ_ASSERT(mIsFile, "Should only be called on files");
   mPath = aPath;
 }
 
 void
-BlobImplBase::GetMozFullPath(nsAString& aFileName,
+BaseBlobImpl::GetMozFullPath(nsAString& aFileName,
                              SystemCallerGuarantee /* unused */,
                              ErrorResult& aRv) const
 {
   MOZ_ASSERT(mIsFile, "Should only be called on files");
 
   GetMozFullPathInternal(aFileName, aRv);
 }
 
 void
-BlobImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
+BaseBlobImpl::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
 {
   if (!mIsFile) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   aFileName.Truncate();
 }
 
 void
-BlobImplBase::GetType(nsAString& aType)
+BaseBlobImpl::GetType(nsAString& aType)
 {
   aType = mContentType;
 }
 
 int64_t
-BlobImplBase::GetLastModified(ErrorResult& aRv)
+BaseBlobImpl::GetLastModified(ErrorResult& aRv)
 {
   MOZ_ASSERT(mIsFile, "Should only be called on files");
   if (IsDateUnknown()) {
     mLastModificationDate = PR_Now();
   }
 
   return mLastModificationDate / PR_USEC_PER_MSEC;
 }
 
 void
-BlobImplBase::SetLastModified(int64_t aLastModified)
+BaseBlobImpl::SetLastModified(int64_t aLastModified)
 {
   mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
 }
 
 int64_t
-BlobImplBase::GetFileId()
+BaseBlobImpl::GetFileId()
 {
   return -1;
 }
 
 nsresult
-BlobImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
+BaseBlobImpl::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
                           nsACString& aContentType, nsACString& aCharset)
 {
   MOZ_ASSERT(aContentLength);
 
   ErrorResult rv;
 
   nsCOMPtr<nsIInputStream> stream;
   GetInternalStream(getter_AddRefs(stream), rv);
@@ -755,24 +111,24 @@ BlobImplBase::GetSendInfo(nsIInputStream
 
   aCharset.Truncate();
 
   stream.forget(aBody);
   return NS_OK;
 }
 
 nsresult
-BlobImplBase::GetMutable(bool* aMutable) const
+BaseBlobImpl::GetMutable(bool* aMutable) const
 {
   *aMutable = !mImmutable;
   return NS_OK;
 }
 
 nsresult
-BlobImplBase::SetMutable(bool aMutable)
+BaseBlobImpl::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;
@@ -785,566 +141,16 @@ BlobImplBase::SetMutable(bool aMutable)
     }
   }
 
   mImmutable = !aMutable;
   return rv;
 }
 
 /* static */ uint64_t
-BlobImplBase::NextSerialNumber()
+BaseBlobImpl::NextSerialNumber()
 {
   static Atomic<uint64_t> nextSerialNumber;
   return nextSerialNumber++;
 }
 
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-already_AddRefed<BlobImpl>
-BlobImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
-                          const nsAString& aContentType,
-                          ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplFile(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aRv = mFile->GetPath(aFilename);
-}
-
-uint64_t
-BlobImplFile::GetSize(ErrorResult& aRv)
-{
-  if (BlobImplBase::IsSizeUnknown()) {
-    MOZ_ASSERT(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;
-    }
-
-    if (fileSize < 0) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return 0;
-    }
-
-    mLength = fileSize;
-  }
-
-  return mLength;
-}
-
-namespace {
-
-class GetTypeRunnable final : public WorkerMainThreadRunnable
-{
-public:
-  GetTypeRunnable(WorkerPrivate* aWorkerPrivate,
-                  BlobImpl* aBlobImpl)
-    : WorkerMainThreadRunnable(aWorkerPrivate,
-                               NS_LITERAL_CSTRING("BlobImplFile :: GetType"))
-    , mBlobImpl(aBlobImpl)
-  {
-    MOZ_ASSERT(aBlobImpl);
-    aWorkerPrivate->AssertIsOnWorkerThread();
-  }
-
-  bool
-  MainThreadRun() override
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    nsAutoString type;
-    mBlobImpl->GetType(type);
-    return true;
-  }
-
-private:
-  ~GetTypeRunnable()
-  {}
-
-  RefPtr<BlobImpl> mBlobImpl;
-};
-
-} // anonymous namespace
-
-void
-BlobImplFile::GetType(nsAString& aType)
-{
-  aType.Truncate();
-
-  if (mContentType.IsVoid()) {
-    MOZ_ASSERT(mWholeFile,
-               "Should only use lazy ContentType when using the whole file");
-
-    if (!NS_IsMainThread()) {
-      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-      if (!workerPrivate) {
-        // I have no idea in which thread this method is called. We cannot
-        // return any valid value.
-        return;
-      }
-
-      RefPtr<GetTypeRunnable> runnable =
-        new GetTypeRunnable(workerPrivate, this);
-
-      ErrorResult rv;
-      runnable->Dispatch(Terminating, rv);
-      if (NS_WARN_IF(rv.Failed())) {
-        rv.SuppressException();
-      }
-      return;
-    }
-
-    nsresult rv;
-    nsCOMPtr<nsIMIMEService> mimeService =
-      do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-
-    nsAutoCString mimeType;
-    rv = mimeService->GetTypeFromFile(mFile, mimeType);
-    if (NS_FAILED(rv)) {
-      mimeType.Truncate();
-    }
-
-    AppendUTF8toUTF16(mimeType, mContentType);
-    mContentType.SetIsVoid(false);
-  }
-
-  aType = mContentType;
-}
-
-int64_t
-BlobImplFile::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (BlobImplBase::IsDateUnknown()) {
-    PRTime msecs;
-    aRv = mFile->GetLastModifiedTime(&msecs);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return 0;
-    }
-
-    mLastModificationDate = msecs;
-  }
-
-  return mLastModificationDate;
-}
-
-void
-BlobImplFile::SetLastModified(int64_t aLastModified)
-{
-  MOZ_CRASH("SetLastModified of a real file is not allowed!");
-}
-
-const uint32_t sFileStreamFlags =
-  nsIFileInputStream::CLOSE_ON_EOF |
-  nsIFileInputStream::REOPEN_ON_REWIND |
-  nsIFileInputStream::DEFER_OPEN |
-  nsIFileInputStream::SHARE_DELETE;
-
-void
-BlobImplFile::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mWholeFile) {
-    aRv = NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags);
-    return;
-  }
-
-  aRv = NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
-                                          -1, -1, sFileStreamFlags);
-}
-
-bool
-BlobImplFile::IsDirectory() const
-{
-  bool isDirectory = false;
-  if (mFile) {
-    mFile->IsDirectory(&isDirectory);
-  }
-  return isDirectory;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// EmptyBlobImpl implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
-
-already_AddRefed<BlobImpl>
-EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
-                           const nsAString& aContentType,
-                           ErrorResult& aRv)
-{
-  MOZ_ASSERT(!aStart && !aLength);
-  RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-
-  DebugOnly<bool> isMutable;
-  MOZ_ASSERT(NS_SUCCEEDED(impl->GetMutable(&isMutable)));
-  MOZ_ASSERT(!isMutable);
-
-  return impl.forget();
-}
-
-void
-EmptyBlobImpl::GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv)
-{
-  if (NS_WARN_IF(!aStream)) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
-    return;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplString implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplString, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplString>
-BlobImplString::Create(const nsACString& aData, const nsAString& aContentType)
-{
-  RefPtr<BlobImplString> blobImpl = new BlobImplString(aData, aContentType);
-  RegisterWeakMemoryReporter(blobImpl);
-  return blobImpl.forget();
-}
-
-BlobImplString::BlobImplString(const nsACString& aData,
-                               const nsAString& aContentType)
-  : BlobImplBase(aContentType, aData.Length())
-  , mData(aData)
-{
-}
-
-BlobImplString::~BlobImplString()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplString::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplString(Substring(mData, aStart, aLength),
-                       aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplString::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  aRv = NS_NewCStringInputStream(aStream, mData);
-}
-
-NS_IMETHODIMP
-BlobImplString::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/string", KIND_HEAP, UNITS_BYTES,
-    mData.SizeOfExcludingThisIfUnshared(MallocSizeOf),
-    "Memory used to back a File/Blob based on a string.");
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplMemory implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplMemory, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplMemory(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplMemory::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mLength > INT32_MAX) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aRv = DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
-}
-
-/* static */ StaticMutex
-BlobImplMemory::DataOwner::sDataOwnerMutex;
-
-/* static */ StaticAutoPtr<LinkedList<BlobImplMemory::DataOwner>>
-BlobImplMemory::DataOwner::sDataOwners;
-
-/* static */ bool
-BlobImplMemory::DataOwner::sMemoryReporterRegistered = false;
-
-MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
-
-class BlobImplMemoryDataOwnerMemoryReporter final
-  : public nsIMemoryReporter
-{
-  ~BlobImplMemoryDataOwnerMemoryReporter() {}
-
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
-                            nsISupports* aData, bool aAnonymize) override
-  {
-    typedef BlobImplMemory::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);
-
-      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);
-
-        nsAutoCString digestString;
-        for (size_t i = 0; i < sizeof(digest); i++) {
-          digestString.AppendPrintf("%02x", digest[i]);
-        }
-
-        aHandleReport->Callback(
-          /* process */ NS_LITERAL_CSTRING(""),
-          nsPrintfCString(
-            "explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
-            owner->mLength, aAnonymize ? "<anonymized>" : digestString.get()),
-          KIND_HEAP, UNITS_BYTES, size,
-          nsPrintfCString(
-            "Memory used to back a memory file of length %llu bytes.  The file "
-            "has a sha1 of %s.\n\n"
-            "Note that the allocator may round up a memory file's length -- "
-            "that is, an N-byte memory file may take up more than N bytes of "
-            "memory.",
-            owner->mLength, digestString.get()),
-          aData);
-      }
-    }
-
-    if (smallObjectsTotal > 0) {
-      aHandleReport->Callback(
-        /* process */ NS_LITERAL_CSTRING(""),
-        NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
-        KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
-        nsPrintfCString(
-          "Memory used to back small memory files (i.e. those taking up less "
-          "than %zu bytes of memory each).\n\n"
-          "Note that the allocator may round up a memory file's length -- "
-          "that is, an N-byte memory file may take up more than N bytes of "
-          "memory.", LARGE_OBJECT_MIN_SIZE),
-        aData);
-    }
-
-    return NS_OK;
-  }
-};
-
-NS_IMPL_ISUPPORTS(BlobImplMemoryDataOwnerMemoryReporter, nsIMemoryReporter)
-
-/* static */ void
-BlobImplMemory::DataOwner::EnsureMemoryReporterRegistered()
-{
-  sDataOwnerMutex.AssertCurrentThreadOwns();
-  if (sMemoryReporterRegistered) {
-    return;
-  }
-
-  RegisterStrongMemoryReporter(new BlobImplMemoryDataOwnerMemoryReporter());
-
-  sMemoryReporterRegistered = true;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplTemporaryBlob implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplTemporaryBlob, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplTemporaryBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                                   const nsAString& aContentType,
-                                   ErrorResult& aRv)
-{
-  if (aStart + aLength > mLength) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplTemporaryBlob(this, aStart + mStartPos,
-                              aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplTemporaryBlob::GetInternalStream(nsIInputStream** aStream,
-                                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> stream =
-    new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength);
-  stream.forget(aStream);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplStream implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplStream, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aContentType,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aContentType, aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aName, aContentType, aLastModifiedDate,
-                       aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aContentType,
-                               uint64_t aLength)
-  : BlobImplBase(aContentType, aLength)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(BlobImplStream* aOther,
-                               const nsAString& aContentType,
-                               uint64_t aStart, uint64_t aLength)
-  : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-  , mInputStream(new SlicedInputStream(aOther->mInputStream, aStart, aLength))
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aName,
-                               const nsAString& aContentType,
-                               int64_t aLastModifiedDate,
-                               uint64_t aLength)
-  : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::~BlobImplStream()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-void
-BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> clonedStream;
-  nsCOMPtr<nsIInputStream> replacementStream;
-
-  aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
-                            getter_AddRefs(replacementStream));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  if (replacementStream) {
-    mInputStream = replacementStream.forget();
-  }
-
-  clonedStream.forget(aStream);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplStream::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType, ErrorResult& aRv)
-{
-  if (!aLength) {
-    RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-    return impl.forget();
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplStream(this, aContentType, aStart, aLength);
-  return impl.forget();
-}
-
-void
-BlobImplStream::MaybeRegisterMemoryReporter()
-{
-  // We report only stringInputStream.
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return;
-  }
-
-  RegisterWeakMemoryReporter(this);
-}
-
-NS_IMETHODIMP
-BlobImplStream::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return NS_OK;
-  }
-
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
-    stringInputStream->SizeOfIncludingThis(MallocSizeOf),
-    "Memory used to back a File/Blob based on an input stream.");
-
-  return NS_OK;
-}
-
 } // namespace dom
 } // namespace mozilla
copy from dom/file/File.h
copy to dom/file/BaseBlobImpl.h
--- a/dom/file/File.h
+++ b/dom/file/BaseBlobImpl.h
@@ -1,395 +1,69 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_dom_File_h
-#define mozilla_dom_File_h
+#ifndef mozilla_dom_BaseBlobImpl_h
+#define mozilla_dom_BaseBlobImpl_h
 
-#include "mozilla/Attributes.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/GuardObjects.h"
-#include "mozilla/LinkedList.h"
-#include "mozilla/StaticMutex.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/Date.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMBlob.h"
-#include "nsIFile.h"
-#include "nsIMemoryReporter.h"
-#include "nsIMutable.h"
-#include "nsIXMLHttpRequest.h"
-#include "nsString.h"
-#include "nsTemporaryFileInputStream.h"
-#include "nsWrapperCache.h"
-#include "nsWeakReference.h"
-
-class nsIFile;
-class nsIInputStream;
-
-#define BLOBIMPL_IID \
-  { 0xbccb3275, 0x6778, 0x4ac5, \
-    { 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
+#include "mozilla/dom/BlobImpl.h"
 
 namespace mozilla {
 namespace dom {
 
-struct BlobPropertyBag;
-struct ChromeFilePropertyBag;
-struct FilePropertyBag;
-class BlobImpl;
-class File;
-class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
-class Promise;
-
-class Blob : public nsIDOMBlob
-           , public nsIXHRSendable
-           , public nsIMutable
-           , public nsSupportsWeakReference
-           , public nsWrapperCache
+class BaseBlobImpl : public BlobImpl
 {
 public:
-  NS_DECL_NSIDOMBLOB
-  NS_DECL_NSIXHRSENDABLE
-  NS_DECL_NSIMUTABLE
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
-
-  typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
-
-  // This creates a Blob or a File based on the type of BlobImpl.
-  static Blob*
-  Create(nsISupports* aParent, BlobImpl* aImpl);
-
-  static already_AddRefed<Blob>
-  CreateStringBlob(nsISupports* aParent, const nsACString& aData,
-                   const nsAString& aContentType);
-
-  // The returned Blob takes ownership of aMemoryBuffer. aMemoryBuffer will be
-  // freed by free so it must be allocated by malloc or something
-  // compatible with it.
-  static already_AddRefed<Blob>
-  CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
-                   const nsAString& aContentType);
-
-  static already_AddRefed<Blob>
-  CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
-                      uint64_t aStartPos, uint64_t aLength,
-                      const nsAString& aContentType);
-
-  BlobImpl* Impl() const
-  {
-    return mImpl;
-  }
-
-  bool IsFile() const;
-
-  const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const;
-
-  // This method returns null if this Blob is not a File; it returns
-  // the same object in case this Blob already implements the File interface;
-  // otherwise it returns a new File object with the same BlobImpl.
-  already_AddRefed<File> ToFile();
-
-  // This method creates a new File object with the given name and the same
-  // BlobImpl.
-  already_AddRefed<File> ToFile(const nsAString& aName,
-                                ErrorResult& aRv) const;
-
-  already_AddRefed<Blob>
-  CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
-              ErrorResult& aRv);
-
-  void
-  GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv);
-
-  int64_t
-  GetFileId();
-
-  // WebIDL methods
-  nsISupports* GetParentObject() const
-  {
-    return mParent;
-  }
-
-  bool
-  IsMemoryFile() const;
-
-  // Blob constructor
-  static already_AddRefed<Blob>
-  Constructor(const GlobalObject& aGlobal,
-              const Optional<Sequence<BlobPart>>& aData,
-              const BlobPropertyBag& aBag,
-              ErrorResult& aRv);
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  uint64_t GetSize(ErrorResult& aRv);
-
-  void GetType(nsAString& aType);
-
-  already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
-                               const Optional<int64_t>& aEnd,
-                               const nsAString& aContentType,
-                               ErrorResult& aRv);
-
-protected:
-  // File constructor should never be used directly. Use Blob::Create instead.
-  Blob(nsISupports* aParent, BlobImpl* aImpl);
-  virtual ~Blob() {};
-
-  virtual bool HasFileInterface() const { return false; }
-
-  // The member is the real backend implementation of this File/Blob.
-  // 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!
-  RefPtr<BlobImpl> mImpl;
-
-private:
-  nsCOMPtr<nsISupports> mParent;
-};
-
-class File final : public Blob
-{
-  friend class Blob;
-
-public:
-  // Note: BlobImpl must be a File in order to use this method.
-  // Check impl->IsFile().
-  static File*
-  Create(nsISupports* aParent, BlobImpl* aImpl);
-
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aName,
-         const nsAString& aContentType, uint64_t aLength,
-         int64_t aLastModifiedDate);
-
-  // The returned File takes ownership of aMemoryBuffer. aMemoryBuffer will be
-  // freed by free so it must be allocated by malloc or something
-  // compatible with it.
-  static already_AddRefed<File>
-  CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
-                   const nsAString& aName, const nsAString& aContentType,
-                   int64_t aLastModifiedDate);
-
-  // This method creates a BlobFileImpl for the new File object. This is
-  // thread-safe, cross-process, cross-thread as any other BlobImpl, but, when
-  // GetType() is called, it must dispatch a runnable to the main-thread in
-  // order to use nsIMIMEService.
-  // Would be nice if we try to avoid to use this method outside the
-  // main-thread to avoid extra runnables.
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile);
-
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile, const nsAString& aName,
-                 const nsAString& aContentType);
-
-  // WebIDL methods
-
-  virtual JSObject* WrapObject(JSContext *cx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  // File constructor
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const Sequence<BlobPart>& aData,
-              const nsAString& aName,
-              const FilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromFileName(const GlobalObject& aGlobal,
-                     const nsAString& aFilePath,
-                     const ChromeFilePropertyBag& aBag,
-                     SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromNsIFile(const GlobalObject& aGlobal,
-                    nsIFile* aFile,
-                    const ChromeFilePropertyBag& aBag,
-                    SystemCallerGuarantee aGuarantee,
-                    ErrorResult& aRv);
-
-  void GetName(nsAString& aName) const;
-
-  int64_t GetLastModified(ErrorResult& aRv);
-
-  Date GetLastModifiedDate(ErrorResult& aRv);
-
-  void GetRelativePath(nsAString& aPath) const;
-
-  void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                      ErrorResult& aRv) const;
-
-  void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv) const;
-
-protected:
-  virtual bool HasFileInterface() const override { return true; }
-
-private:
-  // File constructor should never be used directly. Use Blob::Create or
-  // File::Create.
-  File(nsISupports* aParent, BlobImpl* aImpl);
-  ~File() {};
-};
-
-// This is the abstract class for any File backend. It must be nsISupports
-// because this class must be ref-counted and it has to work with IPC.
-class BlobImpl : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(BLOBIMPL_IID)
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  BlobImpl() {}
-
-  virtual void GetName(nsAString& aName) const = 0;
-
-  virtual void GetDOMPath(nsAString& aName) const = 0;
-
-  virtual void SetDOMPath(const nsAString& aName) = 0;
-
-  virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
-
-  virtual void SetLastModified(int64_t aLastModified) = 0;
-
-  virtual void GetMozFullPath(nsAString& aName,
-                              SystemCallerGuarantee /* unused */,
-                              ErrorResult& aRv) const = 0;
-
-  virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const = 0;
-
-  virtual uint64_t GetSize(ErrorResult& aRv) = 0;
-
-  virtual void GetType(nsAString& aType) = 0;
-
-  /**
-   * An effectively-unique serial number identifying this instance of FileImpl.
-   *
-   * Implementations should obtain a serial number from
-   * FileImplBase::NextSerialNumber().
-   */
-  virtual uint64_t GetSerialNumber() const = 0;
-
-  already_AddRefed<BlobImpl>
-  Slice(const Optional<int64_t>& aStart, const Optional<int64_t>& aEnd,
-        const nsAString& aContentType, ErrorResult& aRv);
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) = 0;
-
-  virtual const nsTArray<RefPtr<BlobImpl>>*
-  GetSubBlobImpls() const = 0;
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) = 0;
-
-  virtual int64_t GetFileId() = 0;
-
-  virtual nsresult GetSendInfo(nsIInputStream** aBody,
-                               uint64_t* aContentLength,
-                               nsACString& aContentType,
-                               nsACString& aCharset) = 0;
-
-  virtual nsresult GetMutable(bool* aMutable) const = 0;
-
-  virtual nsresult SetMutable(bool aMutable) = 0;
-
-  virtual void SetLazyData(const nsAString& aName,
-                           const nsAString& aContentType,
-                           uint64_t aLength,
-                           int64_t aLastModifiedDate) = 0;
-
-  virtual bool IsMemoryFile() const = 0;
-
-  virtual bool IsSizeUnknown() const = 0;
-
-  virtual bool IsDateUnknown() const = 0;
-
-  virtual bool IsFile() const = 0;
-
-  // Returns true if the BlobImpl is backed by an nsIFile and the underlying
-  // file is a directory.
-  virtual bool IsDirectory() const
-  {
-    return false;
-  }
-
-  // True if this implementation can be sent to other threads.
-  virtual bool MayBeClonedToOtherThreads() const
-  {
-    return true;
-  }
-
-protected:
-  virtual ~BlobImpl() {}
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(BlobImpl, BLOBIMPL_IID)
-
-class BlobImplBase : public BlobImpl
-{
-public:
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
+  BaseBlobImpl(const nsAString& aName, const nsAString& aContentType,
                uint64_t aLength, int64_t aLastModifiedDate)
     : mIsFile(true)
     , mImmutable(false)
     , mContentType(aContentType)
     , mName(aName)
     , mStart(0)
     , mLength(aLength)
     , mLastModificationDate(aLastModifiedDate)
     , mSerialNumber(NextSerialNumber())
   {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
+  BaseBlobImpl(const nsAString& aName, const nsAString& aContentType,
                uint64_t aLength)
     : mIsFile(true)
     , mImmutable(false)
     , mContentType(aContentType)
     , mName(aName)
     , mStart(0)
     , mLength(aLength)
     , mLastModificationDate(INT64_MAX)
     , mSerialNumber(NextSerialNumber())
   {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  BlobImplBase(const nsAString& aContentType, uint64_t aLength)
+  BaseBlobImpl(const nsAString& aContentType, uint64_t aLength)
     : mIsFile(false)
     , mImmutable(false)
     , mContentType(aContentType)
     , mStart(0)
     , mLength(aLength)
     , mLastModificationDate(INT64_MAX)
     , mSerialNumber(NextSerialNumber())
   {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  BlobImplBase(const nsAString& aContentType, uint64_t aStart,
+  BaseBlobImpl(const nsAString& aContentType, uint64_t aStart,
                uint64_t aLength)
     : mIsFile(false)
     , mImmutable(false)
     , mContentType(aContentType)
     , mStart(aStart)
     , mLength(aLength)
     , mLastModificationDate(INT64_MAX)
     , mSerialNumber(NextSerialNumber())
@@ -482,17 +156,17 @@ public:
   }
 
   virtual bool IsSizeUnknown() const override
   {
     return mLength == UINT64_MAX;
   }
 
 protected:
-  virtual ~BlobImplBase() {}
+  virtual ~BaseBlobImpl() {}
 
   /**
    * Returns a new, effectively-unique serial number. This should be used
    * by implementations to obtain a serial number for GetSerialNumber().
    * The implementation is thread safe.
    */
   static uint64_t NextSerialNumber();
 
@@ -506,354 +180,12 @@ protected:
   uint64_t mStart;
   uint64_t mLength;
 
   int64_t mLastModificationDate;
 
   const uint64_t mSerialNumber;
 };
 
-class BlobImplString final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplString>
-  Create(const nsACString& aData, const nsAString& aContentType);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplString(const nsACString& aData, const nsAString& aContentType);
-
-  ~BlobImplString();
-
-  nsCString mData;
-};
-
-/**
- * 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 BlobImplMemory final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
-                 const nsAString& aContentType, int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength,
-                 const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-  class DataOwner final : public mozilla::LinkedListElement<DataOwner>
-  {
-  public:
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
-    DataOwner(void* aMemoryBuffer, uint64_t aLength)
-      : mData(aMemoryBuffer)
-      , mLength(aLength)
-    {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      if (!sDataOwners) {
-        sDataOwners = new mozilla::LinkedList<DataOwner>();
-        EnsureMemoryReporterRegistered();
-      }
-      sDataOwners->insertBack(this);
-    }
-
-  private:
-    // Private destructor, to discourage deletion outside of Release():
-    ~DataOwner() {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      remove();
-      if (sDataOwners->isEmpty()) {
-        // Free the linked list if it's empty.
-        sDataOwners = nullptr;
-      }
-
-      free(mData);
-    }
-
-  public:
-    static void EnsureMemoryReporterRegistered();
-
-    // sDataOwners and sMemoryReporterRegistered may only be accessed while
-    // holding sDataOwnerMutex!  You also must hold the mutex while touching
-    // elements of the linked list that DataOwner inherits from.
-    static mozilla::StaticMutex sDataOwnerMutex;
-    static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
-    static bool sMemoryReporterRegistered;
-
-    void* mData;
-    uint64_t mLength;
-  };
-
-private:
-  // Create slice
-  BlobImplMemory(const BlobImplMemory* aOther, uint64_t aStart,
-                 uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mDataOwner(aOther->mDataOwner)
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-    mImmutable = aOther->mImmutable;
-  }
-
-  ~BlobImplMemory() {}
-
-  // Used when backed by a memory store
-  RefPtr<DataOwner> mDataOwner;
-};
-
-class BlobImplTemporaryBlob final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplTemporaryBlob(PRFileDesc* aFD, uint64_t aStartPos,
-                        uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStartPos)
-  {
-    mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplTemporaryBlob(const BlobImplTemporaryBlob* aOther,
-                        uint64_t aStart, uint64_t aLength,
-                        const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStart)
-    , mFileDescOwner(aOther->mFileDescOwner)
-  {}
-
-  ~BlobImplTemporaryBlob() {}
-
-  uint64_t mStartPos;
-  RefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
-};
-
-class BlobImplFile : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // Create as a file
-  explicit BlobImplFile(nsIFile* aFile)
-    : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    // Lazily get the content type and size
-    mContentType.SetIsVoid(true);
-    mFile->GetLeafName(mName);
-  }
-
-  // Create as a file
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile)
-    : BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile,
-               int64_t aLastModificationDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModificationDate)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  // Create as a file with custom name
-  BlobImplFile(nsIFile* aFile, const nsAString& aName,
-               const nsAString& aContentType)
-    : BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    if (aContentType.IsEmpty()) {
-      // Lazily get the content type and size
-      mContentType.SetIsVoid(true);
-    }
-  }
-
-  // Overrides
-  virtual uint64_t GetSize(ErrorResult& aRv) override;
-  virtual void GetType(nsAString& aType) override;
-  virtual int64_t GetLastModified(ErrorResult& aRv) override;
-  virtual void SetLastModified(int64_t aLastModified) override;
-  virtual void GetMozFullPathInternal(nsAString& aFullPath,
-                                      ErrorResult& aRv) const override;
-  virtual void GetInternalStream(nsIInputStream** aInputStream,
-                                 ErrorResult& aRv) override;
-
-  virtual bool IsDirectory() const override;
-
-  // We always have size and date for this kind of blob.
-  virtual bool IsSizeUnknown() const override { return false; }
-  virtual bool IsDateUnknown() const override { return false; }
-
-protected:
-  virtual ~BlobImplFile() = default;
-
-private:
-  // Create slice
-  BlobImplFile(const BlobImplFile* aOther, uint64_t aStart,
-               uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mFile(aOther->mFile)
-    , mWholeFile(false)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    mImmutable = aOther->mImmutable;
-  }
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  nsCOMPtr<nsIFile> mFile;
-  bool mWholeFile;
-};
-
-class EmptyBlobImpl final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  explicit EmptyBlobImpl(const nsAString& aContentType)
-    : BlobImplBase(aContentType, 0 /* aLength */)
-  {
-    mImmutable = true;
-  }
-
-  EmptyBlobImpl(const nsAString& aName,
-                const nsAString& aContentType,
-                int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, 0, aLastModifiedDate)
-  {
-    mImmutable = true;
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-private:
-  ~EmptyBlobImpl() {}
-};
-
-class BlobImplStream final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aContentType,
-         uint64_t aLength);
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aName,
-         const nsAString& aContentType,
-         int64_t aLastModifiedDate,
-         uint64_t aLength);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-private:
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aContentType,
-                 uint64_t aLength);
-
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aName,
-                 const nsAString& aContentType,
-                 int64_t aLastModifiedDate,
-                 uint64_t aLength);
-
-  BlobImplStream(BlobImplStream* aOther,
-                 const nsAString& aContentType,
-                 uint64_t aStart,
-                 uint64_t aLength);
-
-  ~BlobImplStream();
-
-  void MaybeRegisterMemoryReporter();
-
-  nsCOMPtr<nsIInputStream> mInputStream;
-};
-
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_File_h
+#endif // mozilla_dom_BaseBlobImpl_h
copy from dom/file/File.cpp
copy to dom/file/Blob.cpp
--- a/dom/file/File.cpp
+++ b/dom/file/Blob.cpp
@@ -1,140 +1,29 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/File.h"
-
-#include "ipc/nsIRemoteBlob.h"
+#include "Blob.h"
+#include "File.h"
+#include "MemoryBlobImpl.h"
+#include "mozilla/dom/BlobBinding.h"
 #include "MultipartBlobImpl.h"
-#include "nsCExternalHandlerService.h"
-#include "nsContentCID.h"
-#include "nsContentUtils.h"
-#include "nsError.h"
-#include "nsICharsetDetector.h"
-#include "nsIConverterInputStream.h"
-#include "nsIDocument.h"
-#include "nsIFileStreams.h"
+#include "ipc/nsIRemoteBlob.h"
 #include "nsIInputStream.h"
-#include "nsIIPCSerializableInputStream.h"
-#include "nsIMIMEService.h"
-#include "nsISeekableStream.h"
-#include "nsIUnicharInputStream.h"
-#include "nsIUnicodeDecoder.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsIUUIDGenerator.h"
-#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/DOMError.h"
-#include "mozilla/dom/FileBinding.h"
-#include "mozilla/dom/FileCreatorHelper.h"
-#include "mozilla/dom/FileSystemUtils.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerRunnable.h"
-#include "nsThreadUtils.h"
-#include "nsStreamUtils.h"
-#include "SlicedInputStream.h"
+#include "nsPIDOMWindow.h"
+#include "TemporaryBlobImpl.h"
+#include "StreamBlobImpl.h"
+#include "StringBlobImpl.h"
 
 namespace mozilla {
 namespace dom {
 
-using namespace workers;
-
-// XXXkhuey the input stream that we pass out of a File
-// can outlive the actual File 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 final : public nsIInputStream,
-                               public nsISeekableStream,
-                               public nsIIPCSerializableInputStream
-{
-  typedef BlobImplMemory::DataOwner DataOwner;
-public:
-  static nsresult Create(DataOwner* aDataOwner,
-                         uint32_t aStart,
-                         uint32_t aLength,
-                         nsIInputStream** _retval);
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  // These are mandatory.
-  NS_FORWARD_NSIINPUTSTREAM(mStream->)
-  NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
-
-  // This is optional. We use a conditional QI to keep it from being called
-  // if the underlying stream doesn't support it.
-  NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
-
-private:
-  ~DataOwnerAdapter() {}
-
-  DataOwnerAdapter(DataOwner* aDataOwner,
-                   nsIInputStream* aStream)
-    : mDataOwner(aDataOwner), mStream(aStream),
-      mSeekableStream(do_QueryInterface(aStream)),
-      mSerializableInputStream(do_QueryInterface(aStream))
-  {
-    MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
-  }
-
-  RefPtr<DataOwner> mDataOwner;
-  nsCOMPtr<nsIInputStream> mStream;
-  nsCOMPtr<nsISeekableStream> mSeekableStream;
-  nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
-};
-
-NS_IMPL_ADDREF(DataOwnerAdapter)
-NS_IMPL_RELEASE(DataOwnerAdapter)
-
-NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
-  NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
-                                     mSerializableInputStream)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
-NS_INTERFACE_MAP_END
-
-nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
-                                  uint32_t aStart,
-                                  uint32_t aLength,
-                                  nsIInputStream** _retval)
-{
-  nsresult rv;
-  MOZ_ASSERT(aDataOwner, "Uh ...");
-
-  nsCOMPtr<nsIInputStream> stream;
-
-  rv = NS_NewByteInputStream(getter_AddRefs(stream),
-                             static_cast<const char*>(aDataOwner->mData) +
-                             aStart,
-                             (int32_t)aLength,
-                             NS_ASSIGNMENT_DEPEND);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
-
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::Blob implementation
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
   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(Blob)
@@ -155,24 +44,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
   NS_INTERFACE_MAP_ENTRY(nsIMutable)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
 
-// A utility function that enforces the spec constraints on the type of a blob:
-// no codepoints outside the ASCII range (otherwise type becomes empty) and
-// lowercase ASCII only.  We can't just use our existing nsContentUtils
-// ASCII-related helpers because we need the "outside ASCII range" check, and we
-// can't use NS_IsAscii because its definition of "ASCII" (chars all <= 0x7E)
-// differs from the file API definition (which excludes control chars).
-static void
-MakeValidBlobType(nsAString& aType)
+void
+Blob::MakeValidBlobType(nsAString& aType)
 {
   char16_t* iter = aType.BeginWriting();
   char16_t* end = aType.EndWriting();
 
   for ( ; iter != end; ++iter) {
     char16_t c = *iter;
     if (c < 0x20 || c > 0x7E) {
       // Non-ASCII char, bail out.
@@ -194,39 +77,39 @@ Blob::Create(nsISupports* aParent, BlobI
   return aImpl->IsFile() ? new File(aParent, aImpl)
                          : new Blob(aParent, aImpl);
 }
 
 /* static */ already_AddRefed<Blob>
 Blob::CreateStringBlob(nsISupports* aParent, const nsACString& aData,
                        const nsAString& aContentType)
 {
-  RefPtr<BlobImpl> blobImpl = BlobImplString::Create(aData, aContentType);
+  RefPtr<BlobImpl> blobImpl = StringBlobImpl::Create(aData, aContentType);
   RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
   MOZ_ASSERT(!blob->mImpl->IsFile());
   return blob.forget();
 }
 
 /* static */ already_AddRefed<Blob>
 Blob::CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer,
                        uint64_t aLength, const nsAString& aContentType)
 {
   RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aContentType));
+    new MemoryBlobImpl(aMemoryBuffer, aLength, aContentType));
   MOZ_ASSERT(!blob->mImpl->IsFile());
   return blob.forget();
 }
 
 /* static */ already_AddRefed<Blob>
 Blob::CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
                           uint64_t aStartPos, uint64_t aLength,
                           const nsAString& aContentType)
 {
   RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplTemporaryBlob(aFD, aStartPos, aLength, aContentType));
+    new TemporaryBlobImpl(aFD, aStartPos, aLength, aContentType));
   MOZ_ASSERT(!blob->mImpl->IsFile());
   return blob.forget();
 }
 
 Blob::Blob(nsISupports* aParent, BlobImpl* aImpl)
   : mImpl(aImpl)
   , mParent(aParent)
 {
@@ -237,16 +120,19 @@ Blob::Blob(nsISupports* aParent, BlobImp
     nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aParent);
     if (win) {
       MOZ_ASSERT(win->IsInnerWindow());
     }
   }
 #endif
 }
 
+Blob::~Blob()
+{}
+
 bool
 Blob::IsFile() const
 {
   return mImpl->IsFile();
 }
 
 const nsTArray<RefPtr<BlobImpl>>*
 Blob::GetSubBlobImpls() const
@@ -399,952 +285,10 @@ Blob::IsMemoryFile() const
 }
 
 void
 Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
 {
   mImpl->GetInternalStream(aStream, aRv);
 }
 
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::File implementation
-
-File::File(nsISupports* aParent, BlobImpl* aImpl)
-  : Blob(aParent, aImpl)
-{
-  MOZ_ASSERT(aImpl->IsFile());
-}
-
-/* static */ File*
-File::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-  MOZ_ASSERT(aImpl->IsFile());
-
-  return new File(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aName,
-             const nsAString& aContentType, uint64_t aLength,
-             int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aName,
-                       aContentType, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile)
-{
-  RefPtr<File> file = new File(aParent, new BlobImplFile(aFile));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                     const nsAString& aName, const nsAString& aContentType)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplFile(aFile, aName, aContentType));
-  return file.forget();
-}
-
-JSObject*
-File::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return FileBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-File::GetName(nsAString& aFileName) const
-{
-  mImpl->GetName(aFileName);
-}
-
-void
-File::GetRelativePath(nsAString& aPath) const
-{
-  aPath.Truncate();
-
-  nsAutoString path;
-  mImpl->GetDOMPath(path);
-
-  // WebkitRelativePath doesn't start with '/'
-  if (!path.IsEmpty()) {
-    MOZ_ASSERT(path[0] == FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
-    aPath.Assign(Substring(path, 1));
-  }
-}
-
-Date
-File::GetLastModifiedDate(ErrorResult& aRv)
-{
-  int64_t value = GetLastModified(aRv);
-  if (aRv.Failed()) {
-    return Date();
-  }
-
-  return Date(JS::TimeClip(value));
-}
-
-int64_t
-File::GetLastModified(ErrorResult& aRv)
-{
-  return mImpl->GetLastModified(aRv);
-}
-
-void
-File::GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPath(aFilename, aGuarantee, aRv);
-}
-
-void
-File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPathInternal(aFileName, aRv);
-}
-
-// 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;
-  if (aStart < -aSize) {
-    newStartOffset = 0;
-  }
-  else if (aStart < 0) {
-    newStartOffset += aSize;
-  }
-  else if (aStart > aSize) {
-    newStartOffset = aSize;
-  }
-
-  CheckedInt64 newEndOffset = aEnd;
-  if (aEnd < -aSize) {
-    newEndOffset = 0;
-  }
-  else if (aEnd < 0) {
-    newEndOffset += aSize;
-  }
-  else if (aEnd > aSize) {
-    newEndOffset = aSize;
-  }
-
-  if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
-      newStartOffset.value() >= newEndOffset.value()) {
-    aStart = aEnd = 0;
-  }
-  else {
-    aStart = newStartOffset.value();
-    aEnd = newEndOffset.value();
-  }
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  const Sequence<BlobPart>& aData,
-                  const nsAString& aName,
-                  const FilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  // Normalizing the filename
-  nsString name(aName);
-  name.ReplaceChar('/', ':');
-
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(name);
-
-  nsAutoString type(aBag.mType);
-  MakeValidBlobType(type);
-  impl->InitializeBlob(aGlobal.Context(), aData, type, false, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
-
-  if (aBag.mLastModified.WasPassed()) {
-    impl->SetLastModified(aBag.mLastModified.Value());
-  }
-
-  RefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
-  return file.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromNsIFile(const GlobalObject& aGlobal,
-                        nsIFile* aData,
-                        const ChromeFilePropertyBag& aBag,
-                        SystemCallerGuarantee aGuarantee,
-                        ErrorResult& aRv)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, aData, aBag, true, aRv);
-  return promise.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromFileName(const GlobalObject& aGlobal,
-                         const nsAString& aPath,
-                         const ChromeFilePropertyBag& aBag,
-                         SystemCallerGuarantee aGuarantee,
-                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIFile> file;
-  aRv = NS_NewLocalFile(aPath, false, getter_AddRefs(file));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, file, aBag, false, aRv);
-  return promise.forget();
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::BlobImpl implementation
-
-already_AddRefed<BlobImpl>
-BlobImpl::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);
-
-  nsAutoString type(aContentType);
-  MakeValidBlobType(type);
-  return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImpl implementation
-
-NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFile, BlobImpl)
-
-void
-BlobImplBase::GetName(nsAString& aName) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aName = mName;
-}
-
-void
-BlobImplBase::GetDOMPath(nsAString& aPath) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aPath = mPath;
-}
-
-void
-BlobImplBase::SetDOMPath(const nsAString& aPath)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  mPath = aPath;
-}
-
-void
-BlobImplBase::GetMozFullPath(nsAString& aFileName,
-                             SystemCallerGuarantee /* unused */,
-                             ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-
-  GetMozFullPathInternal(aFileName, aRv);
-}
-
-void
-BlobImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  if (!mIsFile) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aFileName.Truncate();
-}
-
-void
-BlobImplBase::GetType(nsAString& aType)
-{
-  aType = mContentType;
-}
-
-int64_t
-BlobImplBase::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (IsDateUnknown()) {
-    mLastModificationDate = PR_Now();
-  }
-
-  return mLastModificationDate / PR_USEC_PER_MSEC;
-}
-
-void
-BlobImplBase::SetLastModified(int64_t aLastModified)
-{
-  mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
-}
-
-int64_t
-BlobImplBase::GetFileId()
-{
-  return -1;
-}
-
-nsresult
-BlobImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
-                          nsACString& aContentType, nsACString& aCharset)
-{
-  MOZ_ASSERT(aContentLength);
-
-  ErrorResult rv;
-
-  nsCOMPtr<nsIInputStream> stream;
-  GetInternalStream(getter_AddRefs(stream), rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  *aContentLength = GetSize(rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  nsAutoString contentType;
-  GetType(contentType);
-
-  if (contentType.IsEmpty()) {
-    aContentType.SetIsVoid(true);
-  } else {
-    CopyUTF16toUTF8(contentType, aContentType);
-  }
-
-  aCharset.Truncate();
-
-  stream.forget(aBody);
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::GetMutable(bool* aMutable) const
-{
-  *aMutable = !mImmutable;
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::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);
-
-    ErrorResult error;
-    GetSize(error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-  }
-
-  mImmutable = !aMutable;
-  return rv;
-}
-
-/* static */ uint64_t
-BlobImplBase::NextSerialNumber()
-{
-  static Atomic<uint64_t> nextSerialNumber;
-  return nextSerialNumber++;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-already_AddRefed<BlobImpl>
-BlobImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
-                          const nsAString& aContentType,
-                          ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplFile(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aRv = mFile->GetPath(aFilename);
-}
-
-uint64_t
-BlobImplFile::GetSize(ErrorResult& aRv)
-{
-  if (BlobImplBase::IsSizeUnknown()) {
-    MOZ_ASSERT(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;
-    }
-
-    if (fileSize < 0) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return 0;
-    }
-
-    mLength = fileSize;
-  }
-
-  return mLength;
-}
-
-namespace {
-
-class GetTypeRunnable final : public WorkerMainThreadRunnable
-{
-public:
-  GetTypeRunnable(WorkerPrivate* aWorkerPrivate,
-                  BlobImpl* aBlobImpl)
-    : WorkerMainThreadRunnable(aWorkerPrivate,
-                               NS_LITERAL_CSTRING("BlobImplFile :: GetType"))
-    , mBlobImpl(aBlobImpl)
-  {
-    MOZ_ASSERT(aBlobImpl);
-    aWorkerPrivate->AssertIsOnWorkerThread();
-  }
-
-  bool
-  MainThreadRun() override
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    nsAutoString type;
-    mBlobImpl->GetType(type);
-    return true;
-  }
-
-private:
-  ~GetTypeRunnable()
-  {}
-
-  RefPtr<BlobImpl> mBlobImpl;
-};
-
-} // anonymous namespace
-
-void
-BlobImplFile::GetType(nsAString& aType)
-{
-  aType.Truncate();
-
-  if (mContentType.IsVoid()) {
-    MOZ_ASSERT(mWholeFile,
-               "Should only use lazy ContentType when using the whole file");
-
-    if (!NS_IsMainThread()) {
-      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-      if (!workerPrivate) {
-        // I have no idea in which thread this method is called. We cannot
-        // return any valid value.
-        return;
-      }
-
-      RefPtr<GetTypeRunnable> runnable =
-        new GetTypeRunnable(workerPrivate, this);
-
-      ErrorResult rv;
-      runnable->Dispatch(Terminating, rv);
-      if (NS_WARN_IF(rv.Failed())) {
-        rv.SuppressException();
-      }
-      return;
-    }
-
-    nsresult rv;
-    nsCOMPtr<nsIMIMEService> mimeService =
-      do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-
-    nsAutoCString mimeType;
-    rv = mimeService->GetTypeFromFile(mFile, mimeType);
-    if (NS_FAILED(rv)) {
-      mimeType.Truncate();
-    }
-
-    AppendUTF8toUTF16(mimeType, mContentType);
-    mContentType.SetIsVoid(false);
-  }
-
-  aType = mContentType;
-}
-
-int64_t
-BlobImplFile::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (BlobImplBase::IsDateUnknown()) {
-    PRTime msecs;
-    aRv = mFile->GetLastModifiedTime(&msecs);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return 0;
-    }
-
-    mLastModificationDate = msecs;
-  }
-
-  return mLastModificationDate;
-}
-
-void
-BlobImplFile::SetLastModified(int64_t aLastModified)
-{
-  MOZ_CRASH("SetLastModified of a real file is not allowed!");
-}
-
-const uint32_t sFileStreamFlags =
-  nsIFileInputStream::CLOSE_ON_EOF |
-  nsIFileInputStream::REOPEN_ON_REWIND |
-  nsIFileInputStream::DEFER_OPEN |
-  nsIFileInputStream::SHARE_DELETE;
-
-void
-BlobImplFile::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mWholeFile) {
-    aRv = NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags);
-    return;
-  }
-
-  aRv = NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
-                                          -1, -1, sFileStreamFlags);
-}
-
-bool
-BlobImplFile::IsDirectory() const
-{
-  bool isDirectory = false;
-  if (mFile) {
-    mFile->IsDirectory(&isDirectory);
-  }
-  return isDirectory;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// EmptyBlobImpl implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
-
-already_AddRefed<BlobImpl>
-EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
-                           const nsAString& aContentType,
-                           ErrorResult& aRv)
-{
-  MOZ_ASSERT(!aStart && !aLength);
-  RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-
-  DebugOnly<bool> isMutable;
-  MOZ_ASSERT(NS_SUCCEEDED(impl->GetMutable(&isMutable)));
-  MOZ_ASSERT(!isMutable);
-
-  return impl.forget();
-}
-
-void
-EmptyBlobImpl::GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv)
-{
-  if (NS_WARN_IF(!aStream)) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
-    return;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplString implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplString, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplString>
-BlobImplString::Create(const nsACString& aData, const nsAString& aContentType)
-{
-  RefPtr<BlobImplString> blobImpl = new BlobImplString(aData, aContentType);
-  RegisterWeakMemoryReporter(blobImpl);
-  return blobImpl.forget();
-}
-
-BlobImplString::BlobImplString(const nsACString& aData,
-                               const nsAString& aContentType)
-  : BlobImplBase(aContentType, aData.Length())
-  , mData(aData)
-{
-}
-
-BlobImplString::~BlobImplString()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplString::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplString(Substring(mData, aStart, aLength),
-                       aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplString::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  aRv = NS_NewCStringInputStream(aStream, mData);
-}
-
-NS_IMETHODIMP
-BlobImplString::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/string", KIND_HEAP, UNITS_BYTES,
-    mData.SizeOfExcludingThisIfUnshared(MallocSizeOf),
-    "Memory used to back a File/Blob based on a string.");
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplMemory implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplMemory, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplMemory(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplMemory::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mLength > INT32_MAX) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aRv = DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
-}
-
-/* static */ StaticMutex
-BlobImplMemory::DataOwner::sDataOwnerMutex;
-
-/* static */ StaticAutoPtr<LinkedList<BlobImplMemory::DataOwner>>
-BlobImplMemory::DataOwner::sDataOwners;
-
-/* static */ bool
-BlobImplMemory::DataOwner::sMemoryReporterRegistered = false;
-
-MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
-
-class BlobImplMemoryDataOwnerMemoryReporter final
-  : public nsIMemoryReporter
-{
-  ~BlobImplMemoryDataOwnerMemoryReporter() {}
-
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
-                            nsISupports* aData, bool aAnonymize) override
-  {
-    typedef BlobImplMemory::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);
-
-      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);
-
-        nsAutoCString digestString;
-        for (size_t i = 0; i < sizeof(digest); i++) {
-          digestString.AppendPrintf("%02x", digest[i]);
-        }
-
-        aHandleReport->Callback(
-          /* process */ NS_LITERAL_CSTRING(""),
-          nsPrintfCString(
-            "explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
-            owner->mLength, aAnonymize ? "<anonymized>" : digestString.get()),
-          KIND_HEAP, UNITS_BYTES, size,
-          nsPrintfCString(
-            "Memory used to back a memory file of length %llu bytes.  The file "
-            "has a sha1 of %s.\n\n"
-            "Note that the allocator may round up a memory file's length -- "
-            "that is, an N-byte memory file may take up more than N bytes of "
-            "memory.",
-            owner->mLength, digestString.get()),
-          aData);
-      }
-    }
-
-    if (smallObjectsTotal > 0) {
-      aHandleReport->Callback(
-        /* process */ NS_LITERAL_CSTRING(""),
-        NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
-        KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
-        nsPrintfCString(
-          "Memory used to back small memory files (i.e. those taking up less "
-          "than %zu bytes of memory each).\n\n"
-          "Note that the allocator may round up a memory file's length -- "
-          "that is, an N-byte memory file may take up more than N bytes of "
-          "memory.", LARGE_OBJECT_MIN_SIZE),
-        aData);
-    }
-
-    return NS_OK;
-  }
-};
-
-NS_IMPL_ISUPPORTS(BlobImplMemoryDataOwnerMemoryReporter, nsIMemoryReporter)
-
-/* static */ void
-BlobImplMemory::DataOwner::EnsureMemoryReporterRegistered()
-{
-  sDataOwnerMutex.AssertCurrentThreadOwns();
-  if (sMemoryReporterRegistered) {
-    return;
-  }
-
-  RegisterStrongMemoryReporter(new BlobImplMemoryDataOwnerMemoryReporter());
-
-  sMemoryReporterRegistered = true;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplTemporaryBlob implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplTemporaryBlob, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplTemporaryBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                                   const nsAString& aContentType,
-                                   ErrorResult& aRv)
-{
-  if (aStart + aLength > mLength) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplTemporaryBlob(this, aStart + mStartPos,
-                              aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplTemporaryBlob::GetInternalStream(nsIInputStream** aStream,
-                                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> stream =
-    new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength);
-  stream.forget(aStream);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplStream implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplStream, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aContentType,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aContentType, aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aName, aContentType, aLastModifiedDate,
-                       aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aContentType,
-                               uint64_t aLength)
-  : BlobImplBase(aContentType, aLength)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(BlobImplStream* aOther,
-                               const nsAString& aContentType,
-                               uint64_t aStart, uint64_t aLength)
-  : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-  , mInputStream(new SlicedInputStream(aOther->mInputStream, aStart, aLength))
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aName,
-                               const nsAString& aContentType,
-                               int64_t aLastModifiedDate,
-                               uint64_t aLength)
-  : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::~BlobImplStream()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-void
-BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> clonedStream;
-  nsCOMPtr<nsIInputStream> replacementStream;
-
-  aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
-                            getter_AddRefs(replacementStream));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  if (replacementStream) {
-    mInputStream = replacementStream.forget();
-  }
-
-  clonedStream.forget(aStream);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplStream::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType, ErrorResult& aRv)
-{
-  if (!aLength) {
-    RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-    return impl.forget();
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplStream(this, aContentType, aStart, aLength);
-  return impl.forget();
-}
-
-void
-BlobImplStream::MaybeRegisterMemoryReporter()
-{
-  // We report only stringInputStream.
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return;
-  }
-
-  RegisterWeakMemoryReporter(this);
-}
-
-NS_IMETHODIMP
-BlobImplStream::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return NS_OK;
-  }
-
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
-    stringInputStream->SizeOfIncludingThis(MallocSizeOf),
-    "Memory used to back a File/Blob based on an input stream.");
-
-  return NS_OK;
-}
-
 } // namespace dom
 } // namespace mozilla
copy from dom/file/File.h
copy to dom/file/Blob.h
--- a/dom/file/File.h
+++ b/dom/file/Blob.h
@@ -1,54 +1,37 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_dom_File_h
-#define mozilla_dom_File_h
+#ifndef mozilla_dom_Blob_h
+#define mozilla_dom_Blob_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
-#include "mozilla/GuardObjects.h"
-#include "mozilla/LinkedList.h"
-#include "mozilla/StaticMutex.h"
-#include "mozilla/StaticPtr.h"
 #include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/Date.h"
+#include "mozilla/dom/BlobImpl.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMBlob.h"
-#include "nsIFile.h"
-#include "nsIMemoryReporter.h"
 #include "nsIMutable.h"
 #include "nsIXMLHttpRequest.h"
-#include "nsString.h"
-#include "nsTemporaryFileInputStream.h"
 #include "nsWrapperCache.h"
 #include "nsWeakReference.h"
 
-class nsIFile;
 class nsIInputStream;
 
-#define BLOBIMPL_IID \
-  { 0xbccb3275, 0x6778, 0x4ac5, \
-    { 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
-
 namespace mozilla {
 namespace dom {
 
 struct BlobPropertyBag;
-struct ChromeFilePropertyBag;
-struct FilePropertyBag;
-class BlobImpl;
 class File;
 class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
-class Promise;
 
 class Blob : public nsIDOMBlob
            , public nsIXHRSendable
            , public nsIMutable
            , public nsSupportsWeakReference
            , public nsWrapperCache
 {
 public:
@@ -105,16 +88,25 @@ public:
               ErrorResult& aRv);
 
   void
   GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv);
 
   int64_t
   GetFileId();
 
+  // A utility function that enforces the spec constraints on the type of a
+  // blob: no codepoints outside the ASCII range (otherwise type becomes empty)
+  // and lowercase ASCII only.  We can't just use our existing nsContentUtils
+  // ASCII-related helpers because we need the "outside ASCII range" check, and
+  // we can't use NS_IsAscii because its definition of "ASCII" (chars all <=
+  // 0x7E) differs from the file API definition (which excludes control chars).
+  static void
+  MakeValidBlobType(nsAString& aType);
+
   // WebIDL methods
   nsISupports* GetParentObject() const
   {
     return mParent;
   }
 
   bool
   IsMemoryFile() const;
@@ -136,724 +128,26 @@ public:
   already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
                                const Optional<int64_t>& aEnd,
                                const nsAString& aContentType,
                                ErrorResult& aRv);
 
 protected:
   // File constructor should never be used directly. Use Blob::Create instead.
   Blob(nsISupports* aParent, BlobImpl* aImpl);
-  virtual ~Blob() {};
+  virtual ~Blob();
 
   virtual bool HasFileInterface() const { return false; }
 
   // The member is the real backend implementation of this File/Blob.
   // 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!
   RefPtr<BlobImpl> mImpl;
 
 private:
   nsCOMPtr<nsISupports> mParent;
 };
 
-class File final : public Blob
-{
-  friend class Blob;
-
-public:
-  // Note: BlobImpl must be a File in order to use this method.
-  // Check impl->IsFile().
-  static File*
-  Create(nsISupports* aParent, BlobImpl* aImpl);
-
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aName,
-         const nsAString& aContentType, uint64_t aLength,
-         int64_t aLastModifiedDate);
-
-  // The returned File takes ownership of aMemoryBuffer. aMemoryBuffer will be
-  // freed by free so it must be allocated by malloc or something
-  // compatible with it.
-  static already_AddRefed<File>
-  CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
-                   const nsAString& aName, const nsAString& aContentType,
-                   int64_t aLastModifiedDate);
-
-  // This method creates a BlobFileImpl for the new File object. This is
-  // thread-safe, cross-process, cross-thread as any other BlobImpl, but, when
-  // GetType() is called, it must dispatch a runnable to the main-thread in
-  // order to use nsIMIMEService.
-  // Would be nice if we try to avoid to use this method outside the
-  // main-thread to avoid extra runnables.
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile);
-
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile, const nsAString& aName,
-                 const nsAString& aContentType);
-
-  // WebIDL methods
-
-  virtual JSObject* WrapObject(JSContext *cx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  // File constructor
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const Sequence<BlobPart>& aData,
-              const nsAString& aName,
-              const FilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromFileName(const GlobalObject& aGlobal,
-                     const nsAString& aFilePath,
-                     const ChromeFilePropertyBag& aBag,
-                     SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromNsIFile(const GlobalObject& aGlobal,
-                    nsIFile* aFile,
-                    const ChromeFilePropertyBag& aBag,
-                    SystemCallerGuarantee aGuarantee,
-                    ErrorResult& aRv);
-
-  void GetName(nsAString& aName) const;
-
-  int64_t GetLastModified(ErrorResult& aRv);
-
-  Date GetLastModifiedDate(ErrorResult& aRv);
-
-  void GetRelativePath(nsAString& aPath) const;
-
-  void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                      ErrorResult& aRv) const;
-
-  void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv) const;
-
-protected:
-  virtual bool HasFileInterface() const override { return true; }
-
-private:
-  // File constructor should never be used directly. Use Blob::Create or
-  // File::Create.
-  File(nsISupports* aParent, BlobImpl* aImpl);
-  ~File() {};
-};
-
-// This is the abstract class for any File backend. It must be nsISupports
-// because this class must be ref-counted and it has to work with IPC.
-class BlobImpl : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(BLOBIMPL_IID)
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  BlobImpl() {}
-
-  virtual void GetName(nsAString& aName) const = 0;
-
-  virtual void GetDOMPath(nsAString& aName) const = 0;
-
-  virtual void SetDOMPath(const nsAString& aName) = 0;
-
-  virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
-
-  virtual void SetLastModified(int64_t aLastModified) = 0;
-
-  virtual void GetMozFullPath(nsAString& aName,
-                              SystemCallerGuarantee /* unused */,
-                              ErrorResult& aRv) const = 0;
-
-  virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const = 0;
-
-  virtual uint64_t GetSize(ErrorResult& aRv) = 0;
-
-  virtual void GetType(nsAString& aType) = 0;
-
-  /**
-   * An effectively-unique serial number identifying this instance of FileImpl.
-   *
-   * Implementations should obtain a serial number from
-   * FileImplBase::NextSerialNumber().
-   */
-  virtual uint64_t GetSerialNumber() const = 0;
-
-  already_AddRefed<BlobImpl>
-  Slice(const Optional<int64_t>& aStart, const Optional<int64_t>& aEnd,
-        const nsAString& aContentType, ErrorResult& aRv);
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) = 0;
-
-  virtual const nsTArray<RefPtr<BlobImpl>>*
-  GetSubBlobImpls() const = 0;
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) = 0;
-
-  virtual int64_t GetFileId() = 0;
-
-  virtual nsresult GetSendInfo(nsIInputStream** aBody,
-                               uint64_t* aContentLength,
-                               nsACString& aContentType,
-                               nsACString& aCharset) = 0;
-
-  virtual nsresult GetMutable(bool* aMutable) const = 0;
-
-  virtual nsresult SetMutable(bool aMutable) = 0;
-
-  virtual void SetLazyData(const nsAString& aName,
-                           const nsAString& aContentType,
-                           uint64_t aLength,
-                           int64_t aLastModifiedDate) = 0;
-
-  virtual bool IsMemoryFile() const = 0;
-
-  virtual bool IsSizeUnknown() const = 0;
-
-  virtual bool IsDateUnknown() const = 0;
-
-  virtual bool IsFile() const = 0;
-
-  // Returns true if the BlobImpl is backed by an nsIFile and the underlying
-  // file is a directory.
-  virtual bool IsDirectory() const
-  {
-    return false;
-  }
-
-  // True if this implementation can be sent to other threads.
-  virtual bool MayBeClonedToOtherThreads() const
-  {
-    return true;
-  }
-
-protected:
-  virtual ~BlobImpl() {}
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(BlobImpl, BLOBIMPL_IID)
-
-class BlobImplBase : public BlobImpl
-{
-public:
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, int64_t aLastModifiedDate)
-    : mIsFile(true)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mName(aName)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(aLastModifiedDate)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength)
-    : mIsFile(true)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mName(aName)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aContentType, uint64_t aLength)
-    : mIsFile(false)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aContentType, uint64_t aStart,
-               uint64_t aLength)
-    : mIsFile(false)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mStart(aStart)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  virtual void GetName(nsAString& aName) const override;
-
-  virtual void GetDOMPath(nsAString& aName) const override;
-
-  virtual void SetDOMPath(const nsAString& aName) override;
-
-  virtual int64_t GetLastModified(ErrorResult& aRv) override;
-
-  virtual void SetLastModified(int64_t aLastModified) override;
-
-  virtual void GetMozFullPath(nsAString& aName,
-                              SystemCallerGuarantee /* unused */,
-                              ErrorResult& aRv) const override;
-
-  virtual void GetMozFullPathInternal(nsAString& aFileName,
-                                      ErrorResult& aRv) const override;
-
-  virtual uint64_t GetSize(ErrorResult& aRv) override
-  {
-    return mLength;
-  }
-
-  virtual void GetType(nsAString& aType) override;
-
-  virtual uint64_t GetSerialNumber() const override { return mSerialNumber; }
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override
-  {
-    return nullptr;
-  }
-
-  virtual const nsTArray<RefPtr<BlobImpl>>*
-  GetSubBlobImpls() const override
-  {
-    return nullptr;
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override
-  {
-    aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-  }
-
-  virtual int64_t GetFileId() override;
-
-  virtual nsresult GetSendInfo(nsIInputStream** aBody,
-                               uint64_t* aContentLength,
-                               nsACString& aContentType,
-                               nsACString& aCharset) override;
-
-  virtual nsresult GetMutable(bool* aMutable) const override;
-
-  virtual nsresult SetMutable(bool aMutable) override;
-
-  virtual void
-  SetLazyData(const nsAString& aName, const nsAString& aContentType,
-              uint64_t aLength, int64_t aLastModifiedDate) override
-  {
-    mName = aName;
-    mContentType = aContentType;
-    mLength = aLength;
-    mLastModificationDate = aLastModifiedDate;
-    mIsFile = !aName.IsVoid();
-  }
-
-  virtual bool IsMemoryFile() const override
-  {
-    return false;
-  }
-
-  virtual bool IsDateUnknown() const override
-  {
-    return mIsFile && mLastModificationDate == INT64_MAX;
-  }
-
-  virtual bool IsFile() const override
-  {
-    return mIsFile;
-  }
-
-  virtual bool IsSizeUnknown() const override
-  {
-    return mLength == UINT64_MAX;
-  }
-
-protected:
-  virtual ~BlobImplBase() {}
-
-  /**
-   * Returns a new, effectively-unique serial number. This should be used
-   * by implementations to obtain a serial number for GetSerialNumber().
-   * The implementation is thread safe.
-   */
-  static uint64_t NextSerialNumber();
-
-  bool mIsFile;
-  bool mImmutable;
-
-  nsString mContentType;
-  nsString mName;
-  nsString mPath; // The path relative to a directory chosen by the user
-
-  uint64_t mStart;
-  uint64_t mLength;
-
-  int64_t mLastModificationDate;
-
-  const uint64_t mSerialNumber;
-};
-
-class BlobImplString final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplString>
-  Create(const nsACString& aData, const nsAString& aContentType);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplString(const nsACString& aData, const nsAString& aContentType);
-
-  ~BlobImplString();
-
-  nsCString mData;
-};
-
-/**
- * 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 BlobImplMemory final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
-                 const nsAString& aContentType, int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength,
-                 const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-  class DataOwner final : public mozilla::LinkedListElement<DataOwner>
-  {
-  public:
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
-    DataOwner(void* aMemoryBuffer, uint64_t aLength)
-      : mData(aMemoryBuffer)
-      , mLength(aLength)
-    {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      if (!sDataOwners) {
-        sDataOwners = new mozilla::LinkedList<DataOwner>();
-        EnsureMemoryReporterRegistered();
-      }
-      sDataOwners->insertBack(this);
-    }
-
-  private:
-    // Private destructor, to discourage deletion outside of Release():
-    ~DataOwner() {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      remove();
-      if (sDataOwners->isEmpty()) {
-        // Free the linked list if it's empty.
-        sDataOwners = nullptr;
-      }
-
-      free(mData);
-    }
-
-  public:
-    static void EnsureMemoryReporterRegistered();
-
-    // sDataOwners and sMemoryReporterRegistered may only be accessed while
-    // holding sDataOwnerMutex!  You also must hold the mutex while touching
-    // elements of the linked list that DataOwner inherits from.
-    static mozilla::StaticMutex sDataOwnerMutex;
-    static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
-    static bool sMemoryReporterRegistered;
-
-    void* mData;
-    uint64_t mLength;
-  };
-
-private:
-  // Create slice
-  BlobImplMemory(const BlobImplMemory* aOther, uint64_t aStart,
-                 uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mDataOwner(aOther->mDataOwner)
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-    mImmutable = aOther->mImmutable;
-  }
-
-  ~BlobImplMemory() {}
-
-  // Used when backed by a memory store
-  RefPtr<DataOwner> mDataOwner;
-};
-
-class BlobImplTemporaryBlob final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplTemporaryBlob(PRFileDesc* aFD, uint64_t aStartPos,
-                        uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStartPos)
-  {
-    mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplTemporaryBlob(const BlobImplTemporaryBlob* aOther,
-                        uint64_t aStart, uint64_t aLength,
-                        const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStart)
-    , mFileDescOwner(aOther->mFileDescOwner)
-  {}
-
-  ~BlobImplTemporaryBlob() {}
-
-  uint64_t mStartPos;
-  RefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
-};
-
-class BlobImplFile : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // Create as a file
-  explicit BlobImplFile(nsIFile* aFile)
-    : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    // Lazily get the content type and size
-    mContentType.SetIsVoid(true);
-    mFile->GetLeafName(mName);
-  }
-
-  // Create as a file
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile)
-    : BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile,
-               int64_t aLastModificationDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModificationDate)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  // Create as a file with custom name
-  BlobImplFile(nsIFile* aFile, const nsAString& aName,
-               const nsAString& aContentType)
-    : BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    if (aContentType.IsEmpty()) {
-      // Lazily get the content type and size
-      mContentType.SetIsVoid(true);
-    }
-  }
-
-  // Overrides
-  virtual uint64_t GetSize(ErrorResult& aRv) override;
-  virtual void GetType(nsAString& aType) override;
-  virtual int64_t GetLastModified(ErrorResult& aRv) override;
-  virtual void SetLastModified(int64_t aLastModified) override;
-  virtual void GetMozFullPathInternal(nsAString& aFullPath,
-                                      ErrorResult& aRv) const override;
-  virtual void GetInternalStream(nsIInputStream** aInputStream,
-                                 ErrorResult& aRv) override;
-
-  virtual bool IsDirectory() const override;
-
-  // We always have size and date for this kind of blob.
-  virtual bool IsSizeUnknown() const override { return false; }
-  virtual bool IsDateUnknown() const override { return false; }
-
-protected:
-  virtual ~BlobImplFile() = default;
-
-private:
-  // Create slice
-  BlobImplFile(const BlobImplFile* aOther, uint64_t aStart,
-               uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mFile(aOther->mFile)
-    , mWholeFile(false)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    mImmutable = aOther->mImmutable;
-  }
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  nsCOMPtr<nsIFile> mFile;
-  bool mWholeFile;
-};
-
-class EmptyBlobImpl final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  explicit EmptyBlobImpl(const nsAString& aContentType)
-    : BlobImplBase(aContentType, 0 /* aLength */)
-  {
-    mImmutable = true;
-  }
-
-  EmptyBlobImpl(const nsAString& aName,
-                const nsAString& aContentType,
-                int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, 0, aLastModifiedDate)
-  {
-    mImmutable = true;
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-private:
-  ~EmptyBlobImpl() {}
-};
-
-class BlobImplStream final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aContentType,
-         uint64_t aLength);
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aName,
-         const nsAString& aContentType,
-         int64_t aLastModifiedDate,
-         uint64_t aLength);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-private:
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aContentType,
-                 uint64_t aLength);
-
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aName,
-                 const nsAString& aContentType,
-                 int64_t aLastModifiedDate,
-                 uint64_t aLength);
-
-  BlobImplStream(BlobImplStream* aOther,
-                 const nsAString& aContentType,
-                 uint64_t aStart,
-                 uint64_t aLength);
-
-  ~BlobImplStream();
-
-  void MaybeRegisterMemoryReporter();
-
-  nsCOMPtr<nsIInputStream> mInputStream;
-};
-
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_File_h
+#endif // mozilla_dom_Blob_h
copy from dom/file/File.cpp
copy to dom/file/BlobImpl.cpp
--- a/dom/file/File.cpp
+++ b/dom/file/BlobImpl.cpp
@@ -1,527 +1,21 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/File.h"
-
-#include "ipc/nsIRemoteBlob.h"
-#include "MultipartBlobImpl.h"
-#include "nsCExternalHandlerService.h"
-#include "nsContentCID.h"
-#include "nsContentUtils.h"
-#include "nsError.h"
-#include "nsICharsetDetector.h"
-#include "nsIConverterInputStream.h"
-#include "nsIDocument.h"
-#include "nsIFileStreams.h"
-#include "nsIInputStream.h"
-#include "nsIIPCSerializableInputStream.h"
-#include "nsIMIMEService.h"
-#include "nsISeekableStream.h"
-#include "nsIUnicharInputStream.h"
-#include "nsIUnicodeDecoder.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsIUUIDGenerator.h"
-#include "nsHostObjectProtocolHandler.h"
-#include "nsStringStream.h"
-#include "nsJSUtils.h"
-#include "nsPrintfCString.h"
-#include "mozilla/SHA1.h"
+#include "BlobImpl.h"
+#include "File.h"
 #include "mozilla/CheckedInt.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/dom/BlobBinding.h"
-#include "mozilla/dom/DOMError.h"
-#include "mozilla/dom/FileBinding.h"
-#include "mozilla/dom/FileCreatorHelper.h"
-#include "mozilla/dom/FileSystemUtils.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerRunnable.h"
-#include "nsThreadUtils.h"
-#include "nsStreamUtils.h"
-#include "SlicedInputStream.h"
 
 namespace mozilla {
 namespace dom {
 
-using namespace workers;
-
-// XXXkhuey the input stream that we pass out of a File
-// can outlive the actual File 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 final : public nsIInputStream,
-                               public nsISeekableStream,
-                               public nsIIPCSerializableInputStream
-{
-  typedef BlobImplMemory::DataOwner DataOwner;
-public:
-  static nsresult Create(DataOwner* aDataOwner,
-                         uint32_t aStart,
-                         uint32_t aLength,
-                         nsIInputStream** _retval);
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  // These are mandatory.
-  NS_FORWARD_NSIINPUTSTREAM(mStream->)
-  NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
-
-  // This is optional. We use a conditional QI to keep it from being called
-  // if the underlying stream doesn't support it.
-  NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
-
-private:
-  ~DataOwnerAdapter() {}
-
-  DataOwnerAdapter(DataOwner* aDataOwner,
-                   nsIInputStream* aStream)
-    : mDataOwner(aDataOwner), mStream(aStream),
-      mSeekableStream(do_QueryInterface(aStream)),
-      mSerializableInputStream(do_QueryInterface(aStream))
-  {
-    MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
-  }
-
-  RefPtr<DataOwner> mDataOwner;
-  nsCOMPtr<nsIInputStream> mStream;
-  nsCOMPtr<nsISeekableStream> mSeekableStream;
-  nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
-};
-
-NS_IMPL_ADDREF(DataOwnerAdapter)
-NS_IMPL_RELEASE(DataOwnerAdapter)
-
-NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
-  NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
-                                     mSerializableInputStream)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
-NS_INTERFACE_MAP_END
-
-nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
-                                  uint32_t aStart,
-                                  uint32_t aLength,
-                                  nsIInputStream** _retval)
-{
-  nsresult rv;
-  MOZ_ASSERT(aDataOwner, "Uh ...");
-
-  nsCOMPtr<nsIInputStream> stream;
-
-  rv = NS_NewByteInputStream(getter_AddRefs(stream),
-                             static_cast<const char*>(aDataOwner->mData) +
-                             aStart,
-                             (int32_t)aLength,
-                             NS_ASSIGNMENT_DEPEND);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
-
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::Blob implementation
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
-  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(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
-  // 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, nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
-  NS_INTERFACE_MAP_ENTRY(nsIMutable)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
-
-// A utility function that enforces the spec constraints on the type of a blob:
-// no codepoints outside the ASCII range (otherwise type becomes empty) and
-// lowercase ASCII only.  We can't just use our existing nsContentUtils
-// ASCII-related helpers because we need the "outside ASCII range" check, and we
-// can't use NS_IsAscii because its definition of "ASCII" (chars all <= 0x7E)
-// differs from the file API definition (which excludes control chars).
-static void
-MakeValidBlobType(nsAString& aType)
-{
-  char16_t* iter = aType.BeginWriting();
-  char16_t* end = aType.EndWriting();
-
-  for ( ; iter != end; ++iter) {
-    char16_t c = *iter;
-    if (c < 0x20 || c > 0x7E) {
-      // Non-ASCII char, bail out.
-      aType.Truncate();
-      return;
-    }
-
-    if (c >= 'A' && c <= 'Z') {
-      *iter = c + ('a' - 'A');
-    }
-  }
-}
-
-/* static */ Blob*
-Blob::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-
-  return aImpl->IsFile() ? new File(aParent, aImpl)
-                         : new Blob(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateStringBlob(nsISupports* aParent, const nsACString& aData,
-                       const nsAString& aContentType)
-{
-  RefPtr<BlobImpl> blobImpl = BlobImplString::Create(aData, aContentType);
-  RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
-                          uint64_t aStartPos, uint64_t aLength,
-                          const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplTemporaryBlob(aFD, aStartPos, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-Blob::Blob(nsISupports* aParent, BlobImpl* aImpl)
-  : mImpl(aImpl)
-  , mParent(aParent)
-{
-  MOZ_ASSERT(mImpl);
-
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aParent);
-    if (win) {
-      MOZ_ASSERT(win->IsInnerWindow());
-    }
-  }
-#endif
-}
-
-bool
-Blob::IsFile() const
-{
-  return mImpl->IsFile();
-}
-
-const nsTArray<RefPtr<BlobImpl>>*
-Blob::GetSubBlobImpls() const
-{
-  return mImpl->GetSubBlobImpls();
-}
-
-already_AddRefed<File>
-Blob::ToFile()
-{
-  if (!mImpl->IsFile()) {
-    return nullptr;
-  }
-
-  RefPtr<File> file;
-  if (HasFileInterface()) {
-    file = static_cast<File*>(this);
-  } else {
-    file = new File(mParent, mImpl);
-  }
-
-  return file.forget();
-}
-
-already_AddRefed<File>
-Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const
-{
-  AutoTArray<RefPtr<BlobImpl>, 1> blobImpls({mImpl});
-
-  nsAutoString contentType;
-  mImpl->GetType(contentType);
-
-  RefPtr<MultipartBlobImpl> impl =
-    MultipartBlobImpl::Create(Move(blobImpls), aName, contentType, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  RefPtr<File> file = new File(mParent, impl);
-  return file.forget();
-}
-
-already_AddRefed<Blob>
-Blob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                  const nsAString& aContentType,
-                  ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl = mImpl->CreateSlice(aStart, aLength,
-                                             aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-uint64_t
-Blob::GetSize(ErrorResult& aRv)
-{
-  return mImpl->GetSize(aRv);
-}
-
-void
-Blob::GetType(nsAString &aType)
-{
-  mImpl->GetType(aType);
-}
-
-already_AddRefed<Blob>
-Blob::Slice(const Optional<int64_t>& aStart,
-            const Optional<int64_t>& aEnd,
-            const nsAString& aContentType,
-            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    mImpl->Slice(aStart, aEnd, aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-NS_IMETHODIMP
-Blob::GetSendInfo(nsIInputStream** aBody,
-                  uint64_t* aContentLength,
-                  nsACString& aContentType,
-                  nsACString& aCharset)
-{
-  return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
-}
-
-NS_IMETHODIMP
-Blob::GetMutable(bool* aMutable)
-{
-  return mImpl->GetMutable(aMutable);
-}
-
-NS_IMETHODIMP
-Blob::SetMutable(bool aMutable)
-{
-  return mImpl->SetMutable(aMutable);
-}
-
-JSObject*
-Blob::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return BlobBinding::Wrap(aCx, this, aGivenProto);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::Constructor(const GlobalObject& aGlobal,
-                  const Optional<Sequence<BlobPart>>& aData,
-                  const BlobPropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();
-
-  if (aData.WasPassed()) {
-    nsAutoString type(aBag.mType);
-    MakeValidBlobType(type);
-    impl->InitializeBlob(aGlobal.Context(), aData.Value(), type,
-                         aBag.mEndings == EndingTypes::Native, aRv);
-  } else {
-    impl->InitializeBlob(aRv);
-  }
-
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  MOZ_ASSERT(!impl->IsFile());
-
-  RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
-  return blob.forget();
-}
-
-int64_t
-Blob::GetFileId()
-{
-  return mImpl->GetFileId();
-}
-
-bool
-Blob::IsMemoryFile() const
-{
-  return mImpl->IsMemoryFile();
-}
-
-void
-Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  mImpl->GetInternalStream(aStream, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::File implementation
-
-File::File(nsISupports* aParent, BlobImpl* aImpl)
-  : Blob(aParent, aImpl)
-{
-  MOZ_ASSERT(aImpl->IsFile());
-}
-
-/* static */ File*
-File::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-  MOZ_ASSERT(aImpl->IsFile());
-
-  return new File(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aName,
-             const nsAString& aContentType, uint64_t aLength,
-             int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aName,
-                       aContentType, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile)
-{
-  RefPtr<File> file = new File(aParent, new BlobImplFile(aFile));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                     const nsAString& aName, const nsAString& aContentType)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplFile(aFile, aName, aContentType));
-  return file.forget();
-}
-
-JSObject*
-File::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return FileBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-File::GetName(nsAString& aFileName) const
-{
-  mImpl->GetName(aFileName);
-}
-
-void
-File::GetRelativePath(nsAString& aPath) const
-{
-  aPath.Truncate();
-
-  nsAutoString path;
-  mImpl->GetDOMPath(path);
-
-  // WebkitRelativePath doesn't start with '/'
-  if (!path.IsEmpty()) {
-    MOZ_ASSERT(path[0] == FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
-    aPath.Assign(Substring(path, 1));
-  }
-}
-
-Date
-File::GetLastModifiedDate(ErrorResult& aRv)
-{
-  int64_t value = GetLastModified(aRv);
-  if (aRv.Failed()) {
-    return Date();
-  }
-
-  return Date(JS::TimeClip(value));
-}
-
-int64_t
-File::GetLastModified(ErrorResult& aRv)
-{
-  return mImpl->GetLastModified(aRv);
-}
-
-void
-File::GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPath(aFilename, aGuarantee, aRv);
-}
-
-void
-File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPathInternal(aFileName, aRv);
-}
-
 // 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;
   if (aStart < -aSize) {
     newStartOffset = 0;
@@ -549,84 +43,16 @@ ParseSize(int64_t aSize, int64_t& aStart
     aStart = aEnd = 0;
   }
   else {
     aStart = newStartOffset.value();
     aEnd = newEndOffset.value();
   }
 }
 
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  const Sequence<BlobPart>& aData,
-                  const nsAString& aName,
-                  const FilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  // Normalizing the filename
-  nsString name(aName);
-  name.ReplaceChar('/', ':');
-
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(name);
-
-  nsAutoString type(aBag.mType);
-  MakeValidBlobType(type);
-  impl->InitializeBlob(aGlobal.Context(), aData, type, false, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
-
-  if (aBag.mLastModified.WasPassed()) {
-    impl->SetLastModified(aBag.mLastModified.Value());
-  }
-
-  RefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
-  return file.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromNsIFile(const GlobalObject& aGlobal,
-                        nsIFile* aData,
-                        const ChromeFilePropertyBag& aBag,
-                        SystemCallerGuarantee aGuarantee,
-                        ErrorResult& aRv)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, aData, aBag, true, aRv);
-  return promise.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromFileName(const GlobalObject& aGlobal,
-                         const nsAString& aPath,
-                         const ChromeFilePropertyBag& aBag,
-                         SystemCallerGuarantee aGuarantee,
-                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIFile> file;
-  aRv = NS_NewLocalFile(aPath, false, getter_AddRefs(file));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, file, aBag, false, aRv);
-  return promise.forget();
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::BlobImpl implementation
-
 already_AddRefed<BlobImpl>
 BlobImpl::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);
@@ -635,716 +61,16 @@ BlobImpl::Slice(const Optional<int64_t>&
   }
 
   int64_t start = aStart.WasPassed() ? aStart.Value() : 0;
   int64_t end = aEnd.WasPassed() ? aEnd.Value() : (int64_t)thisLength;
 
   ParseSize((int64_t)thisLength, start, end);
 
   nsAutoString type(aContentType);
-  MakeValidBlobType(type);
+  Blob::MakeValidBlobType(type);
   return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
 }
 
-////////////////////////////////////////////////////////////////////////////
-// BlobImpl implementation
-
 NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
 
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFile, BlobImpl)
-
-void
-BlobImplBase::GetName(nsAString& aName) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aName = mName;
-}
-
-void
-BlobImplBase::GetDOMPath(nsAString& aPath) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aPath = mPath;
-}
-
-void
-BlobImplBase::SetDOMPath(const nsAString& aPath)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  mPath = aPath;
-}
-
-void
-BlobImplBase::GetMozFullPath(nsAString& aFileName,
-                             SystemCallerGuarantee /* unused */,
-                             ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-
-  GetMozFullPathInternal(aFileName, aRv);
-}
-
-void
-BlobImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  if (!mIsFile) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aFileName.Truncate();
-}
-
-void
-BlobImplBase::GetType(nsAString& aType)
-{
-  aType = mContentType;
-}
-
-int64_t
-BlobImplBase::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (IsDateUnknown()) {
-    mLastModificationDate = PR_Now();
-  }
-
-  return mLastModificationDate / PR_USEC_PER_MSEC;
-}
-
-void
-BlobImplBase::SetLastModified(int64_t aLastModified)
-{
-  mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
-}
-
-int64_t
-BlobImplBase::GetFileId()
-{
-  return -1;
-}
-
-nsresult
-BlobImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
-                          nsACString& aContentType, nsACString& aCharset)
-{
-  MOZ_ASSERT(aContentLength);
-
-  ErrorResult rv;
-
-  nsCOMPtr<nsIInputStream> stream;
-  GetInternalStream(getter_AddRefs(stream), rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  *aContentLength = GetSize(rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  nsAutoString contentType;
-  GetType(contentType);
-
-  if (contentType.IsEmpty()) {
-    aContentType.SetIsVoid(true);
-  } else {
-    CopyUTF16toUTF8(contentType, aContentType);
-  }
-
-  aCharset.Truncate();
-
-  stream.forget(aBody);
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::GetMutable(bool* aMutable) const
-{
-  *aMutable = !mImmutable;
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::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);
-
-    ErrorResult error;
-    GetSize(error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-  }
-
-  mImmutable = !aMutable;
-  return rv;
-}
-
-/* static */ uint64_t
-BlobImplBase::NextSerialNumber()
-{
-  static Atomic<uint64_t> nextSerialNumber;
-  return nextSerialNumber++;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-already_AddRefed<BlobImpl>
-BlobImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
-                          const nsAString& aContentType,
-                          ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplFile(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aRv = mFile->GetPath(aFilename);
-}
-
-uint64_t
-BlobImplFile::GetSize(ErrorResult& aRv)
-{
-  if (BlobImplBase::IsSizeUnknown()) {
-    MOZ_ASSERT(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;
-    }
-
-    if (fileSize < 0) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return 0;
-    }
-
-    mLength = fileSize;
-  }
-
-  return mLength;
-}
-
-namespace {
-
-class GetTypeRunnable final : public WorkerMainThreadRunnable
-{
-public:
-  GetTypeRunnable(WorkerPrivate* aWorkerPrivate,
-                  BlobImpl* aBlobImpl)
-    : WorkerMainThreadRunnable(aWorkerPrivate,
-                               NS_LITERAL_CSTRING("BlobImplFile :: GetType"))
-    , mBlobImpl(aBlobImpl)
-  {
-    MOZ_ASSERT(aBlobImpl);
-    aWorkerPrivate->AssertIsOnWorkerThread();
-  }
-
-  bool
-  MainThreadRun() override
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    nsAutoString type;
-    mBlobImpl->GetType(type);
-    return true;
-  }
-
-private:
-  ~GetTypeRunnable()
-  {}
-
-  RefPtr<BlobImpl> mBlobImpl;
-};
-
-} // anonymous namespace
-
-void
-BlobImplFile::GetType(nsAString& aType)
-{
-  aType.Truncate();
-
-  if (mContentType.IsVoid()) {
-    MOZ_ASSERT(mWholeFile,
-               "Should only use lazy ContentType when using the whole file");
-
-    if (!NS_IsMainThread()) {
-      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-      if (!workerPrivate) {
-        // I have no idea in which thread this method is called. We cannot
-        // return any valid value.
-        return;
-      }
-
-      RefPtr<GetTypeRunnable> runnable =
-        new GetTypeRunnable(workerPrivate, this);
-
-      ErrorResult rv;
-      runnable->Dispatch(Terminating, rv);
-      if (NS_WARN_IF(rv.Failed())) {
-        rv.SuppressException();
-      }
-      return;
-    }
-
-    nsresult rv;
-    nsCOMPtr<nsIMIMEService> mimeService =
-      do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-
-    nsAutoCString mimeType;
-    rv = mimeService->GetTypeFromFile(mFile, mimeType);
-    if (NS_FAILED(rv)) {
-      mimeType.Truncate();
-    }
-
-    AppendUTF8toUTF16(mimeType, mContentType);
-    mContentType.SetIsVoid(false);
-  }
-
-  aType = mContentType;
-}
-
-int64_t
-BlobImplFile::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (BlobImplBase::IsDateUnknown()) {
-    PRTime msecs;
-    aRv = mFile->GetLastModifiedTime(&msecs);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return 0;
-    }
-
-    mLastModificationDate = msecs;
-  }
-
-  return mLastModificationDate;
-}
-
-void
-BlobImplFile::SetLastModified(int64_t aLastModified)
-{
-  MOZ_CRASH("SetLastModified of a real file is not allowed!");
-}
-
-const uint32_t sFileStreamFlags =
-  nsIFileInputStream::CLOSE_ON_EOF |
-  nsIFileInputStream::REOPEN_ON_REWIND |
-  nsIFileInputStream::DEFER_OPEN |
-  nsIFileInputStream::SHARE_DELETE;
-
-void
-BlobImplFile::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mWholeFile) {
-    aRv = NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags);
-    return;
-  }
-
-  aRv = NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
-                                          -1, -1, sFileStreamFlags);
-}
-
-bool
-BlobImplFile::IsDirectory() const
-{
-  bool isDirectory = false;
-  if (mFile) {
-    mFile->IsDirectory(&isDirectory);
-  }
-  return isDirectory;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// EmptyBlobImpl implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
-
-already_AddRefed<BlobImpl>
-EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
-                           const nsAString& aContentType,
-                           ErrorResult& aRv)
-{
-  MOZ_ASSERT(!aStart && !aLength);
-  RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-
-  DebugOnly<bool> isMutable;
-  MOZ_ASSERT(NS_SUCCEEDED(impl->GetMutable(&isMutable)));
-  MOZ_ASSERT(!isMutable);
-
-  return impl.forget();
-}
-
-void
-EmptyBlobImpl::GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv)
-{
-  if (NS_WARN_IF(!aStream)) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
-    return;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplString implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplString, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplString>
-BlobImplString::Create(const nsACString& aData, const nsAString& aContentType)
-{
-  RefPtr<BlobImplString> blobImpl = new BlobImplString(aData, aContentType);
-  RegisterWeakMemoryReporter(blobImpl);
-  return blobImpl.forget();
-}
-
-BlobImplString::BlobImplString(const nsACString& aData,
-                               const nsAString& aContentType)
-  : BlobImplBase(aContentType, aData.Length())
-  , mData(aData)
-{
-}
-
-BlobImplString::~BlobImplString()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplString::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplString(Substring(mData, aStart, aLength),
-                       aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplString::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  aRv = NS_NewCStringInputStream(aStream, mData);
-}
-
-NS_IMETHODIMP
-BlobImplString::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/string", KIND_HEAP, UNITS_BYTES,
-    mData.SizeOfExcludingThisIfUnshared(MallocSizeOf),
-    "Memory used to back a File/Blob based on a string.");
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplMemory implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplMemory, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplMemory(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplMemory::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mLength > INT32_MAX) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aRv = DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
-}
-
-/* static */ StaticMutex
-BlobImplMemory::DataOwner::sDataOwnerMutex;
-
-/* static */ StaticAutoPtr<LinkedList<BlobImplMemory::DataOwner>>
-BlobImplMemory::DataOwner::sDataOwners;
-
-/* static */ bool
-BlobImplMemory::DataOwner::sMemoryReporterRegistered = false;
-
-MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
-
-class BlobImplMemoryDataOwnerMemoryReporter final
-  : public nsIMemoryReporter
-{
-  ~BlobImplMemoryDataOwnerMemoryReporter() {}
-
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
-                            nsISupports* aData, bool aAnonymize) override
-  {
-    typedef BlobImplMemory::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);
-
-      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);
-
-        nsAutoCString digestString;
-        for (size_t i = 0; i < sizeof(digest); i++) {
-          digestString.AppendPrintf("%02x", digest[i]);
-        }
-
-        aHandleReport->Callback(
-          /* process */ NS_LITERAL_CSTRING(""),
-          nsPrintfCString(
-            "explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
-            owner->mLength, aAnonymize ? "<anonymized>" : digestString.get()),
-          KIND_HEAP, UNITS_BYTES, size,
-          nsPrintfCString(
-            "Memory used to back a memory file of length %llu bytes.  The file "
-            "has a sha1 of %s.\n\n"
-            "Note that the allocator may round up a memory file's length -- "
-            "that is, an N-byte memory file may take up more than N bytes of "
-            "memory.",
-            owner->mLength, digestString.get()),
-          aData);
-      }
-    }
-
-    if (smallObjectsTotal > 0) {
-      aHandleReport->Callback(
-        /* process */ NS_LITERAL_CSTRING(""),
-        NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
-        KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
-        nsPrintfCString(
-          "Memory used to back small memory files (i.e. those taking up less "
-          "than %zu bytes of memory each).\n\n"
-          "Note that the allocator may round up a memory file's length -- "
-          "that is, an N-byte memory file may take up more than N bytes of "
-          "memory.", LARGE_OBJECT_MIN_SIZE),
-        aData);
-    }
-
-    return NS_OK;
-  }
-};
-
-NS_IMPL_ISUPPORTS(BlobImplMemoryDataOwnerMemoryReporter, nsIMemoryReporter)
-
-/* static */ void
-BlobImplMemory::DataOwner::EnsureMemoryReporterRegistered()
-{
-  sDataOwnerMutex.AssertCurrentThreadOwns();
-  if (sMemoryReporterRegistered) {
-    return;
-  }
-
-  RegisterStrongMemoryReporter(new BlobImplMemoryDataOwnerMemoryReporter());
-
-  sMemoryReporterRegistered = true;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplTemporaryBlob implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplTemporaryBlob, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplTemporaryBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                                   const nsAString& aContentType,
-                                   ErrorResult& aRv)
-{
-  if (aStart + aLength > mLength) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplTemporaryBlob(this, aStart + mStartPos,
-                              aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplTemporaryBlob::GetInternalStream(nsIInputStream** aStream,
-                                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> stream =
-    new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength);
-  stream.forget(aStream);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplStream implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplStream, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aContentType,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aContentType, aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aName, aContentType, aLastModifiedDate,
-                       aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aContentType,
-                               uint64_t aLength)
-  : BlobImplBase(aContentType, aLength)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(BlobImplStream* aOther,
-                               const nsAString& aContentType,
-                               uint64_t aStart, uint64_t aLength)
-  : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-  , mInputStream(new SlicedInputStream(aOther->mInputStream, aStart, aLength))
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aName,
-                               const nsAString& aContentType,
-                               int64_t aLastModifiedDate,
-                               uint64_t aLength)
-  : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::~BlobImplStream()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-void
-BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> clonedStream;
-  nsCOMPtr<nsIInputStream> replacementStream;
-
-  aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
-                            getter_AddRefs(replacementStream));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  if (replacementStream) {
-    mInputStream = replacementStream.forget();
-  }
-
-  clonedStream.forget(aStream);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplStream::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType, ErrorResult& aRv)
-{
-  if (!aLength) {
-    RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-    return impl.forget();
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplStream(this, aContentType, aStart, aLength);
-  return impl.forget();
-}
-
-void
-BlobImplStream::MaybeRegisterMemoryReporter()
-{
-  // We report only stringInputStream.
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return;
-  }
-
-  RegisterWeakMemoryReporter(this);
-}
-
-NS_IMETHODIMP
-BlobImplStream::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return NS_OK;
-  }
-
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
-    stringInputStream->SizeOfIncludingThis(MallocSizeOf),
-    "Memory used to back a File/Blob based on an input stream.");
-
-  return NS_OK;
-}
-
 } // namespace dom
 } // namespace mozilla
copy from dom/file/File.h
copy to dom/file/BlobImpl.h
--- a/dom/file/File.h
+++ b/dom/file/BlobImpl.h
@@ -1,253 +1,31 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_dom_File_h
-#define mozilla_dom_File_h
+#ifndef mozilla_dom_BlobImpl_h
+#define mozilla_dom_BlobImpl_h
 
-#include "mozilla/Attributes.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/GuardObjects.h"
-#include "mozilla/LinkedList.h"
-#include "mozilla/StaticMutex.h"
-#include "mozilla/StaticPtr.h"
 #include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/Date.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMBlob.h"
-#include "nsIFile.h"
-#include "nsIMemoryReporter.h"
-#include "nsIMutable.h"
-#include "nsIXMLHttpRequest.h"
+#include "mozilla/ErrorResult.h"
+#include "nsISupportsImpl.h"
 #include "nsString.h"
-#include "nsTemporaryFileInputStream.h"
-#include "nsWrapperCache.h"
-#include "nsWeakReference.h"
-
-class nsIFile;
-class nsIInputStream;
 
 #define BLOBIMPL_IID \
   { 0xbccb3275, 0x6778, 0x4ac5, \
     { 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
 
+class nsIInputStream;
+
 namespace mozilla {
 namespace dom {
 
-struct BlobPropertyBag;
-struct ChromeFilePropertyBag;
-struct FilePropertyBag;
-class BlobImpl;
-class File;
-class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
-class Promise;
-
-class Blob : public nsIDOMBlob
-           , public nsIXHRSendable
-           , public nsIMutable
-           , public nsSupportsWeakReference
-           , public nsWrapperCache
-{
-public:
-  NS_DECL_NSIDOMBLOB
-  NS_DECL_NSIXHRSENDABLE
-  NS_DECL_NSIMUTABLE
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
-
-  typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
-
-  // This creates a Blob or a File based on the type of BlobImpl.
-  static Blob*
-  Create(nsISupports* aParent, BlobImpl* aImpl);
-
-  static already_AddRefed<Blob>
-  CreateStringBlob(nsISupports* aParent, const nsACString& aData,
-                   const nsAString& aContentType);
-
-  // The returned Blob takes ownership of aMemoryBuffer. aMemoryBuffer will be
-  // freed by free so it must be allocated by malloc or something
-  // compatible with it.
-  static already_AddRefed<Blob>
-  CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
-                   const nsAString& aContentType);
-
-  static already_AddRefed<Blob>
-  CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
-                      uint64_t aStartPos, uint64_t aLength,
-                      const nsAString& aContentType);
-
-  BlobImpl* Impl() const
-  {
-    return mImpl;
-  }
-
-  bool IsFile() const;
-
-  const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const;
-
-  // This method returns null if this Blob is not a File; it returns
-  // the same object in case this Blob already implements the File interface;
-  // otherwise it returns a new File object with the same BlobImpl.
-  already_AddRefed<File> ToFile();
-
-  // This method creates a new File object with the given name and the same
-  // BlobImpl.
-  already_AddRefed<File> ToFile(const nsAString& aName,
-                                ErrorResult& aRv) const;
-
-  already_AddRefed<Blob>
-  CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
-              ErrorResult& aRv);
-
-  void
-  GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv);
-
-  int64_t
-  GetFileId();
-
-  // WebIDL methods
-  nsISupports* GetParentObject() const
-  {
-    return mParent;
-  }
-
-  bool
-  IsMemoryFile() const;
-
-  // Blob constructor
-  static already_AddRefed<Blob>
-  Constructor(const GlobalObject& aGlobal,
-              const Optional<Sequence<BlobPart>>& aData,
-              const BlobPropertyBag& aBag,
-              ErrorResult& aRv);
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  uint64_t GetSize(ErrorResult& aRv);
-
-  void GetType(nsAString& aType);
-
-  already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
-                               const Optional<int64_t>& aEnd,
-                               const nsAString& aContentType,
-                               ErrorResult& aRv);
-
-protected:
-  // File constructor should never be used directly. Use Blob::Create instead.
-  Blob(nsISupports* aParent, BlobImpl* aImpl);
-  virtual ~Blob() {};
-
-  virtual bool HasFileInterface() const { return false; }
-
-  // The member is the real backend implementation of this File/Blob.
-  // 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!
-  RefPtr<BlobImpl> mImpl;
-
-private:
-  nsCOMPtr<nsISupports> mParent;
-};
-
-class File final : public Blob
-{
-  friend class Blob;
-
-public:
-  // Note: BlobImpl must be a File in order to use this method.
-  // Check impl->IsFile().
-  static File*
-  Create(nsISupports* aParent, BlobImpl* aImpl);
-
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aName,
-         const nsAString& aContentType, uint64_t aLength,
-         int64_t aLastModifiedDate);
-
-  // The returned File takes ownership of aMemoryBuffer. aMemoryBuffer will be
-  // freed by free so it must be allocated by malloc or something
-  // compatible with it.
-  static already_AddRefed<File>
-  CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
-                   const nsAString& aName, const nsAString& aContentType,
-                   int64_t aLastModifiedDate);
-
-  // This method creates a BlobFileImpl for the new File object. This is
-  // thread-safe, cross-process, cross-thread as any other BlobImpl, but, when
-  // GetType() is called, it must dispatch a runnable to the main-thread in
-  // order to use nsIMIMEService.
-  // Would be nice if we try to avoid to use this method outside the
-  // main-thread to avoid extra runnables.
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile);
-
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile, const nsAString& aName,
-                 const nsAString& aContentType);
-
-  // WebIDL methods
-
-  virtual JSObject* WrapObject(JSContext *cx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  // File constructor
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const Sequence<BlobPart>& aData,
-              const nsAString& aName,
-              const FilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromFileName(const GlobalObject& aGlobal,
-                     const nsAString& aFilePath,
-                     const ChromeFilePropertyBag& aBag,
-                     SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromNsIFile(const GlobalObject& aGlobal,
-                    nsIFile* aFile,
-                    const ChromeFilePropertyBag& aBag,
-                    SystemCallerGuarantee aGuarantee,
-                    ErrorResult& aRv);
-
-  void GetName(nsAString& aName) const;
-
-  int64_t GetLastModified(ErrorResult& aRv);
-
-  Date GetLastModifiedDate(ErrorResult& aRv);
-
-  void GetRelativePath(nsAString& aPath) const;
-
-  void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                      ErrorResult& aRv) const;
-
-  void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv) const;
-
-protected:
-  virtual bool HasFileInterface() const override { return true; }
-
-private:
-  // File constructor should never be used directly. Use Blob::Create or
-  // File::Create.
-  File(nsISupports* aParent, BlobImpl* aImpl);
-  ~File() {};
-};
-
 // This is the abstract class for any File backend. It must be nsISupports
 // because this class must be ref-counted and it has to work with IPC.
 class BlobImpl : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(BLOBIMPL_IID)
   NS_DECL_THREADSAFE_ISUPPORTS
 
@@ -333,527 +111,12 @@ public:
   }
 
 protected:
   virtual ~BlobImpl() {}
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(BlobImpl, BLOBIMPL_IID)
 
-class BlobImplBase : public BlobImpl
-{
-public:
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, int64_t aLastModifiedDate)
-    : mIsFile(true)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mName(aName)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(aLastModifiedDate)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength)
-    : mIsFile(true)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mName(aName)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aContentType, uint64_t aLength)
-    : mIsFile(false)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aContentType, uint64_t aStart,
-               uint64_t aLength)
-    : mIsFile(false)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mStart(aStart)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  virtual void GetName(nsAString& aName) const override;
-
-  virtual void GetDOMPath(nsAString& aName) const override;
-
-  virtual void SetDOMPath(const nsAString& aName) override;
-
-  virtual int64_t GetLastModified(ErrorResult& aRv) override;
-
-  virtual void SetLastModified(int64_t aLastModified) override;
-
-  virtual void GetMozFullPath(nsAString& aName,
-                              SystemCallerGuarantee /* unused */,
-                              ErrorResult& aRv) const override;
-
-  virtual void GetMozFullPathInternal(nsAString& aFileName,
-                                      ErrorResult& aRv) const override;
-
-  virtual uint64_t GetSize(ErrorResult& aRv) override
-  {
-    return mLength;
-  }
-
-  virtual void GetType(nsAString& aType) override;
-
-  virtual uint64_t GetSerialNumber() const override { return mSerialNumber; }
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override
-  {
-    return nullptr;
-  }
-
-  virtual const nsTArray<RefPtr<BlobImpl>>*
-  GetSubBlobImpls() const override
-  {
-    return nullptr;
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override
-  {
-    aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-  }
-
-  virtual int64_t GetFileId() override;
-
-  virtual nsresult GetSendInfo(nsIInputStream** aBody,
-                               uint64_t* aContentLength,
-                               nsACString& aContentType,
-                               nsACString& aCharset) override;
-
-  virtual nsresult GetMutable(bool* aMutable) const override;
-
-  virtual nsresult SetMutable(bool aMutable) override;
-
-  virtual void
-  SetLazyData(const nsAString& aName, const nsAString& aContentType,
-              uint64_t aLength, int64_t aLastModifiedDate) override
-  {
-    mName = aName;
-    mContentType = aContentType;
-    mLength = aLength;
-    mLastModificationDate = aLastModifiedDate;
-    mIsFile = !aName.IsVoid();
-  }
-
-  virtual bool IsMemoryFile() const override
-  {
-    return false;
-  }
-
-  virtual bool IsDateUnknown() const override
-  {
-    return mIsFile && mLastModificationDate == INT64_MAX;
-  }
-
-  virtual bool IsFile() const override
-  {
-    return mIsFile;
-  }
-
-  virtual bool IsSizeUnknown() const override
-  {
-    return mLength == UINT64_MAX;
-  }
-
-protected:
-  virtual ~BlobImplBase() {}
-
-  /**
-   * Returns a new, effectively-unique serial number. This should be used
-   * by implementations to obtain a serial number for GetSerialNumber().
-   * The implementation is thread safe.
-   */
-  static uint64_t NextSerialNumber();
-
-  bool mIsFile;
-  bool mImmutable;
-
-  nsString mContentType;
-  nsString mName;
-  nsString mPath; // The path relative to a directory chosen by the user
-
-  uint64_t mStart;
-  uint64_t mLength;
-
-  int64_t mLastModificationDate;
-
-  const uint64_t mSerialNumber;
-};
-
-class BlobImplString final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplString>
-  Create(const nsACString& aData, const nsAString& aContentType);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplString(const nsACString& aData, const nsAString& aContentType);
-
-  ~BlobImplString();
-
-  nsCString mData;
-};
-
-/**
- * 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 BlobImplMemory final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
-                 const nsAString& aContentType, int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength,
-                 const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-  class DataOwner final : public mozilla::LinkedListElement<DataOwner>
-  {
-  public:
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
-    DataOwner(void* aMemoryBuffer, uint64_t aLength)
-      : mData(aMemoryBuffer)
-      , mLength(aLength)
-    {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      if (!sDataOwners) {
-        sDataOwners = new mozilla::LinkedList<DataOwner>();
-        EnsureMemoryReporterRegistered();
-      }
-      sDataOwners->insertBack(this);
-    }
-
-  private:
-    // Private destructor, to discourage deletion outside of Release():
-    ~DataOwner() {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      remove();
-      if (sDataOwners->isEmpty()) {
-        // Free the linked list if it's empty.
-        sDataOwners = nullptr;
-      }
-
-      free(mData);
-    }
-
-  public:
-    static void EnsureMemoryReporterRegistered();
-
-    // sDataOwners and sMemoryReporterRegistered may only be accessed while
-    // holding sDataOwnerMutex!  You also must hold the mutex while touching
-    // elements of the linked list that DataOwner inherits from.
-    static mozilla::StaticMutex sDataOwnerMutex;
-    static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
-    static bool sMemoryReporterRegistered;
-
-    void* mData;
-    uint64_t mLength;
-  };
-
-private:
-  // Create slice
-  BlobImplMemory(const BlobImplMemory* aOther, uint64_t aStart,
-                 uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mDataOwner(aOther->mDataOwner)
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-    mImmutable = aOther->mImmutable;
-  }
-
-  ~BlobImplMemory() {}
-
-  // Used when backed by a memory store
-  RefPtr<DataOwner> mDataOwner;
-};
-
-class BlobImplTemporaryBlob final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplTemporaryBlob(PRFileDesc* aFD, uint64_t aStartPos,
-                        uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStartPos)
-  {
-    mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplTemporaryBlob(const BlobImplTemporaryBlob* aOther,
-                        uint64_t aStart, uint64_t aLength,
-                        const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStart)
-    , mFileDescOwner(aOther->mFileDescOwner)
-  {}
-
-  ~BlobImplTemporaryBlob() {}
-
-  uint64_t mStartPos;
-  RefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
-};
-
-class BlobImplFile : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // Create as a file
-  explicit BlobImplFile(nsIFile* aFile)
-    : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    // Lazily get the content type and size
-    mContentType.SetIsVoid(true);
-    mFile->GetLeafName(mName);
-  }
-
-  // Create as a file
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile)
-    : BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile,
-               int64_t aLastModificationDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModificationDate)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  // Create as a file with custom name
-  BlobImplFile(nsIFile* aFile, const nsAString& aName,
-               const nsAString& aContentType)
-    : BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    if (aContentType.IsEmpty()) {
-      // Lazily get the content type and size
-      mContentType.SetIsVoid(true);
-    }
-  }
-
-  // Overrides
-  virtual uint64_t GetSize(ErrorResult& aRv) override;
-  virtual void GetType(nsAString& aType) override;
-  virtual int64_t GetLastModified(ErrorResult& aRv) override;
-  virtual void SetLastModified(int64_t aLastModified) override;
-  virtual void GetMozFullPathInternal(nsAString& aFullPath,
-                                      ErrorResult& aRv) const override;
-  virtual void GetInternalStream(nsIInputStream** aInputStream,
-                                 ErrorResult& aRv) override;
-
-  virtual bool IsDirectory() const override;
-
-  // We always have size and date for this kind of blob.
-  virtual bool IsSizeUnknown() const override { return false; }
-  virtual bool IsDateUnknown() const override { return false; }
-
-protected:
-  virtual ~BlobImplFile() = default;
-
-private:
-  // Create slice
-  BlobImplFile(const BlobImplFile* aOther, uint64_t aStart,
-               uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mFile(aOther->mFile)
-    , mWholeFile(false)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    mImmutable = aOther->mImmutable;
-  }
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  nsCOMPtr<nsIFile> mFile;
-  bool mWholeFile;
-};
-
-class EmptyBlobImpl final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  explicit EmptyBlobImpl(const nsAString& aContentType)
-    : BlobImplBase(aContentType, 0 /* aLength */)
-  {
-    mImmutable = true;
-  }
-
-  EmptyBlobImpl(const nsAString& aName,
-                const nsAString& aContentType,
-                int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, 0, aLastModifiedDate)
-  {
-    mImmutable = true;
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-private:
-  ~EmptyBlobImpl() {}
-};
-
-class BlobImplStream final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aContentType,
-         uint64_t aLength);
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aName,
-         const nsAString& aContentType,
-         int64_t aLastModifiedDate,
-         uint64_t aLength);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-private:
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aContentType,
-                 uint64_t aLength);
-
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aName,
-                 const nsAString& aContentType,
-                 int64_t aLastModifiedDate,
-                 uint64_t aLength);
-
-  BlobImplStream(BlobImplStream* aOther,
-                 const nsAString& aContentType,
-                 uint64_t aStart,
-                 uint64_t aLength);
-
-  ~BlobImplStream();
-
-  void MaybeRegisterMemoryReporter();
-
-  nsCOMPtr<nsIInputStream> mInputStream;
-};
-
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_File_h
+#endif // mozilla_dom_BlobImpl_h
--- a/dom/file/BlobSet.cpp
+++ b/dom/file/BlobSet.cpp
@@ -2,16 +2,17 @@
 /* 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/BlobSet.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/File.h"
+#include "MemoryBlobImpl.h"
 #include "MultipartBlobImpl.h"
 
 namespace mozilla {
 namespace dom {
 
 nsresult
 BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
 {
@@ -22,17 +23,17 @@ BlobSet::AppendVoidPtr(const void* aData
 
   void* data = malloc(aLength);
   if (!data) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   memcpy((char*)data, aData, aLength);
 
-  RefPtr<BlobImpl> blobImpl = new BlobImplMemory(data, aLength, EmptyString());
+  RefPtr<BlobImpl> blobImpl = new MemoryBlobImpl(data, aLength, EmptyString());
   mBlobImpls.AppendElement(blobImpl);
 
   return NS_OK;
 }
 
 nsresult
 BlobSet::AppendString(const nsAString& aString, bool nativeEOL, JSContext* aCx)
 {
copy from dom/file/File.cpp
copy to dom/file/EmptyBlobImpl.cpp
--- a/dom/file/File.cpp
+++ b/dom/file/EmptyBlobImpl.cpp
@@ -1,985 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/File.h"
-
-#include "ipc/nsIRemoteBlob.h"
-#include "MultipartBlobImpl.h"
-#include "nsCExternalHandlerService.h"
-#include "nsContentCID.h"
-#include "nsContentUtils.h"
-#include "nsError.h"
-#include "nsICharsetDetector.h"
-#include "nsIConverterInputStream.h"
-#include "nsIDocument.h"
-#include "nsIFileStreams.h"
-#include "nsIInputStream.h"
-#include "nsIIPCSerializableInputStream.h"
-#include "nsIMIMEService.h"
-#include "nsISeekableStream.h"
-#include "nsIUnicharInputStream.h"
-#include "nsIUnicodeDecoder.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsIUUIDGenerator.h"
-#include "nsHostObjectProtocolHandler.h"
+#include "EmptyBlobImpl.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/DOMError.h"
-#include "mozilla/dom/FileBinding.h"
-#include "mozilla/dom/FileCreatorHelper.h"
-#include "mozilla/dom/FileSystemUtils.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerRunnable.h"
-#include "nsThreadUtils.h"
-#include "nsStreamUtils.h"
-#include "SlicedInputStream.h"
 
 namespace mozilla {
 namespace dom {
 
-using namespace workers;
-
-// XXXkhuey the input stream that we pass out of a File
-// can outlive the actual File 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 final : public nsIInputStream,
-                               public nsISeekableStream,
-                               public nsIIPCSerializableInputStream
-{
-  typedef BlobImplMemory::DataOwner DataOwner;
-public:
-  static nsresult Create(DataOwner* aDataOwner,
-                         uint32_t aStart,
-                         uint32_t aLength,
-                         nsIInputStream** _retval);
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  // These are mandatory.
-  NS_FORWARD_NSIINPUTSTREAM(mStream->)
-  NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
-
-  // This is optional. We use a conditional QI to keep it from being called
-  // if the underlying stream doesn't support it.
-  NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
-
-private:
-  ~DataOwnerAdapter() {}
-
-  DataOwnerAdapter(DataOwner* aDataOwner,
-                   nsIInputStream* aStream)
-    : mDataOwner(aDataOwner), mStream(aStream),
-      mSeekableStream(do_QueryInterface(aStream)),
-      mSerializableInputStream(do_QueryInterface(aStream))
-  {
-    MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
-  }
-
-  RefPtr<DataOwner> mDataOwner;
-  nsCOMPtr<nsIInputStream> mStream;
-  nsCOMPtr<nsISeekableStream> mSeekableStream;
-  nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
-};
-
-NS_IMPL_ADDREF(DataOwnerAdapter)
-NS_IMPL_RELEASE(DataOwnerAdapter)
-
-NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
-  NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
-                                     mSerializableInputStream)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
-NS_INTERFACE_MAP_END
-
-nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
-                                  uint32_t aStart,
-                                  uint32_t aLength,
-                                  nsIInputStream** _retval)
-{
-  nsresult rv;
-  MOZ_ASSERT(aDataOwner, "Uh ...");
-
-  nsCOMPtr<nsIInputStream> stream;
-
-  rv = NS_NewByteInputStream(getter_AddRefs(stream),
-                             static_cast<const char*>(aDataOwner->mData) +
-                             aStart,
-                             (int32_t)aLength,
-                             NS_ASSIGNMENT_DEPEND);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
-
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::Blob implementation
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
-  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(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
-  // 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, nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
-  NS_INTERFACE_MAP_ENTRY(nsIMutable)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
-
-// A utility function that enforces the spec constraints on the type of a blob:
-// no codepoints outside the ASCII range (otherwise type becomes empty) and
-// lowercase ASCII only.  We can't just use our existing nsContentUtils
-// ASCII-related helpers because we need the "outside ASCII range" check, and we
-// can't use NS_IsAscii because its definition of "ASCII" (chars all <= 0x7E)
-// differs from the file API definition (which excludes control chars).
-static void
-MakeValidBlobType(nsAString& aType)
-{
-  char16_t* iter = aType.BeginWriting();
-  char16_t* end = aType.EndWriting();
-
-  for ( ; iter != end; ++iter) {
-    char16_t c = *iter;
-    if (c < 0x20 || c > 0x7E) {
-      // Non-ASCII char, bail out.
-      aType.Truncate();
-      return;
-    }
-
-    if (c >= 'A' && c <= 'Z') {
-      *iter = c + ('a' - 'A');
-    }
-  }
-}
-
-/* static */ Blob*
-Blob::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-
-  return aImpl->IsFile() ? new File(aParent, aImpl)
-                         : new Blob(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateStringBlob(nsISupports* aParent, const nsACString& aData,
-                       const nsAString& aContentType)
-{
-  RefPtr<BlobImpl> blobImpl = BlobImplString::Create(aData, aContentType);
-  RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
-                          uint64_t aStartPos, uint64_t aLength,
-                          const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplTemporaryBlob(aFD, aStartPos, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-Blob::Blob(nsISupports* aParent, BlobImpl* aImpl)
-  : mImpl(aImpl)
-  , mParent(aParent)
-{
-  MOZ_ASSERT(mImpl);
-
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aParent);
-    if (win) {
-      MOZ_ASSERT(win->IsInnerWindow());
-    }
-  }
-#endif
-}
-
-bool
-Blob::IsFile() const
-{
-  return mImpl->IsFile();
-}
-
-const nsTArray<RefPtr<BlobImpl>>*
-Blob::GetSubBlobImpls() const
-{
-  return mImpl->GetSubBlobImpls();
-}
-
-already_AddRefed<File>
-Blob::ToFile()
-{
-  if (!mImpl->IsFile()) {
-    return nullptr;
-  }
-
-  RefPtr<File> file;
-  if (HasFileInterface()) {
-    file = static_cast<File*>(this);
-  } else {
-    file = new File(mParent, mImpl);
-  }
-
-  return file.forget();
-}
-
-already_AddRefed<File>
-Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const
-{
-  AutoTArray<RefPtr<BlobImpl>, 1> blobImpls({mImpl});
-
-  nsAutoString contentType;
-  mImpl->GetType(contentType);
-
-  RefPtr<MultipartBlobImpl> impl =
-    MultipartBlobImpl::Create(Move(blobImpls), aName, contentType, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  RefPtr<File> file = new File(mParent, impl);
-  return file.forget();
-}
-
-already_AddRefed<Blob>
-Blob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                  const nsAString& aContentType,
-                  ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl = mImpl->CreateSlice(aStart, aLength,
-                                             aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-uint64_t
-Blob::GetSize(ErrorResult& aRv)
-{
-  return mImpl->GetSize(aRv);
-}
-
-void
-Blob::GetType(nsAString &aType)
-{
-  mImpl->GetType(aType);
-}
-
-already_AddRefed<Blob>
-Blob::Slice(const Optional<int64_t>& aStart,
-            const Optional<int64_t>& aEnd,
-            const nsAString& aContentType,
-            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    mImpl->Slice(aStart, aEnd, aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-NS_IMETHODIMP
-Blob::GetSendInfo(nsIInputStream** aBody,
-                  uint64_t* aContentLength,
-                  nsACString& aContentType,
-                  nsACString& aCharset)
-{
-  return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
-}
-
-NS_IMETHODIMP
-Blob::GetMutable(bool* aMutable)
-{
-  return mImpl->GetMutable(aMutable);
-}
-
-NS_IMETHODIMP
-Blob::SetMutable(bool aMutable)
-{
-  return mImpl->SetMutable(aMutable);
-}
-
-JSObject*
-Blob::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return BlobBinding::Wrap(aCx, this, aGivenProto);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::Constructor(const GlobalObject& aGlobal,
-                  const Optional<Sequence<BlobPart>>& aData,
-                  const BlobPropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();
-
-  if (aData.WasPassed()) {
-    nsAutoString type(aBag.mType);
-    MakeValidBlobType(type);
-    impl->InitializeBlob(aGlobal.Context(), aData.Value(), type,
-                         aBag.mEndings == EndingTypes::Native, aRv);
-  } else {
-    impl->InitializeBlob(aRv);
-  }
-
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  MOZ_ASSERT(!impl->IsFile());
-
-  RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
-  return blob.forget();
-}
-
-int64_t
-Blob::GetFileId()
-{
-  return mImpl->GetFileId();
-}
-
-bool
-Blob::IsMemoryFile() const
-{
-  return mImpl->IsMemoryFile();
-}
-
-void
-Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  mImpl->GetInternalStream(aStream, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::File implementation
-
-File::File(nsISupports* aParent, BlobImpl* aImpl)
-  : Blob(aParent, aImpl)
-{
-  MOZ_ASSERT(aImpl->IsFile());
-}
-
-/* static */ File*
-File::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-  MOZ_ASSERT(aImpl->IsFile());
-
-  return new File(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<File>
-File::Create(nsISupports* aParent, const nsAString& aName,
-             const nsAString& aContentType, uint64_t aLength,
-             int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aName,
-                       aContentType, aLastModifiedDate));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile)
-{
-  RefPtr<File> file = new File(aParent, new BlobImplFile(aFile));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                     const nsAString& aName, const nsAString& aContentType)
-{
-  RefPtr<File> file = new File(aParent,
-    new BlobImplFile(aFile, aName, aContentType));
-  return file.forget();
-}
-
-JSObject*
-File::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return FileBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-File::GetName(nsAString& aFileName) const
-{
-  mImpl->GetName(aFileName);
-}
-
-void
-File::GetRelativePath(nsAString& aPath) const
-{
-  aPath.Truncate();
-
-  nsAutoString path;
-  mImpl->GetDOMPath(path);
-
-  // WebkitRelativePath doesn't start with '/'
-  if (!path.IsEmpty()) {
-    MOZ_ASSERT(path[0] == FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
-    aPath.Assign(Substring(path, 1));
-  }
-}
-
-Date
-File::GetLastModifiedDate(ErrorResult& aRv)
-{
-  int64_t value = GetLastModified(aRv);
-  if (aRv.Failed()) {
-    return Date();
-  }
-
-  return Date(JS::TimeClip(value));
-}
-
-int64_t
-File::GetLastModified(ErrorResult& aRv)
-{
-  return mImpl->GetLastModified(aRv);
-}
-
-void
-File::GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPath(aFilename, aGuarantee, aRv);
-}
-
-void
-File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  mImpl->GetMozFullPathInternal(aFileName, aRv);
-}
-
-// 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;
-  if (aStart < -aSize) {
-    newStartOffset = 0;
-  }
-  else if (aStart < 0) {
-    newStartOffset += aSize;
-  }
-  else if (aStart > aSize) {
-    newStartOffset = aSize;
-  }
-
-  CheckedInt64 newEndOffset = aEnd;
-  if (aEnd < -aSize) {
-    newEndOffset = 0;
-  }
-  else if (aEnd < 0) {
-    newEndOffset += aSize;
-  }
-  else if (aEnd > aSize) {
-    newEndOffset = aSize;
-  }
-
-  if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
-      newStartOffset.value() >= newEndOffset.value()) {
-    aStart = aEnd = 0;
-  }
-  else {
-    aStart = newStartOffset.value();
-    aEnd = newEndOffset.value();
-  }
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  const Sequence<BlobPart>& aData,
-                  const nsAString& aName,
-                  const FilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  // Normalizing the filename
-  nsString name(aName);
-  name.ReplaceChar('/', ':');
-
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(name);
-
-  nsAutoString type(aBag.mType);
-  MakeValidBlobType(type);
-  impl->InitializeBlob(aGlobal.Context(), aData, type, false, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
-
-  if (aBag.mLastModified.WasPassed()) {
-    impl->SetLastModified(aBag.mLastModified.Value());
-  }
-
-  RefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
-  return file.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromNsIFile(const GlobalObject& aGlobal,
-                        nsIFile* aData,
-                        const ChromeFilePropertyBag& aBag,
-                        SystemCallerGuarantee aGuarantee,
-                        ErrorResult& aRv)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, aData, aBag, true, aRv);
-  return promise.forget();
-}
-
-/* static */ already_AddRefed<Promise>
-File::CreateFromFileName(const GlobalObject& aGlobal,
-                         const nsAString& aPath,
-                         const ChromeFilePropertyBag& aBag,
-                         SystemCallerGuarantee aGuarantee,
-                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIFile> file;
-  aRv = NS_NewLocalFile(aPath, false, getter_AddRefs(file));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
-  RefPtr<Promise> promise =
-    FileCreatorHelper::CreateFile(global, file, aBag, false, aRv);
-  return promise.forget();
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::BlobImpl implementation
-
-already_AddRefed<BlobImpl>
-BlobImpl::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);
-
-  nsAutoString type(aContentType);
-  MakeValidBlobType(type);
-  return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImpl implementation
-
-NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFile, BlobImpl)
-
-void
-BlobImplBase::GetName(nsAString& aName) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aName = mName;
-}
-
-void
-BlobImplBase::GetDOMPath(nsAString& aPath) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aPath = mPath;
-}
-
-void
-BlobImplBase::SetDOMPath(const nsAString& aPath)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  mPath = aPath;
-}
-
-void
-BlobImplBase::GetMozFullPath(nsAString& aFileName,
-                             SystemCallerGuarantee /* unused */,
-                             ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-
-  GetMozFullPathInternal(aFileName, aRv);
-}
-
-void
-BlobImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  if (!mIsFile) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aFileName.Truncate();
-}
-
-void
-BlobImplBase::GetType(nsAString& aType)
-{
-  aType = mContentType;
-}
-
-int64_t
-BlobImplBase::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (IsDateUnknown()) {
-    mLastModificationDate = PR_Now();
-  }
-
-  return mLastModificationDate / PR_USEC_PER_MSEC;
-}
-
-void
-BlobImplBase::SetLastModified(int64_t aLastModified)
-{
-  mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
-}
-
-int64_t
-BlobImplBase::GetFileId()
-{
-  return -1;
-}
-
-nsresult
-BlobImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
-                          nsACString& aContentType, nsACString& aCharset)
-{
-  MOZ_ASSERT(aContentLength);
-
-  ErrorResult rv;
-
-  nsCOMPtr<nsIInputStream> stream;
-  GetInternalStream(getter_AddRefs(stream), rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  *aContentLength = GetSize(rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  nsAutoString contentType;
-  GetType(contentType);
-
-  if (contentType.IsEmpty()) {
-    aContentType.SetIsVoid(true);
-  } else {
-    CopyUTF16toUTF8(contentType, aContentType);
-  }
-
-  aCharset.Truncate();
-
-  stream.forget(aBody);
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::GetMutable(bool* aMutable) const
-{
-  *aMutable = !mImmutable;
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::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);
-
-    ErrorResult error;
-    GetSize(error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-  }
-
-  mImmutable = !aMutable;
-  return rv;
-}
-
-/* static */ uint64_t
-BlobImplBase::NextSerialNumber()
-{
-  static Atomic<uint64_t> nextSerialNumber;
-  return nextSerialNumber++;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-already_AddRefed<BlobImpl>
-BlobImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
-                          const nsAString& aContentType,
-                          ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplFile(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aRv = mFile->GetPath(aFilename);
-}
-
-uint64_t
-BlobImplFile::GetSize(ErrorResult& aRv)
-{
-  if (BlobImplBase::IsSizeUnknown()) {
-    MOZ_ASSERT(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;
-    }
-
-    if (fileSize < 0) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return 0;
-    }
-
-    mLength = fileSize;
-  }
-
-  return mLength;
-}
-
-namespace {
-
-class GetTypeRunnable final : public WorkerMainThreadRunnable
-{
-public:
-  GetTypeRunnable(WorkerPrivate* aWorkerPrivate,
-                  BlobImpl* aBlobImpl)
-    : WorkerMainThreadRunnable(aWorkerPrivate,
-                               NS_LITERAL_CSTRING("BlobImplFile :: GetType"))
-    , mBlobImpl(aBlobImpl)
-  {
-    MOZ_ASSERT(aBlobImpl);
-    aWorkerPrivate->AssertIsOnWorkerThread();
-  }
-
-  bool
-  MainThreadRun() override
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    nsAutoString type;
-    mBlobImpl->GetType(type);
-    return true;
-  }
-
-private:
-  ~GetTypeRunnable()
-  {}
-
-  RefPtr<BlobImpl> mBlobImpl;
-};
-
-} // anonymous namespace
-
-void
-BlobImplFile::GetType(nsAString& aType)
-{
-  aType.Truncate();
-
-  if (mContentType.IsVoid()) {
-    MOZ_ASSERT(mWholeFile,
-               "Should only use lazy ContentType when using the whole file");
-
-    if (!NS_IsMainThread()) {
-      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-      if (!workerPrivate) {
-        // I have no idea in which thread this method is called. We cannot
-        // return any valid value.
-        return;
-      }
-
-      RefPtr<GetTypeRunnable> runnable =
-        new GetTypeRunnable(workerPrivate, this);
-
-      ErrorResult rv;
-      runnable->Dispatch(Terminating, rv);
-      if (NS_WARN_IF(rv.Failed())) {
-        rv.SuppressException();
-      }
-      return;
-    }
-
-    nsresult rv;
-    nsCOMPtr<nsIMIMEService> mimeService =
-      do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-
-    nsAutoCString mimeType;
-    rv = mimeService->GetTypeFromFile(mFile, mimeType);
-    if (NS_FAILED(rv)) {
-      mimeType.Truncate();
-    }
-
-    AppendUTF8toUTF16(mimeType, mContentType);
-    mContentType.SetIsVoid(false);
-  }
-
-  aType = mContentType;
-}
-
-int64_t
-BlobImplFile::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (BlobImplBase::IsDateUnknown()) {
-    PRTime msecs;
-    aRv = mFile->GetLastModifiedTime(&msecs);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return 0;
-    }
-
-    mLastModificationDate = msecs;
-  }
-
-  return mLastModificationDate;
-}
-
-void
-BlobImplFile::SetLastModified(int64_t aLastModified)
-{
-  MOZ_CRASH("SetLastModified of a real file is not allowed!");
-}
-
-const uint32_t sFileStreamFlags =
-  nsIFileInputStream::CLOSE_ON_EOF |
-  nsIFileInputStream::REOPEN_ON_REWIND |
-  nsIFileInputStream::DEFER_OPEN |
-  nsIFileInputStream::SHARE_DELETE;
-
-void
-BlobImplFile::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mWholeFile) {
-    aRv = NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags);
-    return;
-  }
-
-  aRv = NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
-                                          -1, -1, sFileStreamFlags);
-}
-
-bool
-BlobImplFile::IsDirectory() const
-{
-  bool isDirectory = false;
-  if (mFile) {
-    mFile->IsDirectory(&isDirectory);
-  }
-  return isDirectory;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// EmptyBlobImpl implementation
-
 NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
 
 already_AddRefed<BlobImpl>
 EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
                            const nsAString& aContentType,
                            ErrorResult& aRv)
 {
   MOZ_ASSERT(!aStart && !aLength);
@@ -1003,348 +38,10 @@ EmptyBlobImpl::GetInternalStream(nsIInpu
 
   nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aRv.Throw(rv);
     return;
   }
 }
 
-////////////////////////////////////////////////////////////////////////////
-// BlobImplString implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplString, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplString>
-BlobImplString::Create(const nsACString& aData, const nsAString& aContentType)
-{
-  RefPtr<BlobImplString> blobImpl = new BlobImplString(aData, aContentType);
-  RegisterWeakMemoryReporter(blobImpl);
-  return blobImpl.forget();
-}
-
-BlobImplString::BlobImplString(const nsACString& aData,
-                               const nsAString& aContentType)
-  : BlobImplBase(aContentType, aData.Length())
-  , mData(aData)
-{
-}
-
-BlobImplString::~BlobImplString()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplString::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplString(Substring(mData, aStart, aLength),
-                       aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplString::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  aRv = NS_NewCStringInputStream(aStream, mData);
-}
-
-NS_IMETHODIMP
-BlobImplString::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/string", KIND_HEAP, UNITS_BYTES,
-    mData.SizeOfExcludingThisIfUnshared(MallocSizeOf),
-    "Memory used to back a File/Blob based on a string.");
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplMemory implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplMemory, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplMemory(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplMemory::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mLength > INT32_MAX) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aRv = DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
-}
-
-/* static */ StaticMutex
-BlobImplMemory::DataOwner::sDataOwnerMutex;
-
-/* static */ StaticAutoPtr<LinkedList<BlobImplMemory::DataOwner>>
-BlobImplMemory::DataOwner::sDataOwners;
-
-/* static */ bool
-BlobImplMemory::DataOwner::sMemoryReporterRegistered = false;
-
-MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
-
-class BlobImplMemoryDataOwnerMemoryReporter final
-  : public nsIMemoryReporter
-{
-  ~BlobImplMemoryDataOwnerMemoryReporter() {}
-
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
-                            nsISupports* aData, bool aAnonymize) override
-  {
-    typedef BlobImplMemory::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);
-
-      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);
-
-        nsAutoCString digestString;
-        for (size_t i = 0; i < sizeof(digest); i++) {
-          digestString.AppendPrintf("%02x", digest[i]);
-        }
-
-        aHandleReport->Callback(
-          /* process */ NS_LITERAL_CSTRING(""),
-          nsPrintfCString(
-            "explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
-            owner->mLength, aAnonymize ? "<anonymized>" : digestString.get()),
-          KIND_HEAP, UNITS_BYTES, size,
-          nsPrintfCString(
-            "Memory used to back a memory file of length %llu bytes.  The file "
-            "has a sha1 of %s.\n\n"
-            "Note that the allocator may round up a memory file's length -- "
-            "that is, an N-byte memory file may take up more than N bytes of "
-            "memory.",
-            owner->mLength, digestString.get()),
-          aData);
-      }
-    }
-
-    if (smallObjectsTotal > 0) {
-      aHandleReport->Callback(
-        /* process */ NS_LITERAL_CSTRING(""),
-        NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
-        KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
-        nsPrintfCString(
-          "Memory used to back small memory files (i.e. those taking up less "
-          "than %zu bytes of memory each).\n\n"
-          "Note that the allocator may round up a memory file's length -- "
-          "that is, an N-byte memory file may take up more than N bytes of "
-          "memory.", LARGE_OBJECT_MIN_SIZE),
-        aData);
-    }
-
-    return NS_OK;
-  }
-};
-
-NS_IMPL_ISUPPORTS(BlobImplMemoryDataOwnerMemoryReporter, nsIMemoryReporter)
-
-/* static */ void
-BlobImplMemory::DataOwner::EnsureMemoryReporterRegistered()
-{
-  sDataOwnerMutex.AssertCurrentThreadOwns();
-  if (sMemoryReporterRegistered) {
-    return;
-  }
-
-  RegisterStrongMemoryReporter(new BlobImplMemoryDataOwnerMemoryReporter());
-
-  sMemoryReporterRegistered = true;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplTemporaryBlob implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplTemporaryBlob, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplTemporaryBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                                   const nsAString& aContentType,
-                                   ErrorResult& aRv)
-{
-  if (aStart + aLength > mLength) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplTemporaryBlob(this, aStart + mStartPos,
-                              aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplTemporaryBlob::GetInternalStream(nsIInputStream** aStream,
-                                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> stream =
-    new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength);
-  stream.forget(aStream);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplStream implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplStream, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aContentType,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aContentType, aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aName, aContentType, aLastModifiedDate,
-                       aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aContentType,
-                               uint64_t aLength)
-  : BlobImplBase(aContentType, aLength)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(BlobImplStream* aOther,
-                               const nsAString& aContentType,
-                               uint64_t aStart, uint64_t aLength)
-  : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-  , mInputStream(new SlicedInputStream(aOther->mInputStream, aStart, aLength))
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aName,
-                               const nsAString& aContentType,
-                               int64_t aLastModifiedDate,
-                               uint64_t aLength)
-  : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::~BlobImplStream()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-void
-BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> clonedStream;
-  nsCOMPtr<nsIInputStream> replacementStream;
-
-  aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
-                            getter_AddRefs(replacementStream));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  if (replacementStream) {
-    mInputStream = replacementStream.forget();
-  }
-
-  clonedStream.forget(aStream);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplStream::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType, ErrorResult& aRv)
-{
-  if (!aLength) {
-    RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-    return impl.forget();
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplStream(this, aContentType, aStart, aLength);
-  return impl.forget();
-}
-
-void
-BlobImplStream::MaybeRegisterMemoryReporter()
-{
-  // We report only stringInputStream.
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return;
-  }
-
-  RegisterWeakMemoryReporter(this);
-}
-
-NS_IMETHODIMP
-BlobImplStream::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return NS_OK;
-  }
-
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
-    stringInputStream->SizeOfIncludingThis(MallocSizeOf),
-    "Memory used to back a File/Blob based on an input stream.");
-
-  return NS_OK;
-}
-
 } // namespace dom
 } // namespace mozilla
copy from dom/file/File.h
copy to dom/file/EmptyBlobImpl.h
--- a/dom/file/File.h
+++ b/dom/file/EmptyBlobImpl.h
@@ -1,787 +1,37 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_dom_File_h
-#define mozilla_dom_File_h
+#ifndef mozilla_dom_EmptyBlobImpl_h
+#define mozilla_dom_EmptyBlobImpl_h
 
-#include "mozilla/Attributes.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/GuardObjects.h"
-#include "mozilla/LinkedList.h"
-#include "mozilla/StaticMutex.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/Date.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMBlob.h"
-#include "nsIFile.h"
-#include "nsIMemoryReporter.h"
-#include "nsIMutable.h"
-#include "nsIXMLHttpRequest.h"
-#include "nsString.h"
-#include "nsTemporaryFileInputStream.h"
-#include "nsWrapperCache.h"
-#include "nsWeakReference.h"
-
-class nsIFile;
-class nsIInputStream;
-
-#define BLOBIMPL_IID \
-  { 0xbccb3275, 0x6778, 0x4ac5, \
-    { 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
+#include "BaseBlobImpl.h"
 
 namespace mozilla {
 namespace dom {
 
-struct BlobPropertyBag;
-struct ChromeFilePropertyBag;
-struct FilePropertyBag;
-class BlobImpl;
-class File;
-class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
-class Promise;
-
-class Blob : public nsIDOMBlob
-           , public nsIXHRSendable
-           , public nsIMutable
-           , public nsSupportsWeakReference
-           , public nsWrapperCache
-{
-public:
-  NS_DECL_NSIDOMBLOB
-  NS_DECL_NSIXHRSENDABLE
-  NS_DECL_NSIMUTABLE
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
-
-  typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
-
-  // This creates a Blob or a File based on the type of BlobImpl.
-  static Blob*
-  Create(nsISupports* aParent, BlobImpl* aImpl);
-
-  static already_AddRefed<Blob>
-  CreateStringBlob(nsISupports* aParent, const nsACString& aData,
-                   const nsAString& aContentType);
-
-  // The returned Blob takes ownership of aMemoryBuffer. aMemoryBuffer will be
-  // freed by free so it must be allocated by malloc or something
-  // compatible with it.
-  static already_AddRefed<Blob>
-  CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
-                   const nsAString& aContentType);
-
-  static already_AddRefed<Blob>
-  CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
-                      uint64_t aStartPos, uint64_t aLength,
-                      const nsAString& aContentType);
-
-  BlobImpl* Impl() const
-  {
-    return mImpl;
-  }
-
-  bool IsFile() const;
-
-  const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const;
-
-  // This method returns null if this Blob is not a File; it returns
-  // the same object in case this Blob already implements the File interface;
-  // otherwise it returns a new File object with the same BlobImpl.
-  already_AddRefed<File> ToFile();
-
-  // This method creates a new File object with the given name and the same
-  // BlobImpl.
-  already_AddRefed<File> ToFile(const nsAString& aName,
-                                ErrorResult& aRv) const;
-
-  already_AddRefed<Blob>
-  CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
-              ErrorResult& aRv);
-
-  void
-  GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv);
-
-  int64_t
-  GetFileId();
-
-  // WebIDL methods
-  nsISupports* GetParentObject() const
-  {
-    return mParent;
-  }
-
-  bool
-  IsMemoryFile() const;
-
-  // Blob constructor
-  static already_AddRefed<Blob>
-  Constructor(const GlobalObject& aGlobal,
-              const Optional<Sequence<BlobPart>>& aData,
-              const BlobPropertyBag& aBag,
-              ErrorResult& aRv);
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  uint64_t GetSize(ErrorResult& aRv);
-
-  void GetType(nsAString& aType);
-
-  already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
-                               const Optional<int64_t>& aEnd,
-                               const nsAString& aContentType,
-                               ErrorResult& aRv);
-
-protected:
-  // File constructor should never be used directly. Use Blob::Create instead.
-  Blob(nsISupports* aParent, BlobImpl* aImpl);
-  virtual ~Blob() {};
-
-  virtual bool HasFileInterface() const { return false; }
-
-  // The member is the real backend implementation of this File/Blob.
-  // 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!
-  RefPtr<BlobImpl> mImpl;
-
-private:
-  nsCOMPtr<nsISupports> mParent;
-};
-
-class File final : public Blob
-{
-  friend class Blob;
-
-public:
-  // Note: BlobImpl must be a File in order to use this method.
-  // Check impl->IsFile().
-  static File*
-  Create(nsISupports* aParent, BlobImpl* aImpl);
-
-  static already_AddRefed<File>
-  Create(nsISupports* aParent, const nsAString& aName,
-         const nsAString& aContentType, uint64_t aLength,
-         int64_t aLastModifiedDate);
-
-  // The returned File takes ownership of aMemoryBuffer. aMemoryBuffer will be
-  // freed by free so it must be allocated by malloc or something
-  // compatible with it.
-  static already_AddRefed<File>
-  CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
-                   const nsAString& aName, const nsAString& aContentType,
-                   int64_t aLastModifiedDate);
-
-  // This method creates a BlobFileImpl for the new File object. This is
-  // thread-safe, cross-process, cross-thread as any other BlobImpl, but, when
-  // GetType() is called, it must dispatch a runnable to the main-thread in
-  // order to use nsIMIMEService.
-  // Would be nice if we try to avoid to use this method outside the
-  // main-thread to avoid extra runnables.
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile);
-
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile, const nsAString& aName,
-                 const nsAString& aContentType);
-
-  // WebIDL methods
-
-  virtual JSObject* WrapObject(JSContext *cx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  // File constructor
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const Sequence<BlobPart>& aData,
-              const nsAString& aName,
-              const FilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromFileName(const GlobalObject& aGlobal,
-                     const nsAString& aFilePath,
-                     const ChromeFilePropertyBag& aBag,
-                     SystemCallerGuarantee aGuarantee,
-                     ErrorResult& aRv);
-
-  // ChromeOnly
-  static already_AddRefed<Promise>
-  CreateFromNsIFile(const GlobalObject& aGlobal,
-                    nsIFile* aFile,
-                    const ChromeFilePropertyBag& aBag,
-                    SystemCallerGuarantee aGuarantee,
-                    ErrorResult& aRv);
-
-  void GetName(nsAString& aName) const;
-
-  int64_t GetLastModified(ErrorResult& aRv);
-
-  Date GetLastModifiedDate(ErrorResult& aRv);
-
-  void GetRelativePath(nsAString& aPath) const;
-
-  void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
-                      ErrorResult& aRv) const;
-
-  void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv) const;
-
-protected:
-  virtual bool HasFileInterface() const override { return true; }
-
-private:
-  // File constructor should never be used directly. Use Blob::Create or
-  // File::Create.
-  File(nsISupports* aParent, BlobImpl* aImpl);
-  ~File() {};
-};
-
-// This is the abstract class for any File backend. It must be nsISupports
-// because this class must be ref-counted and it has to work with IPC.
-class BlobImpl : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(BLOBIMPL_IID)
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  BlobImpl() {}
-
-  virtual void GetName(nsAString& aName) const = 0;
-
-  virtual void GetDOMPath(nsAString& aName) const = 0;
-
-  virtual void SetDOMPath(const nsAString& aName) = 0;
-
-  virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
-
-  virtual void SetLastModified(int64_t aLastModified) = 0;
-
-  virtual void GetMozFullPath(nsAString& aName,
-                              SystemCallerGuarantee /* unused */,
-                              ErrorResult& aRv) const = 0;
-
-  virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const = 0;
-
-  virtual uint64_t GetSize(ErrorResult& aRv) = 0;
-
-  virtual void GetType(nsAString& aType) = 0;
-
-  /**
-   * An effectively-unique serial number identifying this instance of FileImpl.
-   *
-   * Implementations should obtain a serial number from
-   * FileImplBase::NextSerialNumber().
-   */
-  virtual uint64_t GetSerialNumber() const = 0;
-
-  already_AddRefed<BlobImpl>
-  Slice(const Optional<int64_t>& aStart, const Optional<int64_t>& aEnd,
-        const nsAString& aContentType, ErrorResult& aRv);
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) = 0;
-
-  virtual const nsTArray<RefPtr<BlobImpl>>*
-  GetSubBlobImpls() const = 0;
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) = 0;
-
-  virtual int64_t GetFileId() = 0;
-
-  virtual nsresult GetSendInfo(nsIInputStream** aBody,
-                               uint64_t* aContentLength,
-                               nsACString& aContentType,
-                               nsACString& aCharset) = 0;
-
-  virtual nsresult GetMutable(bool* aMutable) const = 0;
-
-  virtual nsresult SetMutable(bool aMutable) = 0;
-
-  virtual void SetLazyData(const nsAString& aName,
-                           const nsAString& aContentType,
-                           uint64_t aLength,
-                           int64_t aLastModifiedDate) = 0;
-
-  virtual bool IsMemoryFile() const = 0;
-
-  virtual bool IsSizeUnknown() const = 0;
-
-  virtual bool IsDateUnknown() const = 0;
-
-  virtual bool IsFile() const = 0;
-
-  // Returns true if the BlobImpl is backed by an nsIFile and the underlying
-  // file is a directory.
-  virtual bool IsDirectory() const
-  {
-    return false;
-  }
-
-  // True if this implementation can be sent to other threads.
-  virtual bool MayBeClonedToOtherThreads() const
-  {
-    return true;
-  }
-
-protected:
-  virtual ~BlobImpl() {}
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(BlobImpl, BLOBIMPL_IID)
-
-class BlobImplBase : public BlobImpl
-{
-public:
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, int64_t aLastModifiedDate)
-    : mIsFile(true)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mName(aName)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(aLastModifiedDate)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength)
-    : mIsFile(true)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mName(aName)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aContentType, uint64_t aLength)
-    : mIsFile(false)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mStart(0)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  BlobImplBase(const nsAString& aContentType, uint64_t aStart,
-               uint64_t aLength)
-    : mIsFile(false)
-    , mImmutable(false)
-    , mContentType(aContentType)
-    , mStart(aStart)
-    , mLength(aLength)
-    , mLastModificationDate(INT64_MAX)
-    , mSerialNumber(NextSerialNumber())
-  {
-    MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
-    // Ensure non-null mContentType by default
-    mContentType.SetIsVoid(false);
-  }
-
-  virtual void GetName(nsAString& aName) const override;
-
-  virtual void GetDOMPath(nsAString& aName) const override;
-
-  virtual void SetDOMPath(const nsAString& aName) override;
-
-  virtual int64_t GetLastModified(ErrorResult& aRv) override;
-
-  virtual void SetLastModified(int64_t aLastModified) override;
-
-  virtual void GetMozFullPath(nsAString& aName,
-                              SystemCallerGuarantee /* unused */,
-                              ErrorResult& aRv) const override;
-
-  virtual void GetMozFullPathInternal(nsAString& aFileName,
-                                      ErrorResult& aRv) const override;
-
-  virtual uint64_t GetSize(ErrorResult& aRv) override
-  {
-    return mLength;
-  }
-
-  virtual void GetType(nsAString& aType) override;
-
-  virtual uint64_t GetSerialNumber() const override { return mSerialNumber; }
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override
-  {
-    return nullptr;
-  }
-
-  virtual const nsTArray<RefPtr<BlobImpl>>*
-  GetSubBlobImpls() const override
-  {
-    return nullptr;
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override
-  {
-    aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-  }
-
-  virtual int64_t GetFileId() override;
-
-  virtual nsresult GetSendInfo(nsIInputStream** aBody,
-                               uint64_t* aContentLength,
-                               nsACString& aContentType,
-                               nsACString& aCharset) override;
-
-  virtual nsresult GetMutable(bool* aMutable) const override;
-
-  virtual nsresult SetMutable(bool aMutable) override;
-
-  virtual void
-  SetLazyData(const nsAString& aName, const nsAString& aContentType,
-              uint64_t aLength, int64_t aLastModifiedDate) override
-  {
-    mName = aName;
-    mContentType = aContentType;
-    mLength = aLength;
-    mLastModificationDate = aLastModifiedDate;
-    mIsFile = !aName.IsVoid();
-  }
-
-  virtual bool IsMemoryFile() const override
-  {
-    return false;
-  }
-
-  virtual bool IsDateUnknown() const override
-  {
-    return mIsFile && mLastModificationDate == INT64_MAX;
-  }
-
-  virtual bool IsFile() const override
-  {
-    return mIsFile;
-  }
-
-  virtual bool IsSizeUnknown() const override
-  {
-    return mLength == UINT64_MAX;
-  }
-
-protected:
-  virtual ~BlobImplBase() {}
-
-  /**
-   * Returns a new, effectively-unique serial number. This should be used
-   * by implementations to obtain a serial number for GetSerialNumber().
-   * The implementation is thread safe.
-   */
-  static uint64_t NextSerialNumber();
-
-  bool mIsFile;
-  bool mImmutable;
-
-  nsString mContentType;
-  nsString mName;
-  nsString mPath; // The path relative to a directory chosen by the user
-
-  uint64_t mStart;
-  uint64_t mLength;
-
-  int64_t mLastModificationDate;
-
-  const uint64_t mSerialNumber;
-};
-
-class BlobImplString final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplString>
-  Create(const nsACString& aData, const nsAString& aContentType);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplString(const nsACString& aData, const nsAString& aContentType);
-
-  ~BlobImplString();
-
-  nsCString mData;
-};
-
-/**
- * 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 BlobImplMemory final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
-                 const nsAString& aContentType, int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  BlobImplMemory(void* aMemoryBuffer, uint64_t aLength,
-                 const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-  class DataOwner final : public mozilla::LinkedListElement<DataOwner>
-  {
-  public:
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
-    DataOwner(void* aMemoryBuffer, uint64_t aLength)
-      : mData(aMemoryBuffer)
-      , mLength(aLength)
-    {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      if (!sDataOwners) {
-        sDataOwners = new mozilla::LinkedList<DataOwner>();
-        EnsureMemoryReporterRegistered();
-      }
-      sDataOwners->insertBack(this);
-    }
-
-  private:
-    // Private destructor, to discourage deletion outside of Release():
-    ~DataOwner() {
-      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
-
-      remove();
-      if (sDataOwners->isEmpty()) {
-        // Free the linked list if it's empty.
-        sDataOwners = nullptr;
-      }
-
-      free(mData);
-    }
-
-  public:
-    static void EnsureMemoryReporterRegistered();
-
-    // sDataOwners and sMemoryReporterRegistered may only be accessed while
-    // holding sDataOwnerMutex!  You also must hold the mutex while touching
-    // elements of the linked list that DataOwner inherits from.
-    static mozilla::StaticMutex sDataOwnerMutex;
-    static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
-    static bool sMemoryReporterRegistered;
-
-    void* mData;
-    uint64_t mLength;
-  };
-
-private:
-  // Create slice
-  BlobImplMemory(const BlobImplMemory* aOther, uint64_t aStart,
-                 uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mDataOwner(aOther->mDataOwner)
-  {
-    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
-    mImmutable = aOther->mImmutable;
-  }
-
-  ~BlobImplMemory() {}
-
-  // Used when backed by a memory store
-  RefPtr<DataOwner> mDataOwner;
-};
-
-class BlobImplTemporaryBlob final : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  BlobImplTemporaryBlob(PRFileDesc* aFD, uint64_t aStartPos,
-                        uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStartPos)
-  {
-    mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
-  }
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-private:
-  BlobImplTemporaryBlob(const BlobImplTemporaryBlob* aOther,
-                        uint64_t aStart, uint64_t aLength,
-                        const nsAString& aContentType)
-    : BlobImplBase(aContentType, aLength)
-    , mStartPos(aStart)
-    , mFileDescOwner(aOther->mFileDescOwner)
-  {}
-
-  ~BlobImplTemporaryBlob() {}
-
-  uint64_t mStartPos;
-  RefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
-};
-
-class BlobImplFile : public BlobImplBase
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // Create as a file
-  explicit BlobImplFile(nsIFile* aFile)
-    : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    // Lazily get the content type and size
-    mContentType.SetIsVoid(true);
-    mFile->GetLeafName(mName);
-  }
-
-  // Create as a file
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile)
-    : BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile,
-               int64_t aLastModificationDate)
-    : BlobImplBase(aName, aContentType, aLength, aLastModificationDate)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-  }
-
-  // Create as a file with custom name
-  BlobImplFile(nsIFile* aFile, const nsAString& aName,
-               const nsAString& aContentType)
-    : BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    if (aContentType.IsEmpty()) {
-      // Lazily get the content type and size
-      mContentType.SetIsVoid(true);
-    }
-  }
-
-  // Overrides
-  virtual uint64_t GetSize(ErrorResult& aRv) override;
-  virtual void GetType(nsAString& aType) override;
-  virtual int64_t GetLastModified(ErrorResult& aRv) override;
-  virtual void SetLastModified(int64_t aLastModified) override;
-  virtual void GetMozFullPathInternal(nsAString& aFullPath,
-                                      ErrorResult& aRv) const override;
-  virtual void GetInternalStream(nsIInputStream** aInputStream,
-                                 ErrorResult& aRv) override;
-
-  virtual bool IsDirectory() const override;
-
-  // We always have size and date for this kind of blob.
-  virtual bool IsSizeUnknown() const override { return false; }
-  virtual bool IsDateUnknown() const override { return false; }
-
-protected:
-  virtual ~BlobImplFile() = default;
-
-private:
-  // Create slice
-  BlobImplFile(const BlobImplFile* aOther, uint64_t aStart,
-               uint64_t aLength, const nsAString& aContentType)
-    : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-    , mFile(aOther->mFile)
-    , mWholeFile(false)
-  {
-    MOZ_ASSERT(mFile, "must have file");
-    mImmutable = aOther->mImmutable;
-  }
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  nsCOMPtr<nsIFile> mFile;
-  bool mWholeFile;
-};
-
-class EmptyBlobImpl final : public BlobImplBase
+class EmptyBlobImpl final : public BaseBlobImpl
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   explicit EmptyBlobImpl(const nsAString& aContentType)
-    : BlobImplBase(aContentType, 0 /* aLength */)
+    : BaseBlobImpl(aContentType, 0 /* aLength */)
   {
     mImmutable = true;
   }
 
   EmptyBlobImpl(const nsAString& aName,
                 const nsAString& aContentType,
                 int64_t aLastModifiedDate)
-    : BlobImplBase(aName, aContentType, 0, aLastModifiedDate)
+    : BaseBlobImpl(aName, aContentType, 0, aLastModifiedDate)
   {
     mImmutable = true;
   }
 
   virtual void GetInternalStream(nsIInputStream** aStream,
                                  ErrorResult& aRv) override;
 
   virtual already_AddRefed<BlobImpl>
@@ -792,68 +42,12 @@ public:
   {
     return true;
   }
 
 private:
   ~EmptyBlobImpl() {}
 };
 
-class BlobImplStream final : public BlobImplBase
-                           , public nsIMemoryReporter
-{
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIMEMORYREPORTER
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aContentType,
-         uint64_t aLength);
-
-  static already_AddRefed<BlobImplStream>
-  Create(nsIInputStream* aInputStream,
-         const nsAString& aName,
-         const nsAString& aContentType,
-         int64_t aLastModifiedDate,
-         uint64_t aLength);
-
-  virtual void GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv) override;
-
-  virtual already_AddRefed<BlobImpl>
-  CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType, ErrorResult& aRv) override;
-
-  virtual bool IsMemoryFile() const override
-  {
-    return true;
-  }
-
-private:
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aContentType,
-                 uint64_t aLength);
-
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aName,
-                 const nsAString& aContentType,
-                 int64_t aLastModifiedDate,
-                 uint64_t aLength);
-
-  BlobImplStream(BlobImplStream* aOther,
-                 const nsAString& aContentType,
-                 uint64_t aStart,
-                 uint64_t aLength);
-
-  ~BlobImplStream();
-
-  void MaybeRegisterMemoryReporter();
-
-  nsCOMPtr<nsIInputStream> mInputStream;
-};
-
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_File_h
+#endif // mozilla_dom_EmptyBlobImpl_h
--- a/dom/file/File.cpp
+++ b/dom/file/File.cpp
@@ -1,467 +1,80 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/File.h"
-
-#include "ipc/nsIRemoteBlob.h"
+#include "File.h"
+#include "FileBlobImpl.h"
+#include "MemoryBlobImpl.h"
 #include "MultipartBlobImpl.h"
-#include "nsCExternalHandlerService.h"
-#include "nsContentCID.h"
-#include "nsContentUtils.h"
-#include "nsError.h"
-#include "nsICharsetDetector.h"
-#include "nsIConverterInputStream.h"
-#include "nsIDocument.h"
-#include "nsIFileStreams.h"
-#include "nsIInputStream.h"
-#include "nsIIPCSerializableInputStream.h"
-#include "nsIMIMEService.h"
-#include "nsISeekableStream.h"
-#include "nsIUnicharInputStream.h"
-#include "nsIUnicodeDecoder.h"
-#include "nsNetCID.h"
-#include "nsNetUtil.h"
-#include "nsIUUIDGenerator.h"
-#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/DOMError.h"
 #include "mozilla/dom/FileBinding.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerRunnable.h"
-#include "nsThreadUtils.h"
-#include "nsStreamUtils.h"
-#include "SlicedInputStream.h"
 
 namespace mozilla {
 namespace dom {
 
-using namespace workers;
-
-// XXXkhuey the input stream that we pass out of a File
-// can outlive the actual File 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 final : public nsIInputStream,
-                               public nsISeekableStream,
-                               public nsIIPCSerializableInputStream
-{
-  typedef BlobImplMemory::DataOwner DataOwner;
-public:
-  static nsresult Create(DataOwner* aDataOwner,
-                         uint32_t aStart,
-                         uint32_t aLength,
-                         nsIInputStream** _retval);
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  // These are mandatory.
-  NS_FORWARD_NSIINPUTSTREAM(mStream->)
-  NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
-
-  // This is optional. We use a conditional QI to keep it from being called
-  // if the underlying stream doesn't support it.
-  NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
-
-private:
-  ~DataOwnerAdapter() {}
-
-  DataOwnerAdapter(DataOwner* aDataOwner,
-                   nsIInputStream* aStream)
-    : mDataOwner(aDataOwner), mStream(aStream),
-      mSeekableStream(do_QueryInterface(aStream)),
-      mSerializableInputStream(do_QueryInterface(aStream))
-  {
-    MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
-  }
-
-  RefPtr<DataOwner> mDataOwner;
-  nsCOMPtr<nsIInputStream> mStream;
-  nsCOMPtr<nsISeekableStream> mSeekableStream;
-  nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
-};
-
-NS_IMPL_ADDREF(DataOwnerAdapter)
-NS_IMPL_RELEASE(DataOwnerAdapter)
-
-NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
-  NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
-                                     mSerializableInputStream)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
-NS_INTERFACE_MAP_END
-
-nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
-                                  uint32_t aStart,
-                                  uint32_t aLength,
-                                  nsIInputStream** _retval)
-{
-  nsresult rv;
-  MOZ_ASSERT(aDataOwner, "Uh ...");
-
-  nsCOMPtr<nsIInputStream> stream;
-
-  rv = NS_NewByteInputStream(getter_AddRefs(stream),
-                             static_cast<const char*>(aDataOwner->mData) +
-                             aStart,
-                             (int32_t)aLength,
-                             NS_ASSIGNMENT_DEPEND);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
-
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::Blob implementation
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
-  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(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
-  // 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, nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
-  NS_INTERFACE_MAP_ENTRY(nsIMutable)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
-
-// A utility function that enforces the spec constraints on the type of a blob:
-// no codepoints outside the ASCII range (otherwise type becomes empty) and
-// lowercase ASCII only.  We can't just use our existing nsContentUtils
-// ASCII-related helpers because we need the "outside ASCII range" check, and we
-// can't use NS_IsAscii because its definition of "ASCII" (chars all <= 0x7E)
-// differs from the file API definition (which excludes control chars).
-static void
-MakeValidBlobType(nsAString& aType)
-{
-  char16_t* iter = aType.BeginWriting();
-  char16_t* end = aType.EndWriting();
-
-  for ( ; iter != end; ++iter) {
-    char16_t c = *iter;
-    if (c < 0x20 || c > 0x7E) {
-      // Non-ASCII char, bail out.
-      aType.Truncate();
-      return;
-    }
-
-    if (c >= 'A' && c <= 'Z') {
-      *iter = c + ('a' - 'A');
-    }
-  }
-}
-
-/* static */ Blob*
-Blob::Create(nsISupports* aParent, BlobImpl* aImpl)
-{
-  MOZ_ASSERT(aImpl);
-
-  return aImpl->IsFile() ? new File(aParent, aImpl)
-                         : new Blob(aParent, aImpl);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateStringBlob(nsISupports* aParent, const nsACString& aData,
-                       const nsAString& aContentType)
-{
-  RefPtr<BlobImpl> blobImpl = BlobImplString::Create(aData, aContentType);
-  RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer,
-                       uint64_t aLength, const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
-                          uint64_t aStartPos, uint64_t aLength,
-                          const nsAString& aContentType)
-{
-  RefPtr<Blob> blob = Blob::Create(aParent,
-    new BlobImplTemporaryBlob(aFD, aStartPos, aLength, aContentType));
-  MOZ_ASSERT(!blob->mImpl->IsFile());
-  return blob.forget();
-}
-
-Blob::Blob(nsISupports* aParent, BlobImpl* aImpl)
-  : mImpl(aImpl)
-  , mParent(aParent)
-{
-  MOZ_ASSERT(mImpl);
-
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aParent);
-    if (win) {
-      MOZ_ASSERT(win->IsInnerWindow());
-    }
-  }
-#endif
-}
-
-bool
-Blob::IsFile() const
-{
-  return mImpl->IsFile();
-}
-
-const nsTArray<RefPtr<BlobImpl>>*
-Blob::GetSubBlobImpls() const
-{
-  return mImpl->GetSubBlobImpls();
-}
-
-already_AddRefed<File>
-Blob::ToFile()
-{
-  if (!mImpl->IsFile()) {
-    return nullptr;
-  }
-
-  RefPtr<File> file;
-  if (HasFileInterface()) {
-    file = static_cast<File*>(this);
-  } else {
-    file = new File(mParent, mImpl);
-  }
-
-  return file.forget();
-}
-
-already_AddRefed<File>
-Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const
-{
-  AutoTArray<RefPtr<BlobImpl>, 1> blobImpls({mImpl});
-
-  nsAutoString contentType;
-  mImpl->GetType(contentType);
-
-  RefPtr<MultipartBlobImpl> impl =
-    MultipartBlobImpl::Create(Move(blobImpls), aName, contentType, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  RefPtr<File> file = new File(mParent, impl);
-  return file.forget();
-}
-
-already_AddRefed<Blob>
-Blob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                  const nsAString& aContentType,
-                  ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl = mImpl->CreateSlice(aStart, aLength,
-                                             aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-uint64_t
-Blob::GetSize(ErrorResult& aRv)
-{
-  return mImpl->GetSize(aRv);
-}
-
-void
-Blob::GetType(nsAString &aType)
-{
-  mImpl->GetType(aType);
-}
-
-already_AddRefed<Blob>
-Blob::Slice(const Optional<int64_t>& aStart,
-            const Optional<int64_t>& aEnd,
-            const nsAString& aContentType,
-            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    mImpl->Slice(aStart, aEnd, aContentType, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  RefPtr<Blob> blob = Blob::Create(mParent, impl);
-  return blob.forget();
-}
-
-NS_IMETHODIMP
-Blob::GetSendInfo(nsIInputStream** aBody,
-                  uint64_t* aContentLength,
-                  nsACString& aContentType,
-                  nsACString& aCharset)
-{
-  return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
-}
-
-NS_IMETHODIMP
-Blob::GetMutable(bool* aMutable)
-{
-  return mImpl->GetMutable(aMutable);
-}
-
-NS_IMETHODIMP
-Blob::SetMutable(bool aMutable)
-{
-  return mImpl->SetMutable(aMutable);
-}
-
-JSObject*
-Blob::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return BlobBinding::Wrap(aCx, this, aGivenProto);
-}
-
-/* static */ already_AddRefed<Blob>
-Blob::Constructor(const GlobalObject& aGlobal,
-                  const Optional<Sequence<BlobPart>>& aData,
-                  const BlobPropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();
-
-  if (aData.WasPassed()) {
-    nsAutoString type(aBag.mType);
-    MakeValidBlobType(type);
-    impl->InitializeBlob(aGlobal.Context(), aData.Value(), type,
-                         aBag.mEndings == EndingTypes::Native, aRv);
-  } else {
-    impl->InitializeBlob(aRv);
-  }
-
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  MOZ_ASSERT(!impl->IsFile());
-
-  RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
-  return blob.forget();
-}
-
-int64_t
-Blob::GetFileId()
-{
-  return mImpl->GetFileId();
-}
-
-bool
-Blob::IsMemoryFile() const
-{
-  return mImpl->IsMemoryFile();
-}
-
-void
-Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  mImpl->GetInternalStream(aStream, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::File implementation
-
 File::File(nsISupports* aParent, BlobImpl* aImpl)
   : Blob(aParent, aImpl)
 {
   MOZ_ASSERT(aImpl->IsFile());
 }
 
+File::~File()
+{}
+
 /* static */ File*
 File::Create(nsISupports* aParent, BlobImpl* aImpl)
 {
   MOZ_ASSERT(aImpl);
   MOZ_ASSERT(aImpl->IsFile());
 
   return new File(aParent, aImpl);
 }
 
 /* static */ already_AddRefed<File>
 File::Create(nsISupports* aParent, const nsAString& aName,
              const nsAString& aContentType, uint64_t aLength,
              int64_t aLastModifiedDate)
 {
   RefPtr<File> file = new File(aParent,
-    new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
+    new BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate));
   return file.forget();
 }
 
 /* static */ already_AddRefed<File>
 File::CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer,
                        uint64_t aLength, const nsAString& aName,
                        const nsAString& aContentType,
                        int64_t aLastModifiedDate)
 {
   RefPtr<File> file = new File(aParent,
-    new BlobImplMemory(aMemoryBuffer, aLength, aName,
+    new MemoryBlobImpl(aMemoryBuffer, aLength, aName,
                        aContentType, aLastModifiedDate));
   return file.forget();
 }
 
 /* static */ already_AddRefed<File>
 File::CreateFromFile(nsISupports* aParent, nsIFile* aFile)
 {
-  RefPtr<File> file = new File(aParent, new BlobImplFile(aFile));
+  RefPtr<File> file = new File(aParent, new FileBlobImpl(aFile));
   return file.forget();
 }
 
 /* static */ already_AddRefed<File>
 File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
                      const nsAString& aName, const nsAString& aContentType)
 {
   RefPtr<File> file = new File(aParent,
-    new BlobImplFile(aFile, aName, aContentType));
+    new FileBlobImpl(aFile, aName, aContentType));
   return file.forget();
 }
 
 JSObject*
 File::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return FileBinding::Wrap(aCx, this, aGivenProto);
 }
@@ -512,53 +125,16 @@ File::GetMozFullPath(nsAString& aFilenam
 }
 
 void
 File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
 {
   mImpl->GetMozFullPathInternal(aFileName, aRv);
 }
 
-// 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;
-  if (aStart < -aSize) {
-    newStartOffset = 0;
-  }
-  else if (aStart < 0) {
-    newStartOffset += aSize;
-  }
-  else if (aStart > aSize) {
-    newStartOffset = aSize;
-  }
-
-  CheckedInt64 newEndOffset = aEnd;
-  if (aEnd < -aSize) {
-    newEndOffset = 0;
-  }
-  else if (aEnd < 0) {
-    newEndOffset += aSize;
-  }
-  else if (aEnd > aSize) {
-    newEndOffset = aSize;
-  }
-
-  if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
-      newStartOffset.value() >= newEndOffset.value()) {
-    aStart = aEnd = 0;
-  }
-  else {
-    aStart = newStartOffset.value();
-    aEnd = newEndOffset.value();
-  }
-}
-
 /* static */ already_AddRefed<File>
 File::Constructor(const GlobalObject& aGlobal,
                   const Sequence<BlobPart>& aData,
                   const nsAString& aName,
                   const FilePropertyBag& aBag,
                   ErrorResult& aRv)
 {
   // Normalizing the filename
@@ -614,737 +190,10 @@ File::CreateFromFileName(const GlobalObj
 
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
 
   RefPtr<Promise> promise =
     FileCreatorHelper::CreateFile(global, file, aBag, false, aRv);
   return promise.forget();
 }
 
-////////////////////////////////////////////////////////////////////////////
-// mozilla::dom::BlobImpl implementation
-
-already_AddRefed<BlobImpl>
-BlobImpl::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);
-
-  nsAutoString type(aContentType);
-  MakeValidBlobType(type);
-  return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImpl implementation
-
-NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFile, BlobImpl)
-
-void
-BlobImplBase::GetName(nsAString& aName) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aName = mName;
-}
-
-void
-BlobImplBase::GetDOMPath(nsAString& aPath) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aPath = mPath;
-}
-
-void
-BlobImplBase::SetDOMPath(const nsAString& aPath)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  mPath = aPath;
-}
-
-void
-BlobImplBase::GetMozFullPath(nsAString& aFileName,
-                             SystemCallerGuarantee /* unused */,
-                             ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-
-  GetMozFullPathInternal(aFileName, aRv);
-}
-
-void
-BlobImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
-{
-  if (!mIsFile) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aFileName.Truncate();
-}
-
-void
-BlobImplBase::GetType(nsAString& aType)
-{
-  aType = mContentType;
-}
-
-int64_t
-BlobImplBase::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (IsDateUnknown()) {
-    mLastModificationDate = PR_Now();
-  }
-
-  return mLastModificationDate / PR_USEC_PER_MSEC;
-}
-
-void
-BlobImplBase::SetLastModified(int64_t aLastModified)
-{
-  mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
-}
-
-int64_t
-BlobImplBase::GetFileId()
-{
-  return -1;
-}
-
-nsresult
-BlobImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
-                          nsACString& aContentType, nsACString& aCharset)
-{
-  MOZ_ASSERT(aContentLength);
-
-  ErrorResult rv;
-
-  nsCOMPtr<nsIInputStream> stream;
-  GetInternalStream(getter_AddRefs(stream), rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  *aContentLength = GetSize(rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
-  }
-
-  nsAutoString contentType;
-  GetType(contentType);
-
-  if (contentType.IsEmpty()) {
-    aContentType.SetIsVoid(true);
-  } else {
-    CopyUTF16toUTF8(contentType, aContentType);
-  }
-
-  aCharset.Truncate();
-
-  stream.forget(aBody);
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::GetMutable(bool* aMutable) const
-{
-  *aMutable = !mImmutable;
-  return NS_OK;
-}
-
-nsresult
-BlobImplBase::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);
-
-    ErrorResult error;
-    GetSize(error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-  }
-
-  mImmutable = !aMutable;
-  return rv;
-}
-
-/* static */ uint64_t
-BlobImplBase::NextSerialNumber()
-{
-  static Atomic<uint64_t> nextSerialNumber;
-  return nextSerialNumber++;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplFile implementation
-
-already_AddRefed<BlobImpl>
-BlobImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
-                          const nsAString& aContentType,
-                          ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplFile(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) const
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  aRv = mFile->GetPath(aFilename);
-}
-
-uint64_t
-BlobImplFile::GetSize(ErrorResult& aRv)
-{
-  if (BlobImplBase::IsSizeUnknown()) {
-    MOZ_ASSERT(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;
-    }
-
-    if (fileSize < 0) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return 0;
-    }
-
-    mLength = fileSize;
-  }
-
-  return mLength;
-}
-
-namespace {
-
-class GetTypeRunnable final : public WorkerMainThreadRunnable
-{
-public:
-  GetTypeRunnable(WorkerPrivate* aWorkerPrivate,
-                  BlobImpl* aBlobImpl)
-    : WorkerMainThreadRunnable(aWorkerPrivate,
-                               NS_LITERAL_CSTRING("BlobImplFile :: GetType"))
-    , mBlobImpl(aBlobImpl)
-  {
-    MOZ_ASSERT(aBlobImpl);
-    aWorkerPrivate->AssertIsOnWorkerThread();
-  }
-
-  bool
-  MainThreadRun() override
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    nsAutoString type;
-    mBlobImpl->GetType(type);
-    return true;
-  }
-
-private:
-  ~GetTypeRunnable()
-  {}
-
-  RefPtr<BlobImpl> mBlobImpl;
-};
-
-} // anonymous namespace
-
-void
-BlobImplFile::GetType(nsAString& aType)
-{
-  aType.Truncate();
-
-  if (mContentType.IsVoid()) {
-    MOZ_ASSERT(mWholeFile,
-               "Should only use lazy ContentType when using the whole file");
-
-    if (!NS_IsMainThread()) {
-      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-      if (!workerPrivate) {
-        // I have no idea in which thread this method is called. We cannot
-        // return any valid value.
-        return;
-      }
-
-      RefPtr<GetTypeRunnable> runnable =
-        new GetTypeRunnable(workerPrivate, this);
-
-      ErrorResult rv;
-      runnable->Dispatch(Terminating, rv);
-      if (NS_WARN_IF(rv.Failed())) {
-        rv.SuppressException();
-      }
-      return;
-    }
-
-    nsresult rv;
-    nsCOMPtr<nsIMIMEService> mimeService =
-      do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-
-    nsAutoCString mimeType;
-    rv = mimeService->GetTypeFromFile(mFile, mimeType);
-    if (NS_FAILED(rv)) {
-      mimeType.Truncate();
-    }
-
-    AppendUTF8toUTF16(mimeType, mContentType);
-    mContentType.SetIsVoid(false);
-  }
-
-  aType = mContentType;
-}
-
-int64_t
-BlobImplFile::GetLastModified(ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIsFile, "Should only be called on files");
-  if (BlobImplBase::IsDateUnknown()) {
-    PRTime msecs;
-    aRv = mFile->GetLastModifiedTime(&msecs);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return 0;
-    }
-
-    mLastModificationDate = msecs;
-  }
-
-  return mLastModificationDate;
-}
-
-void
-BlobImplFile::SetLastModified(int64_t aLastModified)
-{
-  MOZ_CRASH("SetLastModified of a real file is not allowed!");
-}
-
-const uint32_t sFileStreamFlags =
-  nsIFileInputStream::CLOSE_ON_EOF |
-  nsIFileInputStream::REOPEN_ON_REWIND |
-  nsIFileInputStream::DEFER_OPEN |
-  nsIFileInputStream::SHARE_DELETE;
-
-void
-BlobImplFile::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mWholeFile) {
-    aRv = NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags);
-    return;
-  }
-
-  aRv = NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
-                                          -1, -1, sFileStreamFlags);
-}
-
-bool
-BlobImplFile::IsDirectory() const
-{
-  bool isDirectory = false;
-  if (mFile) {
-    mFile->IsDirectory(&isDirectory);
-  }
-  return isDirectory;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// EmptyBlobImpl implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
-
-already_AddRefed<BlobImpl>
-EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
-                           const nsAString& aContentType,
-                           ErrorResult& aRv)
-{
-  MOZ_ASSERT(!aStart && !aLength);
-  RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-
-  DebugOnly<bool> isMutable;
-  MOZ_ASSERT(NS_SUCCEEDED(impl->GetMutable(&isMutable)));
-  MOZ_ASSERT(!isMutable);
-
-  return impl.forget();
-}
-
-void
-EmptyBlobImpl::GetInternalStream(nsIInputStream** aStream,
-                                 ErrorResult& aRv)
-{
-  if (NS_WARN_IF(!aStream)) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
-    return;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplString implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplString, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplString>
-BlobImplString::Create(const nsACString& aData, const nsAString& aContentType)
-{
-  RefPtr<BlobImplString> blobImpl = new BlobImplString(aData, aContentType);
-  RegisterWeakMemoryReporter(blobImpl);
-  return blobImpl.forget();
-}
-
-BlobImplString::BlobImplString(const nsACString& aData,
-                               const nsAString& aContentType)
-  : BlobImplBase(aContentType, aData.Length())
-  , mData(aData)
-{
-}
-
-BlobImplString::~BlobImplString()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplString::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplString(Substring(mData, aStart, aLength),
-                       aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplString::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  aRv = NS_NewCStringInputStream(aStream, mData);
-}
-
-NS_IMETHODIMP
-BlobImplString::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/string", KIND_HEAP, UNITS_BYTES,
-    mData.SizeOfExcludingThisIfUnshared(MallocSizeOf),
-    "Memory used to back a File/Blob based on a string.");
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplMemory implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplMemory, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplMemory::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType,
-                            ErrorResult& aRv)
-{
-  RefPtr<BlobImpl> impl =
-    new BlobImplMemory(this, aStart, aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplMemory::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  if (mLength > INT32_MAX) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aRv = DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
-}
-
-/* static */ StaticMutex
-BlobImplMemory::DataOwner::sDataOwnerMutex;
-
-/* static */ StaticAutoPtr<LinkedList<BlobImplMemory::DataOwner>>
-BlobImplMemory::DataOwner::sDataOwners;
-
-/* static */ bool
-BlobImplMemory::DataOwner::sMemoryReporterRegistered = false;
-
-MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
-
-class BlobImplMemoryDataOwnerMemoryReporter final
-  : public nsIMemoryReporter
-{
-  ~BlobImplMemoryDataOwnerMemoryReporter() {}
-
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
-                            nsISupports* aData, bool aAnonymize) override
-  {
-    typedef BlobImplMemory::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);
-
-      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);
-
-        nsAutoCString digestString;
-        for (size_t i = 0; i < sizeof(digest); i++) {
-          digestString.AppendPrintf("%02x", digest[i]);
-        }
-
-        aHandleReport->Callback(
-          /* process */ NS_LITERAL_CSTRING(""),
-          nsPrintfCString(
-            "explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
-            owner->mLength, aAnonymize ? "<anonymized>" : digestString.get()),
-          KIND_HEAP, UNITS_BYTES, size,
-          nsPrintfCString(
-            "Memory used to back a memory file of length %llu bytes.  The file "
-            "has a sha1 of %s.\n\n"
-            "Note that the allocator may round up a memory file's length -- "
-            "that is, an N-byte memory file may take up more than N bytes of "
-            "memory.",
-            owner->mLength, digestString.get()),
-          aData);
-      }
-    }
-
-    if (smallObjectsTotal > 0) {
-      aHandleReport->Callback(
-        /* process */ NS_LITERAL_CSTRING(""),
-        NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
-        KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
-        nsPrintfCString(
-          "Memory used to back small memory files (i.e. those taking up less "
-          "than %zu bytes of memory each).\n\n"
-          "Note that the allocator may round up a memory file's length -- "
-          "that is, an N-byte memory file may take up more than N bytes of "
-          "memory.", LARGE_OBJECT_MIN_SIZE),
-        aData);
-    }
-
-    return NS_OK;
-  }
-};
-
-NS_IMPL_ISUPPORTS(BlobImplMemoryDataOwnerMemoryReporter, nsIMemoryReporter)
-
-/* static */ void
-BlobImplMemory::DataOwner::EnsureMemoryReporterRegistered()
-{
-  sDataOwnerMutex.AssertCurrentThreadOwns();
-  if (sMemoryReporterRegistered) {
-    return;
-  }
-
-  RegisterStrongMemoryReporter(new BlobImplMemoryDataOwnerMemoryReporter());
-
-  sMemoryReporterRegistered = true;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplTemporaryBlob implementation
-
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplTemporaryBlob, BlobImpl)
-
-already_AddRefed<BlobImpl>
-BlobImplTemporaryBlob::CreateSlice(uint64_t aStart, uint64_t aLength,
-                                   const nsAString& aContentType,
-                                   ErrorResult& aRv)
-{
-  if (aStart + aLength > mLength) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplTemporaryBlob(this, aStart + mStartPos,
-                              aLength, aContentType);
-  return impl.forget();
-}
-
-void
-BlobImplTemporaryBlob::GetInternalStream(nsIInputStream** aStream,
-                                         ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> stream =
-    new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength);
-  stream.forget(aStream);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// BlobImplStream implementation
-
-NS_IMPL_ISUPPORTS_INHERITED(BlobImplStream, BlobImpl, nsIMemoryReporter)
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aContentType,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aContentType, aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-/* static */ already_AddRefed<BlobImplStream>
-BlobImplStream::Create(nsIInputStream* aInputStream,
-                       const nsAString& aName,
-                       const nsAString& aContentType,
-                       int64_t aLastModifiedDate,
-                       uint64_t aLength)
-{
-  RefPtr<BlobImplStream> blobImplStream =
-    new BlobImplStream(aInputStream, aName, aContentType, aLastModifiedDate,
-                       aLength);
-  blobImplStream->MaybeRegisterMemoryReporter();
-  return blobImplStream.forget();
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aContentType,
-                               uint64_t aLength)
-  : BlobImplBase(aContentType, aLength)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(BlobImplStream* aOther,
-                               const nsAString& aContentType,
-                               uint64_t aStart, uint64_t aLength)
-  : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
-  , mInputStream(new SlicedInputStream(aOther->mInputStream, aStart, aLength))
-{
-  mImmutable = true;
-}
-
-BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
-                               const nsAString& aName,
-                               const nsAString& aContentType,
-                               int64_t aLastModifiedDate,
-                               uint64_t aLength)
-  : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
-  , mInputStream(aInputStream)
-{
-  mImmutable = true;
-}
-
-BlobImplStream::~BlobImplStream()
-{
-  UnregisterWeakMemoryReporter(this);
-}
-
-void
-BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
-{
-  nsCOMPtr<nsIInputStream> clonedStream;
-  nsCOMPtr<nsIInputStream> replacementStream;
-
-  aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
-                            getter_AddRefs(replacementStream));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  if (replacementStream) {
-    mInputStream = replacementStream.forget();
-  }
-
-  clonedStream.forget(aStream);
-}
-
-already_AddRefed<BlobImpl>
-BlobImplStream::CreateSlice(uint64_t aStart, uint64_t aLength,
-                            const nsAString& aContentType, ErrorResult& aRv)
-{
-  if (!aLength) {
-    RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
-    return impl.forget();
-  }
-
-  RefPtr<BlobImpl> impl =
-    new BlobImplStream(this, aContentType, aStart, aLength);
-  return impl.forget();
-}
-
-void
-BlobImplStream::MaybeRegisterMemoryReporter()
-{
-  // We report only stringInputStream.
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return;
-  }
-
-  RegisterWeakMemoryReporter(this);
-}
-
-NS_IMETHODIMP
-BlobImplStream::CollectReports(nsIHandleReportCallback* aHandleReport,
-                               nsISupports* aData, bool aAnonymize)
-{
-  nsCOMPtr<nsIStringInputStream> stringInputStream =
-    do_QueryInterface(mInputStream);
-  if (!stringInputStream) {
-    return NS_OK;
-  }
-
-  MOZ_COLLECT_REPORT(
-    "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
-    stringInputStream->SizeOfIncludingThis(MallocSizeOf),
-    "Memory used to back a File/Blob based on an input stream.");
-
-  return NS_OK;
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/file/File.h
+++ b/dom/file/File.h
@@ -2,164 +2,28 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_File_h
 #define mozilla_dom_File_h
 
-#include "mozilla/Attributes.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/GuardObjects.h"
-#include "mozilla/LinkedList.h"
-#include "mozilla/StaticMutex.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/Blob.h"
 #include "mozilla/dom/Date.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsCOMPtr.h"
-#include "nsIDOMBlob.h"
-#include "nsIFile.h"
-#include "nsIMemoryReporter.h"
-#include "nsIMutable.h"
-#include "nsIXMLHttpRequest.h"
-#include "nsString.h"
-#include "nsTemporaryFileInputStream.h"
-#include "nsWrapperCache.h"
-#include "nsWeakReference.h"
 
 class nsIFile;
-class nsIInputStream;
-
-#define BLOBIMPL_IID \
-  { 0xbccb3275, 0x6778, 0x4ac5, \
-    { 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
 
 namespace mozilla {
 namespace dom {
 
-struct BlobPropertyBag;
 struct ChromeFilePropertyBag;
 struct FilePropertyBag;
-class BlobImpl;
-class File;
-class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
 class Promise;
 
-class Blob : public nsIDOMBlob
-           , public nsIXHRSendable
-           , public nsIMutable
-           , public nsSupportsWeakReference
-           , public nsWrapperCache
-{
-public: