Backed out changeset 22c00a19e267 (bug 1534712) for causing test_bug536567_perwindowpb.html, browser_jsonview_save_json.js, browser_bookmark_backup_export_import.js to perma fail CLOSED TREE
authorCiure Andrei <aciure@mozilla.com>
Fri, 19 Apr 2019 05:57:19 +0300
changeset 470145 bcd124c140a275c26c764c1793f4b036a37c639f
parent 470144 41f1dcbe9caab2d6c9b9407ec60bd83928d17c08
child 470146 cb9a0420ac32c5e52f52d1b4f3c18a8065935b68
push id112843
push useraiakab@mozilla.com
push dateFri, 19 Apr 2019 09:50:22 +0000
treeherdermozilla-inbound@c06f27cbfe40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1534712
milestone68.0a1
backs out22c00a19e267d91446352bff4d39d70a1280b20c
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 22c00a19e267 (bug 1534712) for causing test_bug536567_perwindowpb.html, browser_jsonview_save_json.js, browser_bookmark_backup_export_import.js to perma fail CLOSED TREE
dom/file/FileBlobImpl.cpp
dom/file/FileBlobImpl.h
dom/file/FileCreatorHelper.cpp
dom/file/FileCreatorHelper.h
dom/file/MultipartBlobImpl.cpp
dom/file/MultipartBlobImpl.h
dom/file/ipc/FileCreatorChild.cpp
dom/file/ipc/FileCreatorChild.h
dom/file/ipc/FileCreatorParent.cpp
dom/file/ipc/FileCreatorParent.h
dom/file/ipc/PFileCreator.ipdl
dom/file/ipc/PTemporaryIPCBlob.ipdl
dom/file/ipc/moz.build
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
ipc/glue/BackgroundChildImpl.cpp
ipc/glue/BackgroundChildImpl.h
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundParentImpl.h
ipc/glue/PBackground.ipdl
ipc/ipdl/ipdl/direct_call.py
modules/libpref/init/StaticPrefList.h
--- a/dom/file/FileBlobImpl.cpp
+++ b/dom/file/FileBlobImpl.cpp
@@ -17,97 +17,86 @@
 
 namespace mozilla {
 namespace dom {
 
 FileBlobImpl::FileBlobImpl(nsIFile* aFile)
     : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), EmptyString(),
                    EmptyString(), UINT64_MAX, INT64_MAX),
       mFile(aFile),
-      mFileId(-1),
       mWholeFile(true),
-      mHasEmptyMozFullPath(false) {
+      mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
   // Lazily get the content type and size
   mContentType.SetIsVoid(true);
   mFile->GetLeafName(mName);
 }
 
 FileBlobImpl::FileBlobImpl(const nsAString& aName,
                            const nsAString& aContentType, uint64_t aLength,
                            nsIFile* aFile)
     : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
                    aLength, UINT64_MAX),
       mFile(aFile),
-      mFileId(-1),
       mWholeFile(true),
-      mHasEmptyMozFullPath(false) {
+      mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
 }
 
 FileBlobImpl::FileBlobImpl(const nsAString& aName,
                            const nsAString& aContentType, uint64_t aLength,
                            nsIFile* aFile, int64_t aLastModificationDate)
     : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
                    aLength, aLastModificationDate),
       mFile(aFile),
-      mFileId(-1),
       mWholeFile(true),
-      mHasEmptyMozFullPath(false) {
+      mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
 }
 
 FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
                            const nsAString& aContentType,
                            const nsAString& aBlobImplType)
     : BaseBlobImpl(aBlobImplType, aName, aContentType, UINT64_MAX, INT64_MAX),
       mFile(aFile),
-      mFileId(-1),
       mWholeFile(true),
-      mHasEmptyMozFullPath(false) {
+      mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
   if (aContentType.IsEmpty()) {
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
   }
 }
 
 FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
                            uint64_t aLength, const nsAString& aContentType)
     : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aContentType,
                    aOther->mStart + aStart, aLength),
       mFile(aOther->mFile),
-      mFileId(-1),
       mWholeFile(false),
-      mHasEmptyMozFullPath(false) {
+      mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
   mImmutable = aOther->mImmutable;
 }
 
 already_AddRefed<BlobImpl> FileBlobImpl::CreateSlice(
     uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
     ErrorResult& aRv) {
   RefPtr<BlobImpl> impl = new FileBlobImpl(this, aStart, aLength, aContentType);
   return impl.forget();
 }
 
 void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
                                           ErrorResult& aRv) const {
   MOZ_ASSERT(mIsFile, "Should only be called on files");
-
-  if (mHasEmptyMozFullPath) {
-    aFilename.Truncate();
-    return;
-  }
-
   aRv = mFile->GetPath(aFilename);
 }
 
 uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) {
   if (BaseBlobImpl::IsSizeUnknown()) {
     MOZ_ASSERT(mWholeFile,
                "Should only use lazy size when using the whole file");
     int64_t fileSize;
@@ -211,16 +200,20 @@ int64_t FileBlobImpl::GetLastModified(Er
     }
 
     mLastModificationDate = msecs;
   }
 
   return mLastModificationDate;
 }
 
+void FileBlobImpl::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 FileBlobImpl::CreateInputStream(nsIInputStream** aStream,
                                      ErrorResult& aRv) {
   nsCOMPtr<nsIInputStream> stream;
   aRv = NS_NewLocalFileInputStream(getter_AddRefs(stream), mFile, -1, -1,
--- a/dom/file/FileBlobImpl.h
+++ b/dom/file/FileBlobImpl.h
@@ -32,16 +32,17 @@ class FileBlobImpl : public BaseBlobImpl
   FileBlobImpl(
       nsIFile* aFile, const nsAString& aName, const nsAString& aContentType,
       const nsAString& aBlobImplType = NS_LITERAL_STRING("FileBlobImpl"));
 
   // 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 CreateInputStream(nsIInputStream** aInputStream,
                                  ErrorResult& aRv) override;
 
   virtual bool IsDirectory() const override;
 
   // We always have size and date for this kind of blob.
@@ -51,36 +52,29 @@ class FileBlobImpl : public BaseBlobImpl
   void SetName(const nsAString& aName) { mName = aName; }
 
   void SetType(const nsAString& aType) { mContentType = aType; }
 
   int64_t GetFileId() override { return mFileId; }
 
   void SetFileId(int64_t aFileId) { mFileId = aFileId; }
 
-  void SetEmptyMozFullPath() { mHasEmptyMozFullPath = true; }
-
  protected:
   virtual ~FileBlobImpl() = default;
 
   // Create slice
   FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart, uint64_t aLength,
                const nsAString& aContentType);
 
   virtual already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart,
                                                  uint64_t aLength,
                                                  const nsAString& aContentType,
                                                  ErrorResult& aRv) override;
 
   nsCOMPtr<nsIFile> mFile;
+  bool mWholeFile;
   int64_t mFileId;
-  bool mWholeFile;
-
-  // When this is set to true, mozFullPath is returned as an empty string. This
-  // is useful in case the file doesn't exist (yet). See:
-  // FileCreatorHelper::CreateFile and aExistenceCheck.
-  bool mHasEmptyMozFullPath;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_FileBlobImpl_h
--- a/dom/file/FileCreatorHelper.cpp
+++ b/dom/file/FileCreatorHelper.cpp
@@ -2,26 +2,23 @@
 /* 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 "FileCreatorHelper.h"
 
 #include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/FileBinding.h"
-#include "mozilla/dom/ipc/FileCreatorChild.h"
-#include "mozilla/ipc/BackgroundChild.h"
-#include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/StaticPrefs.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
-#include "nsProxyRelease.h"
 #include "nsIFile.h"
 
 // Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
 // replaced by FileCreatorHelper#CreateFileW.
 #ifdef CreateFile
 #  undef CreateFile
 #endif
 
@@ -34,38 +31,173 @@ already_AddRefed<Promise> FileCreatorHel
     const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv) {
   MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
 
   RefPtr<Promise> promise = Promise::Create(aGlobalObject, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
-  nsAutoString path;
-  aRv = aFile->GetPath(path);
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobalObject);
+
+  // Parent process
+
+  if (XRE_IsParentProcess()) {
+    RefPtr<File> file =
+        CreateFileInternal(window, aFile, aBag, aIsFromNsIFile, aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+    promise->MaybeResolve(file);
+    return promise.forget();
+  }
+
+  // Content process.
+
+  ContentChild* cc = ContentChild::GetSingleton();
+  if (!cc) {
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return promise.forget();
+  }
+
+  if (!cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE) &&
+      !Preferences::GetBool("dom.file.createInChild", false)) {
+    // If this pref is not set and the request is received by the parent
+    // process, this child is killed for security reason.
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return promise.forget();
+  }
+
+  RefPtr<FileCreatorHelper> helper = new FileCreatorHelper(promise, window);
+
+  // The request is sent to the parent process and it's kept alive by
+  // ContentChild.
+  helper->SendRequest(aFile, aBag, aIsFromNsIFile, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
-  // Register this component to PBackground.
-  mozilla::ipc::PBackgroundChild* actorChild =
-      mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
-  if (NS_WARN_IF(!actorChild)) {
-    aRv.Throw(NS_ERROR_FAILURE);
+  return promise.forget();
+}
+
+/* static */
+already_AddRefed<File> FileCreatorHelper::CreateFileInternal(
+    nsPIDOMWindowInner* aWindow, nsIFile* aFile,
+    const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv) {
+  bool lastModifiedPassed = false;
+  int64_t lastModified = 0;
+  if (aBag.mLastModified.WasPassed()) {
+    lastModifiedPassed = true;
+    lastModified = aBag.mLastModified.Value();
+  }
+
+  RefPtr<BlobImpl> blobImpl;
+  aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
+                       lastModified, aBag.mExistenceCheck, aIsFromNsIFile,
+                       getter_AddRefs(blobImpl));
+  if (aRv.Failed()) {
     return nullptr;
   }
 
-  Maybe<int64_t> lastModified;
-  if (aBag.mLastModified.WasPassed()) {
-    lastModified.emplace(aBag.mLastModified.Value());
+  RefPtr<File> file = File::Create(aWindow, blobImpl);
+  return file.forget();
+}
+
+FileCreatorHelper::FileCreatorHelper(Promise* aPromise,
+                                     nsPIDOMWindowInner* aWindow)
+    : mPromise(aPromise), mWindow(aWindow) {
+  MOZ_ASSERT(aPromise);
+}
+
+FileCreatorHelper::~FileCreatorHelper() {}
+
+void FileCreatorHelper::SendRequest(nsIFile* aFile,
+                                    const ChromeFilePropertyBag& aBag,
+                                    bool aIsFromNsIFile, ErrorResult& aRv) {
+  MOZ_ASSERT(aFile);
+
+  ContentChild* cc = ContentChild::GetSingleton();
+  if (NS_WARN_IF(!cc)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  nsID uuid;
+  aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  nsAutoString path;
+  aRv = aFile->GetPath(path);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
+                          aBag.mLastModified, aBag.mExistenceCheck,
+                          aIsFromNsIFile);
+}
+
+void FileCreatorHelper::ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv) {
+  if (NS_FAILED(aRv)) {
+    mPromise->MaybeReject(aRv);
+    return;
   }
 
-  mozilla::ipc::PFileCreatorChild* actor =
-      actorChild->SendPFileCreatorConstructor(
-          path, aBag.mType, aBag.mName, lastModified, aBag.mExistenceCheck,
-          aIsFromNsIFile);
+  RefPtr<File> file = File::Create(mWindow, aBlobImpl);
+  mPromise->MaybeResolve(file);
+}
+
+/* static */
+nsresult FileCreatorHelper::CreateBlobImplForIPC(
+    const nsAString& aPath, const nsAString& aType, const nsAString& aName,
+    bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
+    bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
+  nsCOMPtr<nsIFile> file;
+  nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
+                        aExistenceCheck, aIsFromNsIFile, aBlobImpl);
+}
+
+/* static */
+nsresult FileCreatorHelper::CreateBlobImpl(
+    nsIFile* aFile, const nsAString& aType, const nsAString& aName,
+    bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
+    bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
+  if (!aExistenceCheck) {
+    RefPtr<FileBlobImpl> impl = new FileBlobImpl(aFile);
 
-  static_cast<FileCreatorChild*>(actor)->SetPromise(promise);
-  return promise.forget();
+    if (!aName.IsEmpty()) {
+      impl->SetName(aName);
+    }
+
+    if (!aType.IsEmpty()) {
+      impl->SetType(aType);
+    }
+
+    if (aLastModifiedPassed) {
+      impl->SetLastModified(aLastModified);
+    }
+
+    impl.forget(aBlobImpl);
+    return NS_OK;
+  }
+
+  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
+  nsresult rv = impl->InitializeChromeFile(
+      aFile, aType, aName, aLastModifiedPassed, aLastModified, aIsFromNsIFile);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  MOZ_ASSERT(impl->IsFile());
+
+  impl.forget(aBlobImpl);
+  return NS_OK;
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/file/FileCreatorHelper.h
+++ b/dom/file/FileCreatorHelper.h
@@ -15,28 +15,60 @@
 // Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
 // replaced by FileCreatorHelper#CreateFileW.
 #ifdef CreateFile
 #  undef CreateFile
 #endif
 
 class nsIFile;
 class nsIGlobalObject;
+class nsPIDOMWindowInner;
 
 namespace mozilla {
 namespace dom {
 
 struct ChromeFilePropertyBag;
 class Promise;
+class File;
 
 class FileCreatorHelper final {
  public:
+  NS_INLINE_DECL_REFCOUNTING(FileCreatorHelper);
+
   static already_AddRefed<Promise> CreateFile(nsIGlobalObject* aGlobalObject,
                                               nsIFile* aFile,
                                               const ChromeFilePropertyBag& aBag,
                                               bool aIsFromNsIFile,
                                               ErrorResult& aRv);
+
+  void ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv);
+
+  // For IPC only
+  static nsresult CreateBlobImplForIPC(
+      const nsAString& aPath, const nsAString& aType, const nsAString& aName,
+      bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
+      bool aIsFromNsIFile, BlobImpl** aBlobImpl);
+
+ private:
+  static already_AddRefed<File> CreateFileInternal(
+      nsPIDOMWindowInner* aWindow, nsIFile* aFile,
+      const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv);
+
+  static nsresult CreateBlobImpl(nsIFile* aFile, const nsAString& aType,
+                                 const nsAString& aName,
+                                 bool aLastModifiedPassed,
+                                 int64_t aLastModified, bool aExistenceCheck,
+                                 bool aIsFromNsIFile, BlobImpl** aBlobImpl);
+
+  FileCreatorHelper(Promise* aPromise, nsPIDOMWindowInner* aWindow);
+  ~FileCreatorHelper();
+
+  void SendRequest(nsIFile* aFile, const ChromeFilePropertyBag& aBag,
+                   bool aIsFromNsIFile, ErrorResult& aRv);
+
+  RefPtr<Promise> mPromise;
+  nsCOMPtr<nsPIDOMWindowInner> mWindow;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_FileCreatorHelper_h
--- a/dom/file/MultipartBlobImpl.cpp
+++ b/dom/file/MultipartBlobImpl.cpp
@@ -269,16 +269,32 @@ void MultipartBlobImpl::SetLengthAndModi
     // could fail.
     mLastModificationDate = nsRFPService::ReduceTimePrecisionAsUSecs(
         lastModifiedSet ? lastModified * PR_USEC_PER_MSEC : JS_Now(), 0);
     // mLastModificationDate is an absolute timestamp so we supply a zero
     // context mix-in
   }
 }
 
+void MultipartBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
+                                               ErrorResult& aRv) const {
+  if (!mIsFromNsIFile || mBlobImpls.Length() == 0) {
+    BaseBlobImpl::GetMozFullPathInternal(aFilename, aRv);
+    return;
+  }
+
+  BlobImpl* blobImpl = mBlobImpls.ElementAt(0).get();
+  if (!blobImpl) {
+    BaseBlobImpl::GetMozFullPathInternal(aFilename, aRv);
+    return;
+  }
+
+  blobImpl->GetMozFullPathInternal(aFilename, aRv);
+}
+
 nsresult MultipartBlobImpl::SetMutable(bool aMutable) {
   nsresult rv;
 
   // This looks a little sketchy since BlobImpl objects are supposed to be
   // threadsafe. However, we try to enforce that all BlobImpl objects must be
   // set to immutable *before* being passed to another thread, so this should
   // be safe.
   if (!aMutable && !mImmutable && !mBlobImpls.IsEmpty()) {
@@ -296,16 +312,92 @@ nsresult MultipartBlobImpl::SetMutable(b
     return rv;
   }
 
   MOZ_ASSERT_IF(!aMutable, mImmutable);
 
   return NS_OK;
 }
 
+nsresult MultipartBlobImpl::InitializeChromeFile(
+    nsIFile* aFile, const nsAString& aType, const nsAString& aName,
+    bool aLastModifiedPassed, int64_t aLastModified, bool aIsFromNsIFile) {
+  MOZ_ASSERT(!mImmutable, "Something went wrong ...");
+  if (mImmutable) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  mName = aName;
+  mContentType = aType;
+  mIsFromNsIFile = aIsFromNsIFile;
+
+  bool exists;
+  nsresult rv = aFile->Exists(&exists);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (!exists) {
+    return NS_ERROR_FILE_NOT_FOUND;
+  }
+
+  bool isDir;
+  rv = aFile->IsDirectory(&isDir);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (isDir) {
+    return NS_ERROR_FILE_IS_DIRECTORY;
+  }
+
+  if (mName.IsEmpty()) {
+    aFile->GetLeafName(mName);
+  }
+
+  RefPtr<File> blob = File::CreateFromFile(nullptr, aFile);
+
+  // Pre-cache size.
+  ErrorResult error;
+  blob->GetSize(error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.StealNSResult();
+  }
+
+  // Pre-cache modified date.
+  blob->GetLastModified(error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.StealNSResult();
+  }
+
+  // XXXkhuey this is terrible
+  if (mContentType.IsEmpty()) {
+    blob->GetType(mContentType);
+  }
+
+  BlobSet blobSet;
+  rv = blobSet.AppendBlobImpl(static_cast<File*>(blob.get())->Impl());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  mBlobImpls = blobSet.GetBlobImpls();
+
+  SetLengthAndModifiedDate(error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.StealNSResult();
+  }
+
+  if (aLastModifiedPassed) {
+    SetLastModified(aLastModified);
+  }
+
+  return NS_OK;
+}
+
 bool MultipartBlobImpl::MayBeClonedToOtherThreads() const {
   for (uint32_t i = 0; i < mBlobImpls.Length(); ++i) {
     if (!mBlobImpls[i]->MayBeClonedToOtherThreads()) {
       return false;
     }
   }
 
   return true;
--- a/dom/file/MultipartBlobImpl.h
+++ b/dom/file/MultipartBlobImpl.h
@@ -27,43 +27,53 @@ class MultipartBlobImpl final : public B
   // Create as a blob
   static already_AddRefed<MultipartBlobImpl> Create(
       nsTArray<RefPtr<BlobImpl>>&& aBlobImpls, const nsAString& aContentType,
       ErrorResult& aRv);
 
   // Create as a file to be later initialized
   explicit MultipartBlobImpl(const nsAString& aName)
       : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
-                     EmptyString(), UINT64_MAX) {}
+                     EmptyString(), UINT64_MAX),
+        mIsFromNsIFile(false) {}
 
   // Create as a blob to be later initialized
   MultipartBlobImpl()
       : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), EmptyString(),
-                     UINT64_MAX) {}
+                     UINT64_MAX),
+        mIsFromNsIFile(false) {}
 
   void InitializeBlob(ErrorResult& aRv);
 
   void InitializeBlob(const Sequence<Blob::BlobPart>& aData,
                       const nsAString& aContentType, bool aNativeEOL,
                       ErrorResult& aRv);
 
+  nsresult InitializeChromeFile(nsIFile* aData, const nsAString& aType,
+                                const nsAString& aName,
+                                bool aLastModifiedPassed, int64_t aLastModified,
+                                bool aIsFromNsIFile);
+
   virtual already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart,
                                                  uint64_t aLength,
                                                  const nsAString& aContentType,
                                                  ErrorResult& aRv) override;
 
   virtual uint64_t GetSize(ErrorResult& aRv) override { return mLength; }
 
   virtual void CreateInputStream(nsIInputStream** aInputStream,
                                  ErrorResult& aRv) override;
 
   virtual const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const override {
     return mBlobImpls.Length() ? &mBlobImpls : nullptr;
   }
 
+  virtual void GetMozFullPathInternal(nsAString& aFullPath,
+                                      ErrorResult& aRv) const override;
+
   virtual nsresult SetMutable(bool aMutable) override;
 
   void SetName(const nsAString& aName) { mName = aName; }
 
   virtual bool MayBeClonedToOtherThreads() const override;
 
   size_t GetAllocationSize() const override;
   size_t GetAllocationSize(
@@ -71,27 +81,30 @@ class MultipartBlobImpl final : public B
 
   void GetBlobImplType(nsAString& aBlobImplType) const override;
 
  protected:
   MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
                     const nsAString& aName, const nsAString& aContentType)
       : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
                      aContentType, UINT64_MAX),
-        mBlobImpls(std::move(aBlobImpls)) {}
+        mBlobImpls(std::move(aBlobImpls)),
+        mIsFromNsIFile(false) {}
 
   MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
                     const nsAString& aContentType)
       : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aContentType,
                      UINT64_MAX),
-        mBlobImpls(std::move(aBlobImpls)) {}
+        mBlobImpls(std::move(aBlobImpls)),
+        mIsFromNsIFile(false) {}
 
   virtual ~MultipartBlobImpl() {}
 
   void SetLengthAndModifiedDate(ErrorResult& aRv);
 
   nsTArray<RefPtr<BlobImpl>> mBlobImpls;
+  bool mIsFromNsIFile;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_MultipartBlobImpl_h
deleted file mode 100644
--- a/dom/file/ipc/FileCreatorChild.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- 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 "FileCreatorChild.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/IPCBlobUtils.h"
-
-namespace mozilla {
-namespace dom {
-
-FileCreatorChild::FileCreatorChild() = default;
-
-FileCreatorChild::~FileCreatorChild() { MOZ_ASSERT(!mPromise); }
-
-void FileCreatorChild::SetPromise(Promise* aPromise) {
-  MOZ_ASSERT(aPromise);
-  MOZ_ASSERT(!mPromise);
-
-  mPromise = aPromise;
-}
-
-mozilla::ipc::IPCResult FileCreatorChild::Recv__delete__(
-    const FileCreationResult& aResult) {
-  MOZ_ASSERT(mPromise);
-
-  RefPtr<Promise> promise;
-  promise.swap(mPromise);
-
-  if (aResult.type() == FileCreationResult::TFileCreationErrorResult) {
-    promise->MaybeReject(aResult.get_FileCreationErrorResult().errorCode());
-    return IPC_OK();
-  }
-
-  MOZ_ASSERT(aResult.type() == FileCreationResult::TFileCreationSuccessResult);
-
-  RefPtr<dom::BlobImpl> impl = dom::IPCBlobUtils::Deserialize(
-      aResult.get_FileCreationSuccessResult().blob());
-
-  RefPtr<File> file = File::Create(promise->GetParentObject(), impl);
-  promise->MaybeResolve(file);
-  return IPC_OK();
-}
-
-void FileCreatorChild::ActorDestroy(ActorDestroyReason aWhy) {
-  if (mPromise) {
-    mPromise->MaybeReject(NS_ERROR_FAILURE);
-    mPromise = nullptr;
-  }
-};
-
-}  // namespace dom
-}  // namespace mozilla
deleted file mode 100644
--- a/dom/file/ipc/FileCreatorChild.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- 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_ipc_FileCreatorChild_h
-#define mozilla_dom_ipc_FileCreatorChild_h
-
-#include "mozilla/ipc/PFileCreatorChild.h"
-
-namespace mozilla {
-namespace dom {
-
-class FileCreatorChild final : public mozilla::ipc::PFileCreatorChild {
-  friend class mozilla::ipc::PFileCreatorChild;
-
- public:
-  FileCreatorChild();
-  ~FileCreatorChild();
-
-  void SetPromise(Promise* aPromise);
-
- private:
-  mozilla::ipc::IPCResult Recv__delete__(
-      const FileCreationResult& aResult) override;
-
-  void ActorDestroy(ActorDestroyReason aWhy) override;
-
-  RefPtr<Promise> mPromise;
-};
-
-}  // namespace dom
-}  // namespace mozilla
-
-#endif  // mozilla_dom_ipc_FileCreatorChild_h
deleted file mode 100644
--- a/dom/file/ipc/FileCreatorParent.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- 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 "FileCreatorParent.h"
-#include "mozilla/dom/FileBlobImpl.h"
-#include "mozilla/dom/IPCBlobUtils.h"
-#include "mozilla/dom/MultipartBlobImpl.h"
-
-namespace mozilla {
-namespace dom {
-
-FileCreatorParent::FileCreatorParent()
-    : mBackgroundEventTarget(GetCurrentThreadEventTarget()), mIPCActive(true) {}
-
-FileCreatorParent::~FileCreatorParent() = default;
-
-mozilla::ipc::IPCResult FileCreatorParent::CreateAndShareFile(
-    const nsString& aFullPath, const nsString& aType, const nsString& aName,
-    const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-    const bool& aIsFromNsIFile) {
-  RefPtr<dom::BlobImpl> blobImpl;
-  nsresult rv =
-      CreateBlobImpl(aFullPath, aType, aName, aLastModified.isSome(),
-                     aLastModified.isSome() ? aLastModified.value() : 0,
-                     aExistenceCheck, aIsFromNsIFile, getter_AddRefs(blobImpl));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    Unused << Send__delete__(this, FileCreationErrorResult(rv));
-    return IPC_OK();
-  }
-
-  MOZ_ASSERT(blobImpl);
-
-  // FileBlobImpl is unable to return the correct type on this thread because
-  // nsIMIMEService is not thread-safe. We must exec the 'type' getter on
-  // main-thread before send the blob to the child actor.
-
-  RefPtr<FileCreatorParent> self = this;
-  NS_DispatchToMainThread(NS_NewRunnableFunction(
-      "FileCreatorParent::CreateAndShareFile", [self, blobImpl]() {
-        nsAutoString type;
-        blobImpl->GetType(type);
-
-        self->mBackgroundEventTarget->Dispatch(NS_NewRunnableFunction(
-            "FileCreatorParent::CreateAndShareFile return", [self, blobImpl]() {
-              if (self->mIPCActive) {
-                IPCBlob ipcBlob;
-                nsresult rv = dom::IPCBlobUtils::Serialize(
-                    blobImpl, self->Manager(), ipcBlob);
-                if (NS_WARN_IF(NS_FAILED(rv))) {
-                  Unused << Send__delete__(self, FileCreationErrorResult(rv));
-                  return;
-                }
-
-                Unused << Send__delete__(self,
-                                         FileCreationSuccessResult(ipcBlob));
-              }
-            }));
-      }));
-
-  return IPC_OK();
-}
-
-void FileCreatorParent::ActorDestroy(ActorDestroyReason aWhy) {
-  mIPCActive = false;
-}
-
-/* static */
-nsresult FileCreatorParent::CreateBlobImpl(
-    const nsAString& aPath, const nsAString& aType, const nsAString& aName,
-    bool aLastModifiedPassed, int64_t aLastModified, bool aExistenceCheck,
-    bool aIsFromNsIFile, BlobImpl** aBlobImpl) {
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  nsCOMPtr<nsIFile> file;
-  nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  if (aExistenceCheck) {
-    bool exists;
-    nsresult rv = file->Exists(&exists);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    if (!exists) {
-      return NS_ERROR_FILE_NOT_FOUND;
-    }
-
-    bool isDir;
-    rv = file->IsDirectory(&isDir);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    if (isDir) {
-      return NS_ERROR_FILE_IS_DIRECTORY;
-    }
-  }
-
-  RefPtr<FileBlobImpl> impl = new FileBlobImpl(file);
-
-  if (!aName.IsEmpty()) {
-    impl->SetName(aName);
-  }
-
-  if (!aType.IsEmpty()) {
-    impl->SetType(aType);
-  }
-
-  if (aLastModifiedPassed) {
-    impl->SetLastModified(aLastModified);
-  }
-
-  if (!aIsFromNsIFile) {
-    impl->SetEmptyMozFullPath();
-  }
-
-  impl.forget(aBlobImpl);
-  return NS_OK;
-}
-
-}  // namespace dom
-}  // namespace mozilla
deleted file mode 100644
--- a/dom/file/ipc/FileCreatorParent.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- 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_ipc_FileCreatorParent_h
-#define mozilla_dom_ipc_FileCreatorParent_h
-
-#include "mozilla/ipc/PFileCreatorParent.h"
-
-class nsIFile;
-
-namespace mozilla {
-namespace dom {
-
-class BlobImpl;
-
-class FileCreatorParent final : public mozilla::ipc::PFileCreatorParent {
- public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileCreatorParent)
-
-  FileCreatorParent();
-
-  mozilla::ipc::IPCResult CreateAndShareFile(
-      const nsString& aFullPath, const nsString& aType, const nsString& aName,
-      const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-      const bool& aIsFromNsIFile);
-
- private:
-  ~FileCreatorParent();
-
-  void ActorDestroy(ActorDestroyReason aWhy) override;
-
-  nsresult CreateBlobImpl(const nsAString& aPath, const nsAString& aType,
-                          const nsAString& aName, bool aLastModifiedPassed,
-                          int64_t aLastModified, bool aExistenceCheck,
-                          bool aIsFromNsIFile, BlobImpl** aBlobImpl);
-
-  nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
-  bool mIPCActive;
-};
-
-}  // namespace dom
-}  // namespace mozilla
-
-#endif  // mozilla_dom_ipc_FileCreatorParent_h
deleted file mode 100644
--- a/dom/file/ipc/PFileCreator.ipdl
+++ /dev/null
@@ -1,41 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-include protocol PBackground;
-include protocol PChildToParentStream;
-include protocol PFileDescriptorSet;
-include protocol PIPCBlobInputStream;
-include protocol PParentToChildStream;
-
-include IPCBlob;
-
-namespace mozilla {
-namespace ipc {
-
-struct FileCreationSuccessResult
-{
-  IPCBlob blob;
-};
-
-struct FileCreationErrorResult
-{
-  nsresult errorCode;
-};
-
-union FileCreationResult
-{
-  FileCreationSuccessResult;
-  FileCreationErrorResult;
-};
-
-protocol PFileCreator
-{
-  manager PBackground;
-
-child:
-  async __delete__(FileCreationResult aResult);
-};
-
-} // namespace ipc
-} // namespace mozilla
--- a/dom/file/ipc/PTemporaryIPCBlob.ipdl
+++ b/dom/file/ipc/PTemporaryIPCBlob.ipdl
@@ -34,10 +34,10 @@ child:
   async __delete__(IPCBlobOrError aBlobOrError);
 
 parent:
   async OperationFailed();
 
   async OperationDone(nsCString aContentType, FileDescriptor aFD);
 };
 
-} // namespace ipc
+} // namespace dom
 } // namespace mozilla
--- a/dom/file/ipc/moz.build
+++ b/dom/file/ipc/moz.build
@@ -3,51 +3,46 @@
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM: File")
 
 EXPORTS.mozilla.dom.ipc += [
-    'FileCreatorChild.h',
-    'FileCreatorParent.h',
     'IPCBlobInputStream.h',
     'IPCBlobInputStreamChild.h',
     'IPCBlobInputStreamParent.h',
     'IPCBlobInputStreamStorage.h',
     'PendingIPCBlobChild.h',
     'PendingIPCBlobParent.h',
     'TemporaryIPCBlobChild.h',
     'TemporaryIPCBlobParent.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'IPCBlobUtils.h',
 ]
 
 UNIFIED_SOURCES += [
-    'FileCreatorChild.cpp',
-    'FileCreatorParent.cpp',
     'IPCBlobInputStream.cpp',
     'IPCBlobInputStreamChild.cpp',
     'IPCBlobInputStreamParent.cpp',
     'IPCBlobInputStreamStorage.cpp',
     'IPCBlobInputStreamThread.cpp',
     'IPCBlobUtils.cpp',
     'PendingIPCBlobChild.cpp',
     'PendingIPCBlobParent.cpp',
     'TemporaryIPCBlobChild.cpp',
     'TemporaryIPCBlobParent.cpp',
 ]
 
 IPDL_SOURCES += [
     'BlobTypes.ipdlh',
     'IPCBlob.ipdlh',
-    'PFileCreator.ipdl',
     'PIPCBlobInputStream.ipdl',
     'PPendingIPCBlob.ipdl',
     'PTemporaryIPCBlob.ipdl',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/file',
     '/dom/ipc',
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -34,16 +34,17 @@
 #include "mozilla/dom/ClientOpenWindowOpActors.h"
 #include "mozilla/dom/ChildProcessMessageManager.h"
 #include "mozilla/dom/ContentProcessMessageManager.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
+#include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/JSWindowActorService.h"
 #include "mozilla/dom/LSObject.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/PLoginReputationChild.h"
 #include "mozilla/dom/PSessionStorageObserverChild.h"
 #include "mozilla/dom/PostMessageEvent.h"
@@ -3382,16 +3383,61 @@ ContentChild::AllocPSessionStorageObserv
 bool ContentChild::DeallocPSessionStorageObserverChild(
     PSessionStorageObserverChild* aActor) {
   MOZ_ASSERT(aActor);
 
   delete aActor;
   return true;
 }
 
+void ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
+                                       const nsAString& aFullPath,
+                                       const nsAString& aType,
+                                       const nsAString& aName,
+                                       const Optional<int64_t>& aLastModified,
+                                       bool aExistenceCheck,
+                                       bool aIsFromNsIFile) {
+  MOZ_ASSERT(aHelper);
+
+  bool lastModifiedPassed = false;
+  int64_t lastModified = 0;
+  if (aLastModified.WasPassed()) {
+    lastModifiedPassed = true;
+    lastModified = aLastModified.Value();
+  }
+
+  Unused << SendFileCreationRequest(
+      aUUID, nsString(aFullPath), nsString(aType), nsString(aName),
+      lastModifiedPassed, lastModified, aExistenceCheck, aIsFromNsIFile);
+  mFileCreationPending.Put(aUUID, aHelper);
+}
+
+mozilla::ipc::IPCResult ContentChild::RecvFileCreationResponse(
+    const nsID& aUUID, const FileCreationResult& aResult) {
+  FileCreatorHelper* helper = mFileCreationPending.GetWeak(aUUID);
+  if (!helper) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  if (aResult.type() == FileCreationResult::TFileCreationErrorResult) {
+    helper->ResponseReceived(nullptr,
+                             aResult.get_FileCreationErrorResult().errorCode());
+  } else {
+    MOZ_ASSERT(aResult.type() ==
+               FileCreationResult::TFileCreationSuccessResult);
+
+    RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(
+        aResult.get_FileCreationSuccessResult().blob());
+    helper->ResponseReceived(impl, NS_OK);
+  }
+
+  mFileCreationPending.Remove(aUUID);
+  return IPC_OK();
+}
+
 mozilla::ipc::IPCResult ContentChild::RecvActivate(PBrowserChild* aTab) {
   TabChild* tab = static_cast<TabChild*>(aTab);
   return tab->RecvActivate();
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvDeactivate(PBrowserChild* aTab) {
   TabChild* tab = static_cast<TabChild*>(aTab);
   return tab->RecvDeactivate();
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -72,16 +72,17 @@ namespace ipc {
 class SharedMap;
 }
 
 class AlertObserver;
 class ConsoleListener;
 class ClonedMessageData;
 class TabChild;
 class GetFilesHelperChild;
+class FileCreatorHelper;
 
 class ContentChild final : public PContentChild,
                            public nsIWindowProvider,
                            public CPOWManagerGetter,
                            public mozilla::ipc::IShmemAllocator {
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
   typedef mozilla::ipc::FileDescriptor FileDescriptor;
   typedef mozilla::ipc::PFileDescriptorSetChild PFileDescriptorSetChild;
@@ -558,16 +559,19 @@ class ContentChild final : public PConte
       const nsID& aUUID, const GetFilesResponseResult& aResult);
 
   mozilla::ipc::IPCResult RecvBlobURLRegistration(
       const nsCString& aURI, const IPCBlob& aBlob,
       const IPC::Principal& aPrincipal);
 
   mozilla::ipc::IPCResult RecvBlobURLUnregistration(const nsCString& aURI);
 
+  mozilla::ipc::IPCResult RecvFileCreationResponse(
+      const nsID& aUUID, const FileCreationResult& aResult);
+
   mozilla::ipc::IPCResult RecvRequestMemoryReport(
       const uint32_t& generation, const bool& anonymize,
       const bool& minimizeMemoryUsage, const Maybe<FileDescriptor>& DMDFile);
 
   mozilla::ipc::IPCResult RecvSetXPCOMProcessAttributes(
       const XPCOMInitData& aXPCOMInit, const StructuredCloneData& aInitialData,
       nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache,
       nsTArray<SystemFontListEntry>&& aFontList,
@@ -636,16 +640,23 @@ class ContentChild final : public PConte
    * Helper function for protocols that use the GPU process when available.
    * Overrides FatalError to just be a warning when communicating with the
    * GPU process since we don't want to crash the content process when the
    * GPU process crashes.
    */
   static void FatalErrorIfNotUsingGPUProcess(const char* const aErrorMsg,
                                              base::ProcessId aOtherPid);
 
+  // This method is used by FileCreatorHelper for the creation of a BlobImpl.
+  void FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
+                           const nsAString& aFullPath, const nsAString& aType,
+                           const nsAString& aName,
+                           const Optional<int64_t>& aLastModified,
+                           bool aExistenceCheck, bool aIsFromNsIFile);
+
   typedef std::function<void(PRFileDesc*)> AnonymousTemporaryFileCallback;
   nsresult AsyncOpenAnonymousTemporaryFile(
       const AnonymousTemporaryFileCallback& aCallback);
 
   already_AddRefed<nsIEventTarget> GetEventTargetFor(TabChild* aTabChild);
 
   mozilla::ipc::IPCResult RecvSetPluginList(
       const uint32_t& aPluginEpoch, nsTArray<PluginTag>&& aPluginTags,
@@ -787,16 +798,20 @@ class ContentChild final : public PConte
   nsCOMPtr<nsIFile> mProfileDir;
 #endif
 
   // Hashtable to keep track of the pending GetFilesHelper objects.
   // This GetFilesHelperChild objects are removed when RecvGetFilesResponse is
   // received.
   nsRefPtrHashtable<nsIDHashKey, GetFilesHelperChild> mGetFilesPendingRequests;
 
+  // Hashtable to keep track of the pending file creation.
+  // These items are removed when RecvFileCreationResponse is received.
+  nsRefPtrHashtable<nsIDHashKey, FileCreatorHelper> mFileCreationPending;
+
   nsClassHashtable<nsUint64HashKey, AnonymousTemporaryFileCallback>
       mPendingAnonymousTemporaryFiles;
 
   mozilla::Atomic<bool> mShuttingDown;
 
 #ifdef NIGHTLY_BUILD
   // NOTE: This member is atomic because it can be accessed from
   // off-main-thread.
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -42,16 +42,17 @@
 #include "mozilla/dom/BrowsingContextGroup.h"
 #include "mozilla/dom/CanonicalBrowsingContext.h"
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientOpenWindowOpActors.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/File.h"
+#include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/FileSystemSecurity.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/GeolocationBinding.h"
 #include "mozilla/dom/JSWindowActorService.h"
 #include "mozilla/dom/LocalStorageCommon.h"
 #include "mozilla/dom/MemoryReportRequest.h"
@@ -5527,16 +5528,59 @@ mozilla::ipc::IPCResult ContentParent::R
 bool ContentParent::DeallocPSessionStorageObserverParent(
     PSessionStorageObserverParent* aActor) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPSessionStorageObserverParent(aActor);
 }
 
+mozilla::ipc::IPCResult ContentParent::RecvFileCreationRequest(
+    const nsID& aID, const nsString& aFullPath, const nsString& aType,
+    const nsString& aName, const bool& aLastModifiedPassed,
+    const int64_t& aLastModified, const bool& aExistenceCheck,
+    const bool& aIsFromNsIFile) {
+  // We allow the creation of File via this IPC call only for the 'file' process
+  // or for testing.
+  if (!mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE) &&
+      !Preferences::GetBool("dom.file.createInChild", false)) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  RefPtr<BlobImpl> blobImpl;
+  nsresult rv = FileCreatorHelper::CreateBlobImplForIPC(
+      aFullPath, aType, aName, aLastModifiedPassed, aLastModified,
+      aExistenceCheck, aIsFromNsIFile, getter_AddRefs(blobImpl));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
+      return IPC_FAIL_NO_REASON(this);
+    }
+
+    return IPC_OK();
+  }
+
+  MOZ_ASSERT(blobImpl);
+
+  IPCBlob ipcBlob;
+  rv = IPCBlobUtils::Serialize(blobImpl, this, ipcBlob);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
+      return IPC_FAIL_NO_REASON(this);
+    }
+
+    return IPC_OK();
+  }
+
+  if (!SendFileCreationResponse(aID, FileCreationSuccessResult(ipcBlob))) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  return IPC_OK();
+}
+
 nsresult ContentParent::SaveRecording(nsIFile* aFile, bool* aRetval) {
   if (mRecordReplayState != eRecording) {
     *aRetval = false;
     return NS_OK;
   }
 
   PRFileDesc* prfd;
   nsresult rv = aFile->OpenNSPRFileDesc(
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1122,16 +1122,22 @@ class ContentParent final : public PCont
       const nsCString& aScope, const IPC::Principal& aPrincipal);
 
   mozilla::ipc::IPCResult RecvGetFilesRequest(const nsID& aID,
                                               const nsString& aDirectoryPath,
                                               const bool& aRecursiveFlag);
 
   mozilla::ipc::IPCResult RecvDeleteGetFilesRequest(const nsID& aID);
 
+  mozilla::ipc::IPCResult RecvFileCreationRequest(
+      const nsID& aID, const nsString& aFullPath, const nsString& aType,
+      const nsString& aName, const bool& aLastModifiedPassed,
+      const int64_t& aLastModified, const bool& aExistenceCheck,
+      const bool& aIsFromNsIFile);
+
   mozilla::ipc::IPCResult RecvAccumulateChildHistograms(
       InfallibleTArray<HistogramAccumulation>&& aAccumulations);
   mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(
       InfallibleTArray<KeyedHistogramAccumulation>&& aAccumulations);
   mozilla::ipc::IPCResult RecvUpdateChildScalars(
       InfallibleTArray<ScalarAction>&& aScalarActions);
   mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars(
       InfallibleTArray<KeyedScalarAction>&& aScalarActions);
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -198,16 +198,32 @@ struct GetFilesResponseFailure
 };
 
 union GetFilesResponseResult
 {
   GetFilesResponseSuccess;
   GetFilesResponseFailure;
 };
 
+struct FileCreationSuccessResult
+{
+  IPCBlob blob;
+};
+
+struct FileCreationErrorResult
+{
+  nsresult errorCode;
+};
+
+union FileCreationResult
+{
+  FileCreationSuccessResult;
+  FileCreationErrorResult;
+};
+
 struct BlobURLRegistrationData
 {
   nsCString url;
   IPCBlob blob;
   Principal principal;
   bool revoked;
 };
 
@@ -649,16 +665,18 @@ child:
     async BlobURLRegistration(nsCString aURI, IPCBlob aBlob,
                               Principal aPrincipal);
 
     async BlobURLUnregistration(nsCString aURI);
 
     async GMPsChanged(GMPCapabilityData[] capabilities);
 
 
+    async FileCreationResponse(nsID aID, FileCreationResult aResult);
+
     /**
      * Sending an activate message moves focus to the child.
      */
     async Activate(PBrowser aTab);
 
     async Deactivate(PBrowser aTab);
 
     async PParentToChildStream();
@@ -1183,16 +1201,21 @@ parent:
      * Notify `push-subscription-change` observers in the parent.
      */
     async NotifyPushSubscriptionChangeObservers(nsCString scope,
                                                 Principal principal);
 
      async GetFilesRequest(nsID aID, nsString aDirectory, bool aRecursiveFlag);
      async DeleteGetFilesRequest(nsID aID);
 
+     async FileCreationRequest(nsID aID, nsString aFullPath, nsString aType,
+                               nsString aName, bool lastModifiedPassed,
+                               int64_t lastModified, bool aExistenceCheck,
+                               bool aIsFromNsIFile);
+
      async StoreAndBroadcastBlobURLRegistration(nsCString url, IPCBlob blob,
                                                 Principal principal);
 
      async UnstoreAndBroadcastBlobURLUnregistration(nsCString url);
 
     /**
      * Messages for communicating child Telemetry to the parent process
      */
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -22,21 +22,19 @@
 #include "mozilla/dom/PBackgroundLSSimpleRequestChild.h"
 #include "mozilla/dom/PBackgroundSDBConnectionChild.h"
 #include "mozilla/dom/PFileSystemRequestChild.h"
 #include "mozilla/dom/EndpointForReportChild.h"
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
-#include "mozilla/dom/ipc/FileCreatorChild.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
 #include "mozilla/dom/ipc/PendingIPCBlobChild.h"
 #include "mozilla/dom/ipc/TemporaryIPCBlobChild.h"
-#include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/quota/PQuotaChild.h"
 #include "mozilla/dom/RemoteWorkerChild.h"
 #include "mozilla/dom/RemoteWorkerServiceChild.h"
 #include "mozilla/dom/SharedWorkerChild.h"
 #include "mozilla/dom/StorageIPC.h"
 #include "mozilla/dom/GamepadEventChannelChild.h"
 #include "mozilla/dom/GamepadTestChannelChild.h"
 #include "mozilla/dom/LocalStorage.h"
@@ -376,28 +374,16 @@ PTemporaryIPCBlobChild* BackgroundChildI
 
 bool BackgroundChildImpl::DeallocPTemporaryIPCBlobChild(
     PTemporaryIPCBlobChild* aActor) {
   RefPtr<mozilla::dom::TemporaryIPCBlobChild> actor =
       dont_AddRef(static_cast<mozilla::dom::TemporaryIPCBlobChild*>(aActor));
   return true;
 }
 
-PFileCreatorChild* BackgroundChildImpl::AllocPFileCreatorChild(
-    const nsString& aFullPath, const nsString& aType, const nsString& aName,
-    const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-    const bool& aIsFromNsIFile) {
-  return new mozilla::dom::FileCreatorChild();
-}
-
-bool BackgroundChildImpl::DeallocPFileCreatorChild(PFileCreatorChild* aActor) {
-  delete static_cast<mozilla::dom::FileCreatorChild*>(aActor);
-  return true;
-}
-
 PIPCBlobInputStreamChild* BackgroundChildImpl::AllocPIPCBlobInputStreamChild(
     const nsID& aID, const uint64_t& aSize) {
   // IPCBlobInputStreamChild is refcounted. Here it's created and in
   // DeallocPIPCBlobInputStreamChild is released.
 
   RefPtr<mozilla::dom::IPCBlobInputStreamChild> actor =
       new mozilla::dom::IPCBlobInputStreamChild(aID, aSize);
   return actor.forget().take();
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ipc_backgroundchildimpl_h__
 #define mozilla_ipc_backgroundchildimpl_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/PBackgroundChild.h"
-#include "nsRefPtrHashtable.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace dom {
 
 class IDBFileHandle;
 
 namespace indexedDB {
@@ -122,23 +121,16 @@ class BackgroundChildImpl : public PBack
   virtual bool DeallocPIPCBlobInputStreamChild(
       PIPCBlobInputStreamChild* aActor) override;
 
   virtual PTemporaryIPCBlobChild* AllocPTemporaryIPCBlobChild() override;
 
   virtual bool DeallocPTemporaryIPCBlobChild(
       PTemporaryIPCBlobChild* aActor) override;
 
-  virtual PFileCreatorChild* AllocPFileCreatorChild(
-      const nsString& aFullPath, const nsString& aType, const nsString& aName,
-      const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-      const bool& aIsFromNsIFile) override;
-
-  virtual bool DeallocPFileCreatorChild(PFileCreatorChild* aActor) override;
-
   virtual mozilla::dom::PRemoteWorkerChild* AllocPRemoteWorkerChild(
       const RemoteWorkerData& aData) override;
 
   virtual mozilla::ipc::IPCResult RecvPRemoteWorkerConstructor(
       PRemoteWorkerChild* aActor, const RemoteWorkerData& aData) override;
 
   virtual bool DeallocPRemoteWorkerChild(
       mozilla::dom::PRemoteWorkerChild* aActor) override;
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -25,21 +25,19 @@
 #include "mozilla/dom/PGamepadTestChannelParent.h"
 #include "mozilla/dom/MessagePortParent.h"
 #include "mozilla/dom/ServiceWorkerActors.h"
 #include "mozilla/dom/ServiceWorkerManagerParent.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
 #include "mozilla/dom/StorageActivityService.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
-#include "mozilla/dom/ipc/FileCreatorParent.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
 #include "mozilla/dom/ipc/PendingIPCBlobParent.h"
 #include "mozilla/dom/ipc/TemporaryIPCBlobParent.h"
-#include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/localstorage/ActorsParent.h"
 #include "mozilla/dom/quota/ActorsParent.h"
 #include "mozilla/dom/simpledb/ActorsParent.h"
 #include "mozilla/dom/RemoteWorkerParent.h"
 #include "mozilla/dom/RemoteWorkerServiceParent.h"
 #include "mozilla/dom/ReportingHeader.h"
 #include "mozilla/dom/SharedWorkerParent.h"
 #include "mozilla/dom/StorageIPC.h"
@@ -53,17 +51,16 @@
 #include "mozilla/ipc/PBackgroundTestParent.h"
 #include "mozilla/ipc/PChildToParentStreamParent.h"
 #include "mozilla/ipc/PParentToChildStreamParent.h"
 #include "mozilla/layout/VsyncParent.h"
 #include "mozilla/net/HttpBackgroundChannelParent.h"
 #include "mozilla/dom/network/UDPSocketParent.h"
 #include "mozilla/dom/WebAuthnTransactionParent.h"
 #include "mozilla/Preferences.h"
-#include "mozilla/StaticPrefs.h"
 #include "nsNetUtil.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsProxyRelease.h"
 #include "mozilla/RefPtr.h"
 #include "nsThreadUtils.h"
 #include "nsTraceRefcnt.h"
 #include "nsXULAppAPI.h"
 
@@ -536,63 +533,16 @@ IPCResult BackgroundParentImpl::RecvPSha
 
 bool BackgroundParentImpl::DeallocPSharedWorkerParent(
     mozilla::dom::PSharedWorkerParent* aActor) {
   RefPtr<mozilla::dom::SharedWorkerParent> actor =
       dont_AddRef(static_cast<mozilla::dom::SharedWorkerParent*>(aActor));
   return true;
 }
 
-PFileCreatorParent* BackgroundParentImpl::AllocPFileCreatorParent(
-    const nsString& aFullPath, const nsString& aType, const nsString& aName,
-    const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-    const bool& aIsFromNsIFile) {
-  RefPtr<mozilla::dom::FileCreatorParent> actor =
-      new mozilla::dom::FileCreatorParent();
-  return actor.forget().take();
-}
-
-mozilla::ipc::IPCResult BackgroundParentImpl::RecvPFileCreatorConstructor(
-    PFileCreatorParent* aActor, const nsString& aFullPath,
-    const nsString& aType, const nsString& aName,
-    const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-    const bool& aIsFromNsIFile) {
-  bool isFileRemoteType = false;
-
-  // If the ContentParent is null we are dealing with a same-process actor.
-  RefPtr<ContentParent> parent = BackgroundParent::GetContentParent(this);
-  if (!parent) {
-    isFileRemoteType = true;
-  } else {
-    isFileRemoteType = parent->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE);
-    NS_ReleaseOnMainThreadSystemGroup("ContentParent release", parent.forget());
-  }
-
-  mozilla::dom::FileCreatorParent* actor =
-      static_cast<mozilla::dom::FileCreatorParent*>(aActor);
-
-  // We allow the creation of File via this IPC call only for the 'file' process
-  // or for testing.
-  if (!isFileRemoteType && !StaticPrefs::dom_file_createInChild()) {
-    Unused << mozilla::dom::FileCreatorParent::Send__delete__(
-        actor, FileCreationErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
-    return IPC_OK();
-  }
-
-  return actor->CreateAndShareFile(aFullPath, aType, aName, aLastModified,
-                                   aExistenceCheck, aIsFromNsIFile);
-}
-
-bool BackgroundParentImpl::DeallocPFileCreatorParent(
-    PFileCreatorParent* aActor) {
-  RefPtr<mozilla::dom::FileCreatorParent> actor =
-      dont_AddRef(static_cast<mozilla::dom::FileCreatorParent*>(aActor));
-  return true;
-}
-
 PTemporaryIPCBlobParent* BackgroundParentImpl::AllocPTemporaryIPCBlobParent() {
   return new mozilla::dom::TemporaryIPCBlobParent();
 }
 
 mozilla::ipc::IPCResult BackgroundParentImpl::RecvPTemporaryIPCBlobConstructor(
     PTemporaryIPCBlobParent* aActor) {
   mozilla::dom::TemporaryIPCBlobParent* actor =
       static_cast<mozilla::dom::TemporaryIPCBlobParent*>(aActor);
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -150,29 +150,16 @@ class BackgroundParentImpl : public PBac
   virtual PTemporaryIPCBlobParent* AllocPTemporaryIPCBlobParent() override;
 
   virtual mozilla::ipc::IPCResult RecvPTemporaryIPCBlobConstructor(
       PTemporaryIPCBlobParent* actor) override;
 
   virtual bool DeallocPTemporaryIPCBlobParent(
       PTemporaryIPCBlobParent* aActor) override;
 
-  virtual PFileCreatorParent* AllocPFileCreatorParent(
-      const nsString& aFullPath, const nsString& aType, const nsString& aName,
-      const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-      const bool& aIsFromNsIFile) override;
-
-  virtual mozilla::ipc::IPCResult RecvPFileCreatorConstructor(
-      PFileCreatorParent* actor, const nsString& aFullPath,
-      const nsString& aType, const nsString& aName,
-      const Maybe<int64_t>& aLastModified, const bool& aExistenceCheck,
-      const bool& aIsFromNsIFile) override;
-
-  virtual bool DeallocPFileCreatorParent(PFileCreatorParent* aActor) override;
-
   virtual mozilla::dom::PRemoteWorkerParent* AllocPRemoteWorkerParent(
       const RemoteWorkerData& aData) override;
 
   virtual bool DeallocPRemoteWorkerParent(PRemoteWorkerParent* aActor) override;
 
   virtual mozilla::dom::PRemoteWorkerServiceParent*
   AllocPRemoteWorkerServiceParent() override;
 
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -24,17 +24,16 @@ include protocol PGamepadEventChannel;
 include protocol PGamepadTestChannel;
 include protocol PHttpBackgroundChannel;
 include protocol PIPCBlobInputStream;
 include protocol PPendingIPCBlob;
 include protocol PRemoteWorker;
 include protocol PRemoteWorkerService;
 include protocol PSharedWorker;
 include protocol PTemporaryIPCBlob;
-include protocol PFileCreator;
 include protocol PMessagePort;
 include protocol PCameras;
 include protocol PMIDIManager;
 include protocol PMIDIPort;
 include protocol PQuota;
 include protocol PChildToParentStream;
 include protocol PParentToChildStream;
 include protocol PServiceWorker;
@@ -90,17 +89,16 @@ sync protocol PBackground
   manages PGamepadTestChannel;
   manages PHttpBackgroundChannel;
   manages PIPCBlobInputStream;
   manages PPendingIPCBlob;
   manages PRemoteWorker;
   manages PRemoteWorkerService;
   manages PSharedWorker;
   manages PTemporaryIPCBlob;
-  manages PFileCreator;
   manages PMessagePort;
   manages PCameras;
   manages PMIDIManager;
   manages PMIDIPort;
   manages PQuota;
   manages PChildToParentStream;
   manages PParentToChildStream;
   manages PServiceWorker;
@@ -194,20 +192,16 @@ parent:
   async PWebAuthnTransaction();
 
   async PSharedWorker(RemoteWorkerData data,
                       uint64_t windowID,
                       MessagePortIdentifier portIdentifier);
 
   async PTemporaryIPCBlob();
 
-  async PFileCreator(nsString aFullPath, nsString aType, nsString aName,
-                     int64_t? lastModified, bool aExistenceCheck,
-                     bool aIsFromNsIFile);
-
   async PClientManager();
 
   async PMIDIManager();
   async PMIDIPort(MIDIPortInfo portInfo, bool sysexEnabled);
 
   // This method is used to propagate storage activities from the child actor
   // to the parent actor. See StorageActivityService.
   async StorageActivity(PrincipalInfo principalInfo);
@@ -229,17 +223,16 @@ child:
   async PCache();
   async PCacheStreamControl();
 
   async PParentToChildStream();
 
   async PPendingIPCBlob(IPCBlob blob);
 
   async PRemoteWorker(RemoteWorkerData data);
-
 both:
   // PIPCBlobInputStream is created on the parent side only if the child starts
   // a migration.
   async PIPCBlobInputStream(nsID aID, uint64_t aSize);
 
   async PFileDescriptorSet(FileDescriptor fd);
 };
 
--- a/ipc/ipdl/ipdl/direct_call.py
+++ b/ipc/ipdl/ipdl/direct_call.py
@@ -24,23 +24,16 @@ DIRECT_CALL_OVERRIDES = {
     ("PCompositorBridge", "parent"): (
         "CompositorBridgeParentBase", "mozilla/layers/CompositorBridgeParent.h"
     ),
 
     ("PContentPermissionRequest", "child"): (
         "RemotePermissionRequest", "nsContentPermissionHelper.h"
     ),
 
-    ("PFileCreator", "child"): (
-        "mozilla::dom::FileCreatorChild", "mozilla/dom/ipc/FileCreatorChild.h"
-    ),
-    ("PFileCreator", "parent"): (
-        "mozilla::dom::FileCreatorParent", "mozilla/dom/ipc/FileCreatorParent.h"
-    ),
-
     ("PFileSystemRequest", "child"): (
         "FileSystemTaskChildBase", "mozilla/dom/FileSystemTaskBase.h"
     ),
 
     ("PGMP", "child"): ("GMPChild", "GMPChild.h"),
     ("PGMP", "parent"): ("GMPParent", "GMPParent.h"),
     ("PGMPContent", "child"): ("GMPContentChild", "GMPContentChild.h"),
     ("PGMPStorage", "child"): ("GMPStorageChild", "GMPStorageChild.h"),
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -567,24 +567,16 @@ VARCACHE_PREF(
 )
 
 VARCACHE_PREF(
   "dom.storage_access.auto_grants.delayed",
    dom_storage_access_auto_grants_delayed,
   bool, true
 )
 
-// Allow the content process to create a File from a path. This is allowed just
-// on parent process, on 'file' Content process, or for testing.
-VARCACHE_PREF(
-  "dom.file.createInChild",
-   dom_file_createInChild,
-  RelaxedAtomicBool, false
-)
-
 //---------------------------------------------------------------------------
 // Extension prefs
 //---------------------------------------------------------------------------
 
 #ifdef ANDROID
 // Private browsing opt-in is only supported on Firefox desktop.
 # define PREF_VALUE true
 #else