Bug 1068975 - Remove FileInfo from File; r=baku
authorJan Varga <jan.varga@gmail.com>
Wed, 09 Sep 2015 13:15:14 +0200
changeset 294159 a6a759b2431a1af78df2bc8145e0c2c07791b22a
parent 294158 ac51f970e85df6b96344c11f3e2f056fb30dfdb9
child 294160 2739625b99bf100ec26ab52f373ebf7fd156f78f
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1068975
milestone43.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 1068975 - Remove FileInfo from File; r=baku
dom/base/File.cpp
dom/base/File.h
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/FileSnapshot.h
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBDatabase.h
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/IndexedDatabaseManager.h
dom/indexedDB/moz.build
dom/ipc/Blob.cpp
dom/ipc/ContentParent.cpp
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -375,28 +375,16 @@ Blob::Constructor(
 }
 
 int64_t
 Blob::GetFileId()
 {
   return mImpl->GetFileId();
 }
 
-void
-Blob::AddFileInfo(indexedDB::FileInfo* aFileInfo)
-{
-  mImpl->AddFileInfo(aFileInfo);
-}
-
-indexedDB::FileInfo*
-Blob::GetFileInfo(indexedDB::FileManager* aFileManager)
-{
-  return mImpl->GetFileInfo(aFileManager);
-}
-
 bool
 Blob::IsMemoryFile() const
 {
   return mImpl->IsMemoryFile();
 }
 
 void
 Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
@@ -457,46 +445,16 @@ File::CreateMemoryFile(nsISupports* aPar
 /* static */ already_AddRefed<File>
 File::CreateFromFile(nsISupports* aParent, nsIFile* aFile, bool aTemporary)
 {
   nsRefPtr<File> file = new File(aParent, new BlobImplFile(aFile, aTemporary));
   return file.forget();
 }
 
 /* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, const nsAString& aContentType,
-                     uint64_t aLength, nsIFile* aFile,
-                     indexedDB::FileInfo* aFileInfo)
-{
-  nsRefPtr<File> file = new File(aParent,
-    new BlobImplFile(aContentType, aLength, aFile, aFileInfo));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, const nsAString& aName,
-                     const nsAString& aContentType,
-                     uint64_t aLength, nsIFile* aFile,
-                     indexedDB::FileInfo* aFileInfo)
-{
-  nsRefPtr<File> file = new File(aParent,
-    new BlobImplFile(aName, aContentType, aLength, aFile, aFileInfo));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                     indexedDB::FileInfo* aFileInfo)
-{
-  nsRefPtr<File> file = new File(aParent,
-    new BlobImplFile(aFile, aFileInfo));
-  return file.forget();
-}
-
-/* static */ already_AddRefed<File>
 File::CreateFromFile(nsISupports* aParent, nsIFile* aFile,
                      const nsAString& aName, const nsAString& aContentType)
 {
   nsRefPtr<File> file = new File(aParent,
     new BlobImplFile(aFile, aName, aContentType));
   return file.forget();
 }
 
@@ -795,88 +753,17 @@ void
 BlobImplBase::SetLastModified(int64_t aLastModified)
 {
   mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
 }
 
 int64_t
 BlobImplBase::GetFileId()
 {
-  int64_t id = -1;
-
-  if (IsStoredFile() && IsWholeFile() && !IsSnapshot()) {
-    if (!indexedDB::IndexedDatabaseManager::IsClosed()) {
-      indexedDB::IndexedDatabaseManager::FileMutex().Lock();
-    }
-
-    NS_ASSERTION(!mFileInfos.IsEmpty(),
-                 "A stored file must have at least one file info!");
-
-    nsRefPtr<indexedDB::FileInfo>& fileInfo = mFileInfos.ElementAt(0);
-    if (fileInfo) {
-      id =  fileInfo->Id();
-    }
-
-    if (!indexedDB::IndexedDatabaseManager::IsClosed()) {
-      indexedDB::IndexedDatabaseManager::FileMutex().Unlock();
-    }
-  }
-
-  return id;
-}
-
-void
-BlobImplBase::AddFileInfo(indexedDB::FileInfo* aFileInfo)
-{
-  if (indexedDB::IndexedDatabaseManager::IsClosed()) {
-    NS_ERROR("Shouldn't be called after shutdown!");
-    return;
-  }
-
-  nsRefPtr<indexedDB::FileInfo> fileInfo = aFileInfo;
-
-  MutexAutoLock lock(indexedDB::IndexedDatabaseManager::FileMutex());
-
-  NS_ASSERTION(!mFileInfos.Contains(aFileInfo),
-               "Adding the same file info agan?!");
-
-  nsRefPtr<indexedDB::FileInfo>* element = mFileInfos.AppendElement();
-  element->swap(fileInfo);
-}
-
-indexedDB::FileInfo*
-BlobImplBase::GetFileInfo(indexedDB::FileManager* aFileManager)
-{
-  if (indexedDB::IndexedDatabaseManager::IsClosed()) {
-    NS_ERROR("Shouldn't be called after shutdown!");
-    return nullptr;
-  }
-
-  // A slice created from a stored file must keep the file info alive.
-  // However, we don't support sharing of slices yet, so the slice must be
-  // copied again. That's why we have to ignore the first file info.
-  // Snapshots are handled in a similar way (they have to be copied).
-  uint32_t startIndex;
-  if (IsStoredFile() && (!IsWholeFile() || IsSnapshot())) {
-    startIndex = 1;
-  }
-  else {
-    startIndex = 0;
-  }
-
-  MutexAutoLock lock(indexedDB::IndexedDatabaseManager::FileMutex());
-
-  for (uint32_t i = startIndex; i < mFileInfos.Length(); i++) {
-    nsRefPtr<indexedDB::FileInfo>& fileInfo = mFileInfos.ElementAt(i);
-    if (fileInfo->Manager() == aFileManager) {
-      return fileInfo;
-    }
-  }
-
-  return nullptr;
+  return -1;
 }
 
 nsresult
 BlobImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
                           nsACString& aContentType, nsACString& aCharset)
 {
   MOZ_ASSERT(aContentLength);
 
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -3,25 +3,23 @@
 /* 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/Date.h"
-#include "mozilla/dom/indexedDB/FileInfo.h"
-#include "mozilla/dom/indexedDB/FileManager.h"
-#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMBlob.h"
 #include "nsIFile.h"
 #include "nsIMutable.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsString.h"
@@ -34,20 +32,16 @@ class nsIInputStream;
 
 #define BLOBIMPL_IID \
   { 0xbccb3275, 0x6778, 0x4ac5, \
     { 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
 
 namespace mozilla {
 namespace dom {
 
-namespace indexedDB {
-class FileInfo;
-} // namespace indexedDB
-
 struct BlobPropertyBag;
 struct ChromeFilePropertyBag;
 struct FilePropertyBag;
 class BlobImpl;
 class File;
 class OwningArrayBufferOrArrayBufferViewOrBlobOrString;
 
 /**
@@ -131,22 +125,16 @@ public:
               ErrorResult& aRv);
 
   void
   GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv);
 
   int64_t
   GetFileId();
 
-  indexedDB::FileInfo*
-  GetFileInfo(indexedDB::FileManager* aFileManager);
-
-  void
-  AddFileInfo(indexedDB::FileInfo* aFileInfo);
-
   // WebIDL methods
   nsISupports* GetParentObject() const
   {
     return mParent;
   }
 
   bool
   IsMemoryFile() const;
@@ -217,30 +205,16 @@ public:
   CreateMemoryFile(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
                    const nsAString& aName, const nsAString& aContentType,
                    int64_t aLastModifiedDate);
 
   static already_AddRefed<File>
   CreateFromFile(nsISupports* aParent, nsIFile* aFile, bool aTemporary = false);
 
   static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, const nsAString& aContentType,
-                 uint64_t aLength, nsIFile* aFile,
-                 indexedDB::FileInfo* aFileInfo);
-
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, const nsAString& aName,
-                 const nsAString& aContentType, uint64_t aLength,
-                 nsIFile* aFile, indexedDB::FileInfo* aFileInfo);
-
-  static already_AddRefed<File>
-  CreateFromFile(nsISupports* aParent, nsIFile* aFile,
-                 indexedDB::FileInfo* aFileInfo);
-
-  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;
 
@@ -340,21 +314,16 @@ public:
   virtual const nsTArray<nsRefPtr<BlobImpl>>*
   GetSubBlobImpls() const = 0;
 
   virtual void GetInternalStream(nsIInputStream** aStream,
                                  ErrorResult& aRv) = 0;
 
   virtual int64_t GetFileId() = 0;
 
-  virtual void AddFileInfo(indexedDB::FileInfo* aFileInfo) = 0;
-
-  virtual indexedDB::FileInfo*
-  GetFileInfo(indexedDB::FileManager* aFileManager) = 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;
@@ -512,21 +481,16 @@ public:
   virtual void GetInternalStream(nsIInputStream** aStream,
                                  ErrorResult& aRv) override
   {
     aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   }
 
   virtual int64_t GetFileId() override;
 
-  virtual void AddFileInfo(indexedDB::FileInfo* aFileInfo) override;
-
-  virtual indexedDB::FileInfo*
-  GetFileInfo(indexedDB::FileManager* aFileManager) 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;
@@ -583,72 +547,45 @@ public:
     return mDirState == BlobDirState::eIsDir;
   }
 
   virtual BlobDirState GetDirState() const override
   {
     return mDirState;
   }
 
-  virtual bool IsStoredFile() const
-  {
-    return false;
-  }
-
-  virtual bool IsWholeFile() const
-  {
-    NS_NOTREACHED("Should only be called on dom blobs backed by files!");
-    return false;
-  }
-
-  virtual bool IsSnapshot() const
-  {
-    return false;
-  }
-
   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();
 
-  indexedDB::FileInfo* GetFileInfo() const
-  {
-    NS_ASSERTION(IsStoredFile(), "Should only be called on stored files!");
-    NS_ASSERTION(!mFileInfos.IsEmpty(), "Must have at least one file info!");
-
-    return mFileInfos.ElementAt(0);
-  }
-
   bool mIsFile;
   bool mImmutable;
   BlobDirState mDirState;
 
   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;
-
-  // Protected by IndexedDatabaseManager::FileMutex()
-  nsTArray<nsRefPtr<indexedDB::FileInfo>> mFileInfos;
 };
 
 /**
  * This class may be used off the main thread, and in particular, its
  * constructor and destructor may not run on the same thread.  Be careful!
  */
 class BlobImplMemory final : public BlobImplBase
 {
@@ -786,113 +723,65 @@ class BlobImplFile : public BlobImplBase
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // Create as a file
   explicit BlobImplFile(nsIFile* aFile, bool aTemporary = false)
     : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
-    , mStoredFile(false)
     , mIsTemporary(aTemporary)
   {
     NS_ASSERTION(mFile, "must have file");
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
     mFile->GetLeafName(mName);
   }
 
-  BlobImplFile(nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
-    : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-    , mStoredFile(true)
-    , mIsTemporary(false)
-  {
-    NS_ASSERTION(mFile, "must have file");
-    NS_ASSERTION(aFileInfo, "must have file info");
-    // Lazily get the content type and size
-    mContentType.SetIsVoid(true);
-    mFile->GetLeafName(mName);
-
-    mFileInfos.AppendElement(aFileInfo);
-  }
-
   // Create as a file
   BlobImplFile(const nsAString& aName, const nsAString& aContentType,
                uint64_t aLength, nsIFile* aFile)
     : BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
-    , mStoredFile(false)
     , mIsTemporary(false)
   {
     NS_ASSERTION(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)
-    , mStoredFile(false)
     , mIsTemporary(false)
   {
     NS_ASSERTION(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)
-    , mStoredFile(false)
     , mIsTemporary(false)
   {
     NS_ASSERTION(mFile, "must have file");
     if (aContentType.IsEmpty()) {
       // Lazily get the content type and size
       mContentType.SetIsVoid(true);
     }
   }
 
-  // Create as a stored file
-  BlobImplFile(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, nsIFile* aFile,
-               indexedDB::FileInfo* aFileInfo)
-    : BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
-    , mFile(aFile)
-    , mWholeFile(true)
-    , mStoredFile(true)
-    , mIsTemporary(false)
-  {
-    NS_ASSERTION(mFile, "must have file");
-    mFileInfos.AppendElement(aFileInfo);
-  }
-
-  // Create as a stored blob
-  BlobImplFile(const nsAString& aContentType, uint64_t aLength,
-               nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
-    : BlobImplBase(aContentType, aLength)
-    , mFile(aFile)
-    , mWholeFile(true)
-    , mStoredFile(true)
-    , mIsTemporary(false)
-  {
-    NS_ASSERTION(mFile, "must have file");
-    mFileInfos.AppendElement(aFileInfo);
-  }
-
   // Create as a file to be later initialized
   BlobImplFile()
     : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
     , mWholeFile(true)
-    , mStoredFile(false)
     , mIsTemporary(false)
   {
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
     mName.SetIsVoid(true);
   }
 
   // Overrides
@@ -925,55 +814,27 @@ protected:
 
 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)
-    , mStoredFile(aOther->mStoredFile)
     , mIsTemporary(false)
   {
     NS_ASSERTION(mFile, "must have file");
     mImmutable = aOther->mImmutable;
-
-    if (mStoredFile) {
-      indexedDB::FileInfo* fileInfo;
-
-      using indexedDB::IndexedDatabaseManager;
-
-      if (IndexedDatabaseManager::IsClosed()) {
-        fileInfo = aOther->GetFileInfo();
-      }
-      else {
-        mozilla::MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
-        fileInfo = aOther->GetFileInfo();
-      }
-
-      mFileInfos.AppendElement(fileInfo);
-    }
   }
 
   virtual already_AddRefed<BlobImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
               const nsAString& aContentType, ErrorResult& aRv) override;
 
-  virtual bool IsStoredFile() const override
-  {
-    return mStoredFile;
-  }
-
-  virtual bool IsWholeFile() const override
-  {
-    return mWholeFile;
-  }
-
   nsCOMPtr<nsIFile> mFile;
   bool mWholeFile;
-  bool mStoredFile;
   bool mIsTemporary;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_File_h
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ActorsChild.h"
 
 #include "BackgroundChildImpl.h"
-#include "FileManager.h"
 #include "IDBDatabase.h"
 #include "IDBEvents.h"
 #include "IDBFactory.h"
 #include "IDBIndex.h"
 #include "IDBMutableFile.h"
 #include "IDBObjectStore.h"
 #include "IDBMutableFile.h"
 #include "IDBRequest.h"
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -80,16 +80,17 @@
 #include "nsISupports.h"
 #include "nsISupportsImpl.h"
 #include "nsISupportsPriority.h"
 #include "nsIThread.h"
 #include "nsITimer.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsPrintfCString.h"
+#include "nsQueryObject.h"
 #include "nsRefPtrHashtable.h"
 #include "nsString.h"
 #include "nsThreadPool.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMCID.h"
 #include "PermissionRequestBase.h"
 #include "ProfilerHelpers.h"
 #include "prsystem.h"
@@ -109,16 +110,19 @@
   MOZ_LOG(IndexedDatabaseManager::GetLoggingModule(),                           \
          LogLevel::Debug,                                                         \
          _args )
 
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
 #define IDB_MOBILE
 #endif
 
+#define BLOB_IMPL_STORED_FILE_IID \
+  {0x6b505c84, 0x2c60, 0x4ffb, {0x8b, 0x91, 0xfe, 0x22, 0xb1, 0xec, 0x75, 0xe2}}
+
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
 using namespace mozilla::dom::quota;
 using namespace mozilla::ipc;
 
 namespace {
@@ -8374,26 +8378,30 @@ public:
   }
 
   NS_INLINE_DECL_REFCOUNTING(DatabaseLoggingInfo)
 
 private:
   ~DatabaseLoggingInfo();
 };
 
-class NonMainThreadHackBlobImpl final
+class BlobImplStoredFile final
   : public BlobImplFile
 {
-  bool mSnapshot;
-
-public:
-  NonMainThreadHackBlobImpl(nsIFile* aFile, FileInfo* aFileInfo, bool aSnapshot)
-    : BlobImplFile(aFile, aFileInfo)
+  nsRefPtr<FileInfo> mFileInfo;
+  const bool mSnapshot;
+
+public:
+  BlobImplStoredFile(nsIFile* aFile, FileInfo* aFileInfo, bool aSnapshot)
+    : BlobImplFile(aFile)
+    , mFileInfo(aFileInfo)
     , mSnapshot(aSnapshot)
   {
+    AssertIsOnBackgroundThread();
+
     // Getting the content type is not currently supported off the main thread.
     // This isn't a problem here because:
     //
     //   1. The real content type is stored in the structured clone data and
     //      that's all that the DOM will see. This blob's data will be updated
     //      during RecvSetMysteryBlobInfo().
     //   2. The nsExternalHelperAppService guesses the content type based only
     //      on the file extension. Our stored files have no extension so the
@@ -8401,26 +8409,49 @@ public:
     //      string.
     //
     // So, this is a hack to keep the nsExternalHelperAppService out of the
     // picture entirely. Eventually we should probably fix this some other way.
     mContentType.Truncate();
     mIsFile = false;
   }
 
-  virtual bool
-  IsSnapshot() const override
-  {
-    return mSnapshot;
-  }
-
-private:
-  ~NonMainThreadHackBlobImpl()
-  { }
-};
+  bool
+  IsShareable(FileManager* aFileManager) const
+  {
+    AssertIsOnBackgroundThread();
+
+    return mFileInfo->Manager() == aFileManager && !mSnapshot;
+  }
+
+  FileInfo*
+  GetFileInfo() const
+  {
+    AssertIsOnBackgroundThread();
+
+    return mFileInfo;
+  }
+
+private:
+  ~BlobImplStoredFile()
+  { }
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECLARE_STATIC_IID_ACCESSOR(BLOB_IMPL_STORED_FILE_IID)
+
+  virtual int64_t
+  GetFileId() override
+  {
+    MOZ_ASSERT(mFileInfo);
+
+    return mFileInfo->Id();
+  }
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(BlobImplStoredFile, BLOB_IMPL_STORED_FILE_IID)
 
 class QuotaClient final
   : public mozilla::dom::quota::Client
   , public nsIObserver
 {
   // The number of seconds we will wait after receiving the idle-daily
   // notification before beginning maintenance.
   static const uint32_t kIdleObserverTimeSec = 1;
@@ -9089,20 +9120,19 @@ ConvertBlobsToActors(PBackgroundParent* 
           IDB_REPORT_INTERNAL_ERR();
           return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
         }
 
         MOZ_ALWAYS_TRUE(aActors.AppendElement(NullableMutableFile(actor),
                                               fallible));
       }
     } else {
-      nsRefPtr<BlobImpl> impl =
-        new NonMainThreadHackBlobImpl(nativeFile,
-                                      file.mFileInfo,
-                                      /* aSnapshot */ false);
+      nsRefPtr<BlobImpl> impl = new BlobImplStoredFile(nativeFile,
+                                                       file.mFileInfo,
+                                                       /* aSnapshot */ false);
 
       PBlobParent* actor =
         BackgroundParent::GetOrCreateActorForBlobImpl(aBackgroundActor, impl);
       if (!actor) {
         // This can only fail if the child has crashed.
         IDB_REPORT_INTERNAL_ERR();
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
@@ -13144,20 +13174,25 @@ Database::AllocPBackgroundIDBDatabaseFil
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aBlobParent);
 
   nsRefPtr<BlobImpl> blobImpl =
     static_cast<BlobParent*>(aBlobParent)->GetBlobImpl();
   MOZ_ASSERT(blobImpl);
 
+  nsRefPtr<FileInfo> fileInfo;
   nsRefPtr<DatabaseFile> actor;
 
-  if (nsRefPtr<FileInfo> fileInfo = blobImpl->GetFileInfo(mFileManager)) {
+  nsRefPtr<BlobImplStoredFile> storedFileImpl = do_QueryObject(blobImpl);
+  if (storedFileImpl && storedFileImpl->IsShareable(mFileManager)) {
     // This blob was previously shared with the child.
+    fileInfo = storedFileImpl->GetFileInfo();
+    MOZ_ASSERT(fileInfo);
+
     actor = new DatabaseFile(fileInfo);
   } else {
     // This is a blob we haven't seen before.
     fileInfo = mFileManager->GetNewFileInfo();
     MOZ_ASSERT(fileInfo);
 
     actor = new DatabaseFile(blobImpl, fileInfo);
   }
@@ -16093,16 +16128,24 @@ FileManager::GetUsage(nsIFile* aDirector
     return rv;
   }
 
   *aUsage = usage;
   return NS_OK;
 }
 
 /*******************************************************************************
+ * FileImplStoredFile
+ ******************************************************************************/
+
+NS_IMPL_ISUPPORTS_INHERITED(BlobImplStoredFile,
+                            BlobImplFile,
+                            BlobImplStoredFile)
+
+/*******************************************************************************
  * QuotaClient
  ******************************************************************************/
 
 QuotaClient* QuotaClient::sInstance = nullptr;
 
 QuotaClient::QuotaClient()
   : mMaintenanceStartTime(0)
   , mMaintenanceRunId(0)
@@ -19033,17 +19076,17 @@ MutableFile::CreateStream(bool aReadOnly
 }
 
 already_AddRefed<BlobImpl>
 MutableFile::CreateBlobImpl()
 {
   AssertIsOnBackgroundThread();
 
   nsRefPtr<BlobImpl> blobImpl =
-    new NonMainThreadHackBlobImpl(mFile, mFileInfo, /* aSnapshot */ true);
+    new BlobImplStoredFile(mFile, mFileInfo, /* aSnapshot */ true);
   return blobImpl.forget();
 }
 
 PBackgroundFileHandleParent*
 MutableFile::AllocPBackgroundFileHandleParent(const FileMode& aMode)
 {
   AssertIsOnBackgroundThread();
 
--- a/dom/indexedDB/FileSnapshot.h
+++ b/dom/indexedDB/FileSnapshot.h
@@ -124,28 +124,16 @@ private:
                     ErrorResult& aRv) override;
 
   virtual int64_t
   GetFileId() override
   {
     return mBlobImpl->GetFileId();
   }
 
-  virtual void
-  AddFileInfo(FileInfo* aFileInfo) override
-  {
-    return mBlobImpl->AddFileInfo(aFileInfo);
-  }
-
-  virtual FileInfo*
-  GetFileInfo(FileManager* aFileManager) override
-  {
-    return mBlobImpl->GetFileInfo(aFileManager);
-  }
-
   virtual nsresult
   GetSendInfo(nsIInputStream** aBody,
               uint64_t* aContentLength,
               nsACString& aContentType,
               nsACString& aCharset) override
   {
     return mBlobImpl->GetSendInfo(aBody,
                                   aContentLength,
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IDBDatabase.h"
 
 #include "FileInfo.h"
-#include "FileManager.h"
 #include "IDBEvents.h"
 #include "IDBFactory.h"
 #include "IDBIndex.h"
 #include "IDBMutableFile.h"
 #include "IDBObjectStore.h"
 #include "IDBRequest.h"
 #include "IDBTransaction.h"
 #include "IDBFactory.h"
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -33,17 +33,16 @@ class DOMStringList;
 struct IDBObjectStoreParameters;
 template <class> class Optional;
 class StringOrStringSequence;
 
 namespace indexedDB {
 
 class BackgroundDatabaseChild;
 class DatabaseSpec;
-class FileManager;
 class IDBFactory;
 class IDBMutableFile;
 class IDBObjectStore;
 class IDBOpenDBRequest;
 class IDBRequest;
 class IDBTransaction;
 class PBackgroundIDBDatabaseFileChild;
 
@@ -64,18 +63,16 @@ class IDBDatabase final
   // and the world will explode.
   nsRefPtr<IDBFactory> mFactory;
 
   nsAutoPtr<DatabaseSpec> mSpec;
 
   // Normally null except during a versionchange transaction.
   nsAutoPtr<DatabaseSpec> mPreviousSpec;
 
-  nsRefPtr<FileManager> mFileManager;
-
   BackgroundDatabaseChild* mBackgroundActor;
 
   nsTHashtable<nsPtrHashKey<IDBTransaction>> mTransactions;
 
   nsDataHashtable<nsISupportsHashKey, PBackgroundIDBDatabaseFileChild*>
     mFileActors;
 
   nsTHashtable<nsISupportsHashKey> mReceivedBlobs;
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -26,16 +26,18 @@
 #include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Logging.h"
 
+#include "FileInfo.h"
+#include "FileManager.h"
 #include "IDBEvents.h"
 #include "IDBFactory.h"
 #include "IDBKeyRange.h"
 #include "IDBRequest.h"
 #include "ProfilerHelpers.h"
 #include "WorkerScope.h"
 #include "WorkerPrivate.h"
 
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -198,17 +198,17 @@ private:
 
   // Maintains a list of all file managers per origin. This list isn't
   // protected by any mutex but it is only ever touched on the IO thread.
   nsClassHashtable<nsCStringHashKey, FileManagerInfo> mFileManagerInfos;
 
   nsClassHashtable<nsRefPtrHashKey<FileManager>,
                    nsTArray<int64_t>> mPendingDeleteInfos;
 
-  // Lock protecting FileManager.mFileInfos and BlobImplBase.mFileInfos
+  // Lock protecting FileManager.mFileInfos.
   // It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt
   // and FileInfo.mSliceRefCnt
   mozilla::Mutex mFileMutex;
 
 #ifdef ENABLE_INTL_API
   nsCString mLocale;
 #endif
 
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -17,18 +17,16 @@ XPCSHELL_TESTS_MANIFESTS += [
     'test/unit/xpcshell-parent-process.ini'
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     MOCHITEST_MANIFESTS += ['test/mochitest-intl-api.ini']
 
 EXPORTS.mozilla.dom.indexedDB += [
     'ActorsParent.h',
-    'FileInfo.h',
-    'FileManager.h',
     'FileSnapshot.h',
     'IDBCursor.h',
     'IDBDatabase.h',
     'IDBEvents.h',
     'IDBFactory.h',
     'IDBFileHandle.h',
     'IDBFileRequest.h',
     'IDBIndex.h',
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -2012,22 +2012,16 @@ public:
   GetSubBlobImpls() const override;
 
   virtual void
   GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv) override;
 
   virtual int64_t
   GetFileId() override;
 
-  virtual void
-  AddFileInfo(FileInfo* aFileInfo) override;
-
-  virtual FileInfo*
-  GetFileInfo(FileManager* aFileManager) override;
-
   virtual nsresult
   GetSendInfo(nsIInputStream** aBody,
               uint64_t* aContentLength,
               nsACString& aContentType,
               nsACString& aCharset) override;
 
   virtual nsresult
   GetMutable(bool* aMutable) const override;
@@ -2758,30 +2752,16 @@ RemoteBlobImpl::GetInternalStream(nsIInp
 
 int64_t
 BlobParent::
 RemoteBlobImpl::GetFileId()
 {
   return mBlobImpl->GetFileId();
 }
 
-void
-BlobParent::
-RemoteBlobImpl::AddFileInfo(FileInfo* aFileInfo)
-{
-  return mBlobImpl->AddFileInfo(aFileInfo);
-}
-
-FileInfo*
-BlobParent::
-RemoteBlobImpl::GetFileInfo(FileManager* aFileManager)
-{
-  return mBlobImpl->GetFileInfo(aFileManager);
-}
-
 nsresult
 BlobParent::
 RemoteBlobImpl::GetSendInfo(nsIInputStream** aBody,
                             uint64_t* aContentLength,
                             nsACString& aContentType,
                             nsACString& aCharset)
 {
   return mBlobImpl->GetSendInfo(aBody,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -51,16 +51,17 @@
 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
 #include "mozilla/dom/PFMRadioParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
 #include "mozilla/dom/cellbroadcast/CellBroadcastParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
 #include "mozilla/dom/icc/IccParent.h"
+#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "mozilla/dom/mobileconnection/MobileConnectionParent.h"
 #include "mozilla/dom/mobilemessage/SmsParent.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/PresentationParent.h"
 #include "mozilla/dom/PPresentationParent.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/telephony/TelephonyParent.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"