Bug 1332003 - Entries API must create BlobImpl in the parent process. r=smaug, a=lizzard
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 01 Feb 2017 07:33:18 +0100
changeset 378156 9f9e9f92c6d459451031bcde54d2db9defa09409
parent 378155 dfdab396dff7a77d7d075b231431bad1c2a2bcb8
child 378157 8483128d72e6509e552ce106ea450203b0502bf8
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, lizzard
bugs1332003
milestone53.0a2
Bug 1332003 - Entries API must create BlobImpl in the parent process. r=smaug, a=lizzard
dom/filesystem/CreateFileTask.cpp
dom/filesystem/CreateFileTask.h
dom/filesystem/Directory.h
dom/filesystem/FileSystemTaskBase.cpp
dom/filesystem/GetDirectoryListingTask.cpp
dom/filesystem/GetDirectoryListingTask.h
dom/filesystem/GetFileOrDirectoryTask.cpp
dom/filesystem/GetFileOrDirectoryTask.h
dom/filesystem/GetFilesHelper.cpp
dom/filesystem/GetFilesHelper.h
dom/filesystem/GetFilesTask.cpp
dom/filesystem/GetFilesTask.h
dom/filesystem/PFileSystemParams.ipdlh
dom/filesystem/PFileSystemRequest.ipdl
--- a/dom/filesystem/CreateFileTask.cpp
+++ b/dom/filesystem/CreateFileTask.cpp
@@ -135,20 +135,18 @@ CreateFileTaskChild::GetRequestParams(co
 void
 CreateFileTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue,
                                              ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
 
   const FileSystemFileResponse& r = aValue.get_FileSystemFileResponse();
 
-  aRv = NS_NewLocalFile(r.realPath(), true, getter_AddRefs(mTargetPath));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
+  mBlobImpl = static_cast<BlobChild*>(r.blobChild())->GetBlobImpl();
+  MOZ_ASSERT(mBlobImpl);
 }
 
 void
 CreateFileTaskChild::HandlerCallback()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
 
   if (mFileSystem->IsShutdown()) {
@@ -157,19 +155,20 @@ CreateFileTaskChild::HandlerCallback()
   }
 
   if (HasError()) {
     mPromise->MaybeReject(mErrorValue);
     mPromise = nullptr;
     return;
   }
 
-  RefPtr<File> file = File::CreateFromFile(mFileSystem->GetParentObject(),
-                                           mTargetPath);
+  RefPtr<File> file = File::Create(mFileSystem->GetParentObject(), mBlobImpl);
   mPromise->MaybeResolve(file);
+
+  mBlobImpl = nullptr;
   mPromise = nullptr;
 }
 
 void
 CreateFileTaskChild::GetPermissionAccessType(nsCString& aAccess) const
 {
   GET_PERMISSION_ACCESS_TYPE(aAccess)
 }
@@ -228,23 +227,20 @@ CreateFileTaskParent::CreateFileTaskPare
   MOZ_ASSERT(aFileSystem);
 }
 
 FileSystemResponseValue
 CreateFileTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
 {
   AssertIsOnBackgroundThread();
 
-  nsAutoString path;
-  aRv = mTargetPath->GetPath(path);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return FileSystemDirectoryResponse();
-  }
-
-  return FileSystemFileResponse(path, EmptyString());
+  RefPtr<BlobImpl> blobImpl = new BlobImplFile(mTargetPath);
+  BlobParent* blobParent =
+    BlobParent::GetOrCreate(mRequestParent->Manager(), blobImpl);
+  return FileSystemFileResponse(blobParent, nullptr);
 }
 
 nsresult
 CreateFileTaskParent::IOWork()
 {
   class MOZ_RAII AutoClose final
   {
   public:
--- a/dom/filesystem/CreateFileTask.h
+++ b/dom/filesystem/CreateFileTask.h
@@ -54,16 +54,18 @@ protected:
 private:
   CreateFileTaskChild(FileSystemBase* aFileSystem,
                       nsIFile* aFile,
                       bool aReplace);
 
   RefPtr<Promise> mPromise;
   nsCOMPtr<nsIFile> mTargetPath;
 
+  // This is the content of what we want to store. Then, when the File is
+  // created, this will be used to store the new object.
   RefPtr<BlobImpl> mBlobImpl;
 
   // This is going to be the content of the file, received by createFile()
   // params.
   InfallibleTArray<uint8_t> mArrayData;
 
   bool mReplace;
 };
--- a/dom/filesystem/Directory.h
+++ b/dom/filesystem/Directory.h
@@ -34,26 +34,16 @@ class FileSystemBase;
 class Promise;
 class StringOrFileOrDirectory;
 
 class Directory final
   : public nsISupports
   , public nsWrapperCache
 {
 public:
-  struct FileOrDirectoryPath
-  {
-    nsString mPath;
-
-    enum {
-      eFilePath,
-      eDirectoryPath
-    } mType;
-  };
-
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Directory)
 
   static bool
   DeviceStorageEnabled(JSContext* aCx, JSObject* aObj);
 
   static bool
   WebkitBlinkDirectoryPickerEnabled(JSContext* aCx, JSObject* aObj);
--- a/dom/filesystem/FileSystemTaskBase.cpp
+++ b/dom/filesystem/FileSystemTaskBase.cpp
@@ -200,18 +200,18 @@ FileSystemTaskChildBase::SetError(const 
   mErrorValue = FileSystemErrorFromNsError(aErrorValue);
 }
 
 /**
  * FileSystemTaskParentBase class
  */
 
 FileSystemTaskParentBase::FileSystemTaskParentBase(FileSystemBase* aFileSystem,
-                                                  const FileSystemParams& aParam,
-                                                  FileSystemRequestParent* aParent)
+                                                   const FileSystemParams& aParam,
+                                                   FileSystemRequestParent* aParent)
   : mErrorValue(NS_OK)
   , mFileSystem(aFileSystem)
   , mRequestParent(aParent)
   , mBackgroundEventTarget(NS_GetCurrentThread())
 {
   MOZ_ASSERT(XRE_IsParentProcess(),
              "Only call from parent process!");
   MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
--- a/dom/filesystem/GetDirectoryListingTask.cpp
+++ b/dom/filesystem/GetDirectoryListingTask.cpp
@@ -83,53 +83,80 @@ GetDirectoryListingTaskChild::GetPromise
 }
 
 FileSystemParams
 GetDirectoryListingTaskChild::GetRequestParams(const nsString& aSerializedDOMPath,
                                                ErrorResult& aRv) const
 {
   mFileSystem->AssertIsOnOwningThread();
 
+  // this is the real path.
   nsAutoString path;
   aRv = mTargetPath->GetPath(path);
   if (NS_WARN_IF(aRv.Failed())) {
     return FileSystemGetDirectoryListingParams();
   }
 
+  // this is the dom path.
+  nsAutoString directoryPath;
+  mDirectory->GetPath(directoryPath, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return FileSystemGetDirectoryListingParams();
+  }
+
   return FileSystemGetDirectoryListingParams(aSerializedDOMPath, path,
-                                             mFilters);
+                                             directoryPath, mFilters);
 }
 
 void
 GetDirectoryListingTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue,
                                                       ErrorResult& aRv)
 {
   mFileSystem->AssertIsOnOwningThread();
   MOZ_ASSERT(aValue.type() ==
                FileSystemResponseValue::TFileSystemDirectoryListingResponse);
 
   FileSystemDirectoryListingResponse r = aValue;
   for (uint32_t i = 0; i < r.data().Length(); ++i) {
     const FileSystemDirectoryListingResponseData& data = r.data()[i];
 
-    Directory::FileOrDirectoryPath element;
+    OwningFileOrDirectory* ofd = mTargetData.AppendElement(fallible);
+    if (!ofd) {
+      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return;
+    }
 
     if (data.type() == FileSystemDirectoryListingResponseData::TFileSystemDirectoryListingResponseFile) {
-      element.mType = Directory::FileOrDirectoryPath::eFilePath;
-      element.mPath = data.get_FileSystemDirectoryListingResponseFile().fileRealPath();
+      const FileSystemDirectoryListingResponseFile& d =
+        data.get_FileSystemDirectoryListingResponseFile();
+
+      RefPtr<BlobImpl> blobImpl =
+        static_cast<BlobChild*>(d.blobChild())->GetBlobImpl();
+      MOZ_ASSERT(blobImpl);
+
+      RefPtr<File> file = File::Create(mFileSystem->GetParentObject(), blobImpl);
+      MOZ_ASSERT(file);
+
+      ofd->SetAsFile() = file;
     } else {
       MOZ_ASSERT(data.type() == FileSystemDirectoryListingResponseData::TFileSystemDirectoryListingResponseDirectory);
+      const FileSystemDirectoryListingResponseDirectory& d =
+        data.get_FileSystemDirectoryListingResponseDirectory();
 
-      element.mType = Directory::FileOrDirectoryPath::eDirectoryPath;
-      element.mPath = data.get_FileSystemDirectoryListingResponseDirectory().directoryRealPath();
-    }
+      nsCOMPtr<nsIFile> path;
+      aRv = NS_NewLocalFile(d.directoryRealPath(), true, getter_AddRefs(path));
+      if (NS_WARN_IF(aRv.Failed())) {
+        return;
+      }
 
-    if (!mTargetData.AppendElement(element, fallible)) {
-      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-      return;
+      RefPtr<Directory> directory =
+        Directory::Create(mFileSystem->GetParentObject(), path, mFileSystem);
+      MOZ_ASSERT(directory);
+
+      ofd->SetAsDirectory() = directory;
     }
   }
 }
 
 void
 GetDirectoryListingTaskChild::HandlerCallback()
 {
   mFileSystem->AssertIsOnOwningThread();
@@ -140,91 +167,17 @@ GetDirectoryListingTaskChild::HandlerCal
   }
 
   if (HasError()) {
     mPromise->MaybeReject(mErrorValue);
     mPromise = nullptr;
     return;
   }
 
-  size_t count = mTargetData.Length();
-
-  nsAutoString directoryPath;
-  ErrorResult error;
-  mDirectory->GetPath(directoryPath, error);
-  if (NS_WARN_IF(error.Failed())) {
-    mPromise->MaybeReject(error.StealNSResult());
-    mPromise = nullptr;
-    return;
-  }
-
-  Sequence<OwningFileOrDirectory> listing;
-
-  if (!listing.SetLength(count, mozilla::fallible_t())) {
-    mPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
-    mPromise = nullptr;
-    return;
-  }
-
-  for (unsigned i = 0; i < count; i++) {
-    nsCOMPtr<nsIFile> path;
-    nsresult rv = NS_NewLocalFile(mTargetData[i].mPath, true,
-                                  getter_AddRefs(path));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      mPromise->MaybeReject(rv);
-      mPromise = nullptr;
-      return;
-    }
-
-#ifdef DEBUG
-    nsCOMPtr<nsIFile> rootPath;
-    rv = NS_NewLocalFile(mFileSystem->LocalOrDeviceStorageRootPath(), false,
-                         getter_AddRefs(rootPath));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      mPromise->MaybeReject(rv);
-      mPromise = nullptr;
-      return;
-    }
-
-    MOZ_ASSERT(FileSystemUtils::IsDescendantPath(rootPath, path));
-#endif
-
-    if (mTargetData[i].mType == Directory::FileOrDirectoryPath::eDirectoryPath) {
-      RefPtr<Directory> directory =
-        Directory::Create(mFileSystem->GetParentObject(), path, mFileSystem);
-      MOZ_ASSERT(directory);
-
-      // Propogate mFilter onto sub-Directory object:
-      directory->SetContentFilters(mFilters);
-      listing[i].SetAsDirectory() = directory;
-    } else {
-      MOZ_ASSERT(mTargetData[i].mType == Directory::FileOrDirectoryPath::eFilePath);
-
-      RefPtr<File> file =
-        File::CreateFromFile(mFileSystem->GetParentObject(), path);
-      MOZ_ASSERT(file);
-
-      nsAutoString filePath;
-      filePath.Assign(directoryPath);
-
-      // This is specific for unix root filesystem.
-      if (!directoryPath.EqualsLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL)) {
-        filePath.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
-      }
-
-      nsAutoString name;
-      file->GetName(name);
-      filePath.Append(name);
-      file->SetPath(filePath);
-
-      listing[i].SetAsFile() = file;
-    }
-  }
-
-  mPromise->MaybeResolve(listing);
+  mPromise->MaybeResolve(mTargetData);
   mPromise = nullptr;
 }
 
 void
 GetDirectoryListingTaskChild::GetPermissionAccessType(nsCString& aAccess) const
 {
   aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION);
 }
@@ -254,16 +207,17 @@ GetDirectoryListingTaskParent::Create(Fi
 
   return task.forget();
 }
 
 GetDirectoryListingTaskParent::GetDirectoryListingTaskParent(FileSystemBase* aFileSystem,
                                                              const FileSystemGetDirectoryListingParams& aParam,
                                                              FileSystemRequestParent* aParent)
   : FileSystemTaskParentBase(aFileSystem, aParam, aParent)
+  , mDOMPath(aParam.domPath())
   , mFilters(aParam.filters())
 {
   MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aFileSystem);
 }
 
 FileSystemResponseValue
@@ -271,22 +225,45 @@ GetDirectoryListingTaskParent::GetSucces
 {
   AssertIsOnBackgroundThread();
 
   InfallibleTArray<PBlobParent*> blobs;
 
   nsTArray<FileSystemDirectoryListingResponseData> inputs;
 
   for (unsigned i = 0; i < mTargetData.Length(); i++) {
-    if (mTargetData[i].mType == Directory::FileOrDirectoryPath::eFilePath) {
+    if (mTargetData[i].mType == FileOrDirectoryPath::eFilePath) {
+      nsCOMPtr<nsIFile> path;
+      nsresult rv = NS_NewLocalFile(mTargetData[i].mPath, true,
+                                    getter_AddRefs(path));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return FileSystemErrorResponse(rv);
+      }
+
       FileSystemDirectoryListingResponseFile fileData;
-      fileData.fileRealPath() = mTargetData[i].mPath;
+      RefPtr<BlobImpl> blobImpl = new BlobImplFile(path);
+
+      nsAutoString filePath;
+      filePath.Assign(mDOMPath);
+
+      // This is specific for unix root filesystem.
+      if (!mDOMPath.EqualsLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL)) {
+        filePath.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
+      }
+
+      nsAutoString name;
+      blobImpl->GetName(name);
+      filePath.Append(name);
+      blobImpl->SetPath(filePath);
+
+      fileData.blobParent() =
+        BlobParent::GetOrCreate(mRequestParent->Manager(), blobImpl);
       inputs.AppendElement(fileData);
     } else {
-      MOZ_ASSERT(mTargetData[i].mType == Directory::FileOrDirectoryPath::eDirectoryPath);
+      MOZ_ASSERT(mTargetData[i].mType == FileOrDirectoryPath::eDirectoryPath);
       FileSystemDirectoryListingResponseDirectory directoryData;
       directoryData.directoryRealPath() = mTargetData[i].mPath;
       inputs.AppendElement(directoryData);
     }
   }
 
   FileSystemDirectoryListingResponse response;
   response.data().SwapElements(inputs);
@@ -390,20 +367,20 @@ GetDirectoryListingTaskParent::IOWork()
       }
     }
 
     nsAutoString path;
     if (NS_WARN_IF(NS_FAILED(currFile->GetPath(path)))) {
       continue;
     }
 
-    Directory::FileOrDirectoryPath element;
+    FileOrDirectoryPath element;
     element.mPath = path;
-    element.mType = isDir ? Directory::FileOrDirectoryPath::eDirectoryPath
-                          : Directory::FileOrDirectoryPath::eFilePath;
+    element.mType = isDir ? FileOrDirectoryPath::eDirectoryPath
+                          : FileOrDirectoryPath::eFilePath;
 
     if (!mTargetData.AppendElement(element, fallible)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
   return NS_OK;
 }
 
--- a/dom/filesystem/GetDirectoryListingTask.h
+++ b/dom/filesystem/GetDirectoryListingTask.h
@@ -53,19 +53,17 @@ private:
   virtual void
   HandlerCallback() override;
 
   RefPtr<Promise> mPromise;
   RefPtr<Directory> mDirectory;
   nsCOMPtr<nsIFile> mTargetPath;
   nsString mFilters;
 
-  // We cannot store File or Directory objects bacause this object is created
-  // on a different thread and File and Directory are not thread-safe.
-  FallibleTArray<Directory::FileOrDirectoryPath> mTargetData;
+  FallibleTArray<OwningFileOrDirectory> mTargetData;
 };
 
 class GetDirectoryListingTaskParent final : public FileSystemTaskParentBase
 {
 public:
   static already_AddRefed<GetDirectoryListingTaskParent>
   Create(FileSystemBase* aFileSystem,
          const FileSystemGetDirectoryListingParams& aParam,
@@ -82,19 +80,28 @@ private:
 
   virtual FileSystemResponseValue
   GetSuccessRequestResult(ErrorResult& aRv) const override;
 
   virtual nsresult
   IOWork() override;
 
   nsCOMPtr<nsIFile> mTargetPath;
+  nsString mDOMPath;
   nsString mFilters;
 
-  // We cannot store File or Directory objects bacause this object is created
-  // on a different thread and File and Directory are not thread-safe.
-  FallibleTArray<Directory::FileOrDirectoryPath> mTargetData;
+  struct FileOrDirectoryPath
+  {
+    nsString mPath;
+
+    enum {
+      eFilePath,
+      eDirectoryPath
+    } mType;
+  };
+
+  FallibleTArray<FileOrDirectoryPath> mTargetData;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_GetDirectoryListing_h
--- a/dom/filesystem/GetFileOrDirectoryTask.cpp
+++ b/dom/filesystem/GetFileOrDirectoryTask.cpp
@@ -53,17 +53,16 @@ GetFileOrDirectoryTaskChild::Create(File
   return task.forget();
 }
 
 GetFileOrDirectoryTaskChild::GetFileOrDirectoryTaskChild(FileSystemBase* aFileSystem,
                                                          nsIFile* aTargetPath,
                                                          bool aDirectoryOnly)
   : FileSystemTaskChildBase(aFileSystem)
   , mTargetPath(aTargetPath)
-  , mIsDirectory(aDirectoryOnly)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   MOZ_ASSERT(aFileSystem);
 }
 
 GetFileOrDirectoryTaskChild::~GetFileOrDirectoryTaskChild()
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -95,33 +94,36 @@ void
 GetFileOrDirectoryTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue,
                                                      ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   switch (aValue.type()) {
     case FileSystemResponseValue::TFileSystemFileResponse: {
       FileSystemFileResponse r = aValue;
 
-      aRv = NS_NewLocalFile(r.realPath(), true, getter_AddRefs(mTargetPath));
-      if (NS_WARN_IF(aRv.Failed())) {
-        return;
-      }
+      RefPtr<BlobImpl> blobImpl =
+        static_cast<BlobChild*>(r.blobChild())->GetBlobImpl();
+      MOZ_ASSERT(blobImpl);
 
-      mIsDirectory = false;
+      mResultFile = File::Create(mFileSystem->GetParentObject(), blobImpl);
+      MOZ_ASSERT(mResultFile);
       break;
     }
     case FileSystemResponseValue::TFileSystemDirectoryResponse: {
       FileSystemDirectoryResponse r = aValue;
 
-      aRv = NS_NewLocalFile(r.realPath(), true, getter_AddRefs(mTargetPath));
+      nsCOMPtr<nsIFile> file;
+      aRv = NS_NewLocalFile(r.realPath(), true, getter_AddRefs(file));
       if (NS_WARN_IF(aRv.Failed())) {
         return;
       }
 
-      mIsDirectory = true;
+      mResultDirectory = Directory::Create(mFileSystem->GetParentObject(),
+                                           file, mFileSystem);
+      MOZ_ASSERT(mResultDirectory);
       break;
     }
     default: {
       MOZ_CRASH("not reached");
       break;
     }
   }
 }
@@ -136,30 +138,26 @@ GetFileOrDirectoryTaskChild::HandlerCall
   }
 
   if (HasError()) {
     mPromise->MaybeReject(mErrorValue);
     mPromise = nullptr;
     return;
   }
 
-  if (mIsDirectory) {
-    RefPtr<Directory> dir = Directory::Create(mFileSystem->GetParentObject(),
-                                              mTargetPath,
-                                              mFileSystem);
-    MOZ_ASSERT(dir);
-
-    mPromise->MaybeResolve(dir);
+  if (mResultDirectory) {
+    mPromise->MaybeResolve(mResultDirectory);
+    mResultDirectory = nullptr;
     mPromise = nullptr;
     return;
   }
 
-  RefPtr<File> file = File::CreateFromFile(mFileSystem->GetParentObject(),
-                                           mTargetPath);
-  mPromise->MaybeResolve(file);
+  MOZ_ASSERT(mResultFile);
+  mPromise->MaybeResolve(mResultFile);
+  mResultFile = nullptr;
   mPromise = nullptr;
 }
 
 void
 GetFileOrDirectoryTaskChild::GetPermissionAccessType(nsCString& aAccess) const
 {
   aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION);
 }
@@ -211,17 +209,20 @@ GetFileOrDirectoryTaskParent::GetSuccess
   if (NS_WARN_IF(aRv.Failed())) {
     return FileSystemDirectoryResponse();
   }
 
   if (mIsDirectory) {
     return FileSystemDirectoryResponse(path);
   }
 
-  return FileSystemFileResponse(path, EmptyString());
+  RefPtr<BlobImpl> blobImpl = new BlobImplFile(mTargetPath);
+  BlobParent* blobParent =
+    BlobParent::GetOrCreate(mRequestParent->Manager(), blobImpl);
+  return FileSystemFileResponse(blobParent, nullptr);
 }
 
 nsresult
 GetFileOrDirectoryTaskParent::IOWork()
 {
   MOZ_ASSERT(XRE_IsParentProcess(),
              "Only call from parent process!");
   MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
--- a/dom/filesystem/GetFileOrDirectoryTask.h
+++ b/dom/filesystem/GetFileOrDirectoryTask.h
@@ -49,18 +49,18 @@ private:
   // If aDirectoryOnly is set, we should ensure that the target is a directory.
   GetFileOrDirectoryTaskChild(FileSystemBase* aFileSystem,
                               nsIFile* aTargetPath,
                               bool aDirectoryOnly);
 
   RefPtr<Promise> mPromise;
   nsCOMPtr<nsIFile> mTargetPath;
 
-  // Whether we get a directory.
-  bool mIsDirectory;
+  RefPtr<File> mResultFile;
+  RefPtr<Directory> mResultDirectory;
 };
 
 class GetFileOrDirectoryTaskParent final : public FileSystemTaskParentBase
 {
 public:
   static already_AddRefed<GetFileOrDirectoryTaskParent>
   Create(FileSystemBase* aFileSystem,
          const FileSystemGetFileOrDirectoryParams& aParam,
--- a/dom/filesystem/GetFilesHelper.cpp
+++ b/dom/filesystem/GetFilesHelper.cpp
@@ -298,32 +298,20 @@ GetFilesHelper::RunMainThread()
   MOZ_ASSERT(!mListingCompleted);
 
   // If there is an error, do nothing.
   if (NS_FAILED(mErrorResult)) {
     return;
   }
 
   // Create the sequence of Files.
-  for (uint32_t i = 0; i < mTargetPathArray.Length(); ++i) {
-    nsCOMPtr<nsIFile> file;
-    mErrorResult =
-      NS_NewLocalFile(mTargetPathArray[i].mRealPath, true,
-                      getter_AddRefs(file));
-    if (NS_WARN_IF(NS_FAILED(mErrorResult))) {
-      mFiles.Clear();
-      return;
-    }
-
-    RefPtr<File> domFile =
-      File::CreateFromFile(mGlobal, file);
+  for (uint32_t i = 0; i < mTargetBlobImplArray.Length(); ++i) {
+    RefPtr<File> domFile = File::Create(mGlobal, mTargetBlobImplArray[i]);
     MOZ_ASSERT(domFile);
 
-    domFile->SetPath(mTargetPathArray[i].mDomPath);
-
     if (!mFiles.AppendElement(domFile, fallible)) {
       mErrorResult = NS_ERROR_OUT_OF_MEMORY;
       mFiles.Clear();
       return;
     }
   }
 }
 
@@ -390,26 +378,23 @@ GetFilesHelperBase::ExploreDirectory(con
 
     nsAutoString leafName;
     if (NS_WARN_IF(NS_FAILED(currFile->GetLeafName(leafName)))) {
       continue;
     }
     domPath.Append(leafName);
 
     if (isFile) {
-      FileData* data = mTargetPathArray.AppendElement(fallible);
-      if (!data) {
+      RefPtr<BlobImpl> blobImpl = new BlobImplFile(currFile);
+      blobImpl->SetPath(domPath);
+
+      if (!mTargetBlobImplArray.AppendElement(blobImpl, fallible)) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
 
-      if (NS_WARN_IF(NS_FAILED(currFile->GetPath(data->mRealPath)))) {
-        continue;
-      }
-
-      data->mDomPath = domPath;
       continue;
     }
 
     MOZ_ASSERT(isDir);
     if (!mRecursiveFlag) {
       continue;
     }
 
--- a/dom/filesystem/GetFilesHelper.h
+++ b/dom/filesystem/GetFilesHelper.h
@@ -58,23 +58,18 @@ protected:
   nsresult
   AddExploredDirectory(nsIFile* aDirectory);
 
   bool
   ShouldFollowSymLink(nsIFile* aDirectory);
 
   bool mRecursiveFlag;
 
-  // We populate this array in the I/O thread with the paths of the Files that
-  // we want to send as result to the promise objects.
-  struct FileData {
-    nsString mDomPath;
-    nsString mRealPath;
-  };
-  FallibleTArray<FileData> mTargetPathArray;
+  // We populate this array in the I/O thread with the BlobImpl.
+  FallibleTArray<RefPtr<BlobImpl>> mTargetBlobImplArray;
   nsTHashtable<nsCStringHashKey> mExploredDirectories;
 };
 
 // Retrieving the list of files can be very time/IO consuming. We use this
 // helper class to do it just once.
 class GetFilesHelper : public Runnable
                      , public GetFilesHelperBase
 {
--- a/dom/filesystem/GetFilesTask.cpp
+++ b/dom/filesystem/GetFilesTask.cpp
@@ -117,18 +117,21 @@ GetFilesTaskChild::SetSuccessRequestResu
 
   if (!mTargetData.SetLength(r.data().Length(), mozilla::fallible_t())) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   for (uint32_t i = 0; i < r.data().Length(); ++i) {
     const FileSystemFileResponse& data = r.data()[i];
-    mTargetData[i].mRealPath = data.realPath();
-    mTargetData[i].mDOMPath = data.domPath();
+    RefPtr<BlobImpl> blobImpl =
+      static_cast<BlobChild*>(data.blobChild())->GetBlobImpl();
+    MOZ_ASSERT(blobImpl);
+
+    mTargetData[i] = File::Create(mFileSystem->GetParentObject(), blobImpl);
   }
 }
 
 void
 GetFilesTaskChild::HandlerCallback()
 {
   mFileSystem->AssertIsOnOwningThread();
   if (mFileSystem->IsShutdown()) {
@@ -137,58 +140,17 @@ GetFilesTaskChild::HandlerCallback()
   }
 
   if (HasError()) {
     mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     mPromise = nullptr;
     return;
   }
 
-  size_t count = mTargetData.Length();
-
-  Sequence<RefPtr<File>> listing;
-
-  if (!listing.SetLength(count, mozilla::fallible_t())) {
-    mPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
-    mPromise = nullptr;
-    return;
-  }
-
-  for (unsigned i = 0; i < count; i++) {
-    nsCOMPtr<nsIFile> path;
-    nsresult rv = NS_NewLocalFile(mTargetData[i].mRealPath, true,
-                                  getter_AddRefs(path));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
-      mPromise = nullptr;
-      return;
-    }
-
-#ifdef DEBUG
-    nsCOMPtr<nsIFile> rootPath;
-    rv = NS_NewLocalFile(mFileSystem->LocalOrDeviceStorageRootPath(), false,
-                         getter_AddRefs(rootPath));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
-      mPromise = nullptr;
-      return;
-    }
-
-    MOZ_ASSERT(FileSystemUtils::IsDescendantPath(rootPath, path));
-#endif
-
-    RefPtr<File> file =
-      File::CreateFromFile(mFileSystem->GetParentObject(), path);
-    MOZ_ASSERT(file);
-    file->SetPath(mTargetData[i].mDOMPath);
-
-    listing[i] = file;
-  }
-
-  mPromise->MaybeResolve(listing);
+  mPromise->MaybeResolve(mTargetData);
   mPromise = nullptr;
 }
 
 void
 GetFilesTaskChild::GetPermissionAccessType(nsCString& aAccess) const
 {
   aAccess.AssignLiteral("read");
 }
@@ -234,27 +196,27 @@ GetFilesTaskParent::GetFilesTaskParent(F
 FileSystemResponseValue
 GetFilesTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
 {
   AssertIsOnBackgroundThread();
 
   InfallibleTArray<PBlobParent*> blobs;
 
   FallibleTArray<FileSystemFileResponse> inputs;
-  if (!inputs.SetLength(mTargetPathArray.Length(), mozilla::fallible_t())) {
+  if (!inputs.SetLength(mTargetBlobImplArray.Length(), mozilla::fallible_t())) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     FileSystemFilesResponse response;
     return response;
   }
 
-  for (unsigned i = 0; i < mTargetPathArray.Length(); i++) {
-    FileSystemFileResponse fileData;
-    fileData.realPath() = mTargetPathArray[i].mRealPath;
-    fileData.domPath() = mTargetPathArray[i].mDomPath;
-    inputs[i] = fileData;
+  for (unsigned i = 0; i < mTargetBlobImplArray.Length(); i++) {
+    BlobParent* blobParent =
+      BlobParent::GetOrCreate(mRequestParent->Manager(),
+                              mTargetBlobImplArray[i]);
+    inputs[i] = FileSystemFileResponse(blobParent, nullptr);
   }
 
   FileSystemFilesResponse response;
   response.data().SwapElements(inputs);
   return response;
 }
 
 nsresult
--- a/dom/filesystem/GetFilesTask.h
+++ b/dom/filesystem/GetFilesTask.h
@@ -55,22 +55,17 @@ private:
   HandlerCallback() override;
 
   RefPtr<Promise> mPromise;
   RefPtr<Directory> mDirectory;
   nsCOMPtr<nsIFile> mTargetPath;
   bool mRecursiveFlag;
 
   // We store the fullpath and the dom path of Files.
-  struct FileData {
-    nsString mRealPath;
-    nsString mDOMPath;
-  };
-
-  FallibleTArray<FileData> mTargetData;
+  FallibleTArray<RefPtr<File>> mTargetData;
 };
 
 class GetFilesTaskParent final : public FileSystemTaskParentBase
                                , public GetFilesHelperBase
 {
 public:
   static already_AddRefed<GetFilesTaskParent>
   Create(FileSystemBase* aFileSystem,
--- a/dom/filesystem/PFileSystemParams.ipdlh
+++ b/dom/filesystem/PFileSystemParams.ipdlh
@@ -26,16 +26,17 @@ struct FileSystemCreateFileParams
   FileSystemFileDataValue data;
   bool replace;
 };
 
 struct FileSystemGetDirectoryListingParams
 {
   nsString filesystem;
   nsString realPath;
+  nsString domPath;
 
   // 'filters' could be an array rather than a semicolon separated string
   // (we'd then use InfallibleTArray<nsString> internally), but that is
   // wasteful.  E10s requires us to pass the filters over as a string anyway,
   // so avoiding using an array avoids serialization on the side passing the
   // filters.  Since an nsString can share its buffer when copied,
   // using that instead of InfallibleTArray<nsString> makes copying the filters
   // around in any given process a bit more efficient too, since copying a
--- a/dom/filesystem/PFileSystemRequest.ipdl
+++ b/dom/filesystem/PFileSystemRequest.ipdl
@@ -7,29 +7,27 @@
 include protocol PBackground;
 include protocol PBlob;
 
 namespace mozilla {
 namespace dom {
 
 struct FileSystemFileResponse
 {
-  nsString realPath;
-  nsString domPath;
+  PBlob blob;
 };
 
 struct FileSystemDirectoryResponse
 {
   nsString realPath;
 };
 
 struct FileSystemDirectoryListingResponseFile
 {
-  // This is the full real path for the file that we are sending via IPC.
-  nsString fileRealPath;
+  PBlob blob;
 };
 
 struct FileSystemDirectoryListingResponseDirectory
 {
   // This is the full real path for the directory that we are sending via IPC.
   nsString directoryRealPath;
 };