Backed out 4 changesets (bug 1695906, bug 1686031) for causing bustages in ActorsParent.cpp
authorAlexandru Michis <malexandru@mozilla.com>
Tue, 09 Mar 2021 23:06:01 +0200
changeset 570369 7adfa8f8a78c15faf8c213963bd00826b0ea0a01
parent 570368 ced2f37c88339471b11b21acb0342adf67ca4daa
child 570370 df94cbb3007d4edf4ccd67b72ad7eda50c074603
push id138071
push usermalexandru@mozilla.com
push dateTue, 09 Mar 2021 22:47:42 +0000
treeherderautoland@df94cbb3007d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1695906, 1686031
milestone88.0a1
backs out43a39c4915482bf1e684fc5829f4640f259572aa
9be2fd0b5b6a4ece2514a70d1c8b3bf3ca8b9ded
f483f50d292a1da61bc1294bb832522b1aa65b85
470d617d76739c4d09327b034e582fa7ec445671
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 4 changesets (bug 1695906, bug 1686031) for causing bustages in ActorsParent.cpp CLOSED TREE Backed out changeset 43a39c491548 (bug 1686031) Backed out changeset 9be2fd0b5b6a (bug 1686031) Backed out changeset f483f50d292a (bug 1695906) Backed out changeset 470d617d7673 (bug 1686031)
dom/indexedDB/ActorsParent.cpp
dom/quota/ActorsParent.cpp
dom/quota/OriginMetadata.h
dom/quota/QuotaManager.h
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -5090,22 +5090,22 @@ class DeleteFilesRunnable final : public
   // OpenDirectoryListener overrides.
   virtual void DirectoryLockAcquired(DirectoryLock* aLock) override;
 
   virtual void DirectoryLockFailed() override;
 };
 
 class Maintenance final : public Runnable, public OpenDirectoryListener {
   struct DirectoryInfo final {
-    InitializedOnce<const FullOriginMetadata> mFullOriginMetadata;
+    InitializedOnce<const OriginMetadata> mOriginMetadata;
     InitializedOnce<const nsTArray<nsString>> mDatabasePaths;
     const PersistenceType mPersistenceType;
 
     DirectoryInfo(PersistenceType aPersistenceType,
-                  FullOriginMetadata aFullOriginMetadata,
+                  OriginMetadata aOriginMetadata,
                   nsTArray<nsString>&& aDatabasePaths);
 
     DirectoryInfo(const DirectoryInfo& aOther) = delete;
     DirectoryInfo(DirectoryInfo&& aOther) = delete;
 
     ~DirectoryInfo() { MOZ_COUNT_DTOR(Maintenance::DirectoryInfo); }
   };
 
@@ -5249,25 +5249,25 @@ class Maintenance final : public Runnabl
   NS_DECL_NSIRUNNABLE
 
   // OpenDirectoryListener overrides.
   void DirectoryLockAcquired(DirectoryLock* aLock) override;
 
   void DirectoryLockFailed() override;
 };
 
-Maintenance::DirectoryInfo::DirectoryInfo(
-    PersistenceType aPersistenceType, FullOriginMetadata aFullOriginMetadata,
-    nsTArray<nsString>&& aDatabasePaths)
-    : mFullOriginMetadata(std::move(aFullOriginMetadata)),
+Maintenance::DirectoryInfo::DirectoryInfo(PersistenceType aPersistenceType,
+                                          OriginMetadata aOriginMetadata,
+                                          nsTArray<nsString>&& aDatabasePaths)
+    : mOriginMetadata(std::move(aOriginMetadata)),
       mDatabasePaths(std::move(aDatabasePaths)),
       mPersistenceType(aPersistenceType) {
   MOZ_ASSERT(aPersistenceType != PERSISTENCE_TYPE_INVALID);
-  MOZ_ASSERT(!mFullOriginMetadata->mGroup.IsEmpty());
-  MOZ_ASSERT(!mFullOriginMetadata->mOrigin.IsEmpty());
+  MOZ_ASSERT(!mOriginMetadata->mGroup.IsEmpty());
+  MOZ_ASSERT(!mOriginMetadata->mOrigin.IsEmpty());
 #ifdef DEBUG
   MOZ_ASSERT(!mDatabasePaths->IsEmpty());
   for (const nsString& databasePath : *mDatabasePaths) {
     MOZ_ASSERT(!databasePath.IsEmpty());
   }
 #endif
 
   MOZ_COUNT_CTOR(Maintenance::DirectoryInfo);
@@ -13581,41 +13581,46 @@ nsresult Maintenance::DirectoryWork() {
                           GetDirEntryKind(*originDir));
 
           switch (dirEntryKind) {
             case nsIFileKind::ExistsAsFile:
               break;
 
             case nsIFileKind::ExistsAsDirectory: {
               // Get the necessary information about the origin
-              // (LoadFullOriginMetadataWithRestore also checks if it's a valid
+              // (GetDirectoryMetadata2WithRestore also checks if it's a valid
               // origin).
 
               IDB_TRY_INSPECT(
                   const auto& metadata,
-                  quotaManager->LoadFullOriginMetadataWithRestore(originDir),
+                  quotaManager
+                      ->GetDirectoryMetadataWithOriginMetadata2WithRestore(
+                          originDir),
                   // Not much we can do here...
                   Ok{});
 
               // Don't do any maintenance for private browsing databases, which
               // are only temporary.
-              if (OriginAttributes::IsPrivateBrowsing(metadata.mOrigin)) {
+              if (OriginAttributes::IsPrivateBrowsing(
+                      metadata.mOriginMetadata.mOrigin)) {
                 return Ok{};
               }
 
               if (persistent) {
                 // We have to check that all persistent origins are cleaned up,
                 // but there's no way to do that by one call, we need to
                 // initialize (and possibly clean up) them one by one
                 // (EnsureTemporaryStorageIsInitialized cleans up only
                 // non-persistent origins).
 
                 IDB_TRY_UNWRAP(
                     const DebugOnly<bool> created,
-                    quotaManager->EnsurePersistentOriginIsInitialized(metadata)
+                    quotaManager
+                        ->EnsurePersistentOriginIsInitialized(
+                            metadata.mOriginMetadata)
                         .map([](const auto& res) { return res.second; }),
                     // Not much we can do here...
                     Ok{});
 
                 // We found this origin directory by traversing the repository,
                 // so EnsurePersistentOriginIsInitialized shouldn't report that
                 // a new directory has been created.
                 MOZ_ASSERT(!created);
@@ -13677,17 +13682,18 @@ nsresult Maintenance::DirectoryWork() {
                         // iterating.
                         break;
                     }
 
                     return Ok{};
                   }));
 
               if (!databasePaths.IsEmpty()) {
-                mDirectoryInfos.EmplaceBack(persistenceType, metadata,
+                mDirectoryInfos.EmplaceBack(persistenceType,
+                                            metadata.mOriginMetadata,
                                             std::move(databasePaths));
               }
 
               break;
             }
 
             case nsIFileKind::DoesNotExist:
               // Ignore files that got removed externally while iterating.
@@ -13753,27 +13759,27 @@ nsresult Maintenance::BeginDatabaseMaint
 
   for (DirectoryInfo& directoryInfo : mDirectoryInfos) {
     RefPtr<DirectoryLock> directoryLock;
 
     for (const nsString& databasePath : *directoryInfo.mDatabasePaths) {
       if (Helper::IsSafeToRunMaintenance(databasePath)) {
         if (!directoryLock) {
           directoryLock = mDirectoryLock->Specialize(
-              directoryInfo.mPersistenceType,
-              *directoryInfo.mFullOriginMetadata, Client::IDB);
+              directoryInfo.mPersistenceType, *directoryInfo.mOriginMetadata,
+              Client::IDB);
           MOZ_ASSERT(directoryLock);
         }
 
         // No key needs to be passed here, because we skip encrypted databases
         // in DoDirectoryWork as long as they are only used in private browsing
         // mode.
         const auto databaseMaintenance = MakeRefPtr<DatabaseMaintenance>(
             this, directoryLock, directoryInfo.mPersistenceType,
-            *directoryInfo.mFullOriginMetadata, databasePath, Nothing{});
+            *directoryInfo.mOriginMetadata, databasePath, Nothing{});
 
         if (!threadPool) {
           threadPool = mQuotaClient->GetOrCreateThreadPool();
           MOZ_ASSERT(threadPool);
         }
 
         MOZ_ALWAYS_SUCCEEDS(
             threadPool->Dispatch(databaseMaintenance, NS_DISPATCH_NORMAL));
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -1968,50 +1968,49 @@ void UnregisterNormalOriginOp(NormalOrig
   }
 }
 
 class StorageOperationBase {
  protected:
   struct OriginProps {
     enum Type { eChrome, eContent, eObsolete, eInvalid };
 
-    NotNull<nsCOMPtr<nsIFile>> mDirectory;
+    nsCOMPtr<nsIFile> mDirectory;
     nsString mLeafName;
     nsCString mSpec;
     OriginAttributes mAttrs;
     int64_t mTimestamp;
     OriginMetadata mOriginMetadata;
     nsCString mOriginalSuffix;
 
-    LazyInitializedOnceEarlyDestructible<const PersistenceType>
-        mPersistenceType;
     Type mType;
     bool mNeedsRestore;
     bool mNeedsRestore2;
     bool mIgnore;
 
    public:
-    explicit OriginProps(MovingNotNull<nsCOMPtr<nsIFile>> aDirectory)
-        : mDirectory(std::move(aDirectory)),
-          mTimestamp(0),
+    explicit OriginProps()
+        : mTimestamp(0),
           mType(eContent),
           mNeedsRestore(false),
           mNeedsRestore2(false),
           mIgnore(false) {}
 
-    template <typename PersistenceTypeFunc>
-    nsresult Init(PersistenceTypeFunc&& aPersistenceTypeFunc);
+    nsresult Init(nsIFile* aDirectory);
   };
 
   nsTArray<OriginProps> mOriginProps;
 
   nsCOMPtr<nsIFile> mDirectory;
 
+  const bool mPersistent;
+
  public:
-  explicit StorageOperationBase(nsIFile* aDirectory) : mDirectory(aDirectory) {
+  StorageOperationBase(nsIFile* aDirectory, bool aPersistent)
+      : mDirectory(aDirectory), mPersistent(aPersistent) {
     AssertIsOnIOThread();
   }
 
   NS_INLINE_DECL_REFCOUNTING(StorageOperationBase)
 
  protected:
   virtual ~StorageOperationBase() = default;
 
@@ -2024,18 +2023,16 @@ class StorageOperationBase {
   // method, it is only intended to read current version ".metadata-v2" files.
   // And unlike the old ".metadata" files, the ".metadata-v2" format can evolve
   // because our "storage.sqlite" lets us track the overall version of the
   // storage directory.
   nsresult GetDirectoryMetadata2(nsIFile* aDirectory, int64_t& aTimestamp,
                                  nsACString& aSuffix, nsACString& aGroup,
                                  nsACString& aOrigin, bool& aIsApp);
 
-  int64_t GetOriginLastModifiedTime(const OriginProps& aOriginProps);
-
   nsresult RemoveObsoleteOrigin(const OriginProps& aOriginProps);
 
   /**
    * Rename the origin if the origin string generation from nsIPrincipal
    * changed. This consists of renaming the origin in the metadata files and
    * renaming the origin directory itself. For simplicity, the origin in
    * metadata files is not actually updated, but the metadata files are
    * recreated instead.
@@ -2133,105 +2130,70 @@ class MOZ_STACK_CLASS OriginParser final
 
   void HandleToken(const nsDependentCSubstring& aToken);
 
   void HandleTrailingSeparator();
 };
 
 class RepositoryOperationBase : public StorageOperationBase {
  public:
-  explicit RepositoryOperationBase(nsIFile* aDirectory)
-      : StorageOperationBase(aDirectory) {}
+  RepositoryOperationBase(nsIFile* aDirectory, bool aPersistent)
+      : StorageOperationBase(aDirectory, aPersistent) {}
 
   nsresult ProcessRepository();
 
  protected:
   virtual ~RepositoryOperationBase() = default;
 
   template <typename UpgradeMethod>
   nsresult MaybeUpgradeClients(const OriginProps& aOriginsProps,
                                UpgradeMethod aMethod);
 
  private:
-  virtual PersistenceType PersistenceTypeFromSpec(const nsCString& aSpec) = 0;
-
   virtual nsresult PrepareOriginDirectory(OriginProps& aOriginProps,
                                           bool* aRemoved) = 0;
 
   virtual nsresult PrepareClientDirectory(nsIFile* aFile,
                                           const nsAString& aLeafName,
                                           bool& aRemoved);
 };
 
 class CreateOrUpgradeDirectoryMetadataHelper final
     : public RepositoryOperationBase {
   nsCOMPtr<nsIFile> mPermanentStorageDir;
 
-  // The legacy PersistenceType, before the default repository introduction.
-  enum class LegacyPersistenceType {
-    Persistent = 0,
-    Temporary
-    // The PersistenceType had also PERSISTENCE_TYPE_INVALID, but we don't need
-    // it here.
-  };
-
-  LazyInitializedOnce<const LegacyPersistenceType> mLegacyPersistenceType;
-
  public:
-  explicit CreateOrUpgradeDirectoryMetadataHelper(nsIFile* aDirectory)
-      : RepositoryOperationBase(aDirectory) {}
-
-  nsresult Init();
+  CreateOrUpgradeDirectoryMetadataHelper(nsIFile* aDirectory, bool aPersistent)
+      : RepositoryOperationBase(aDirectory, aPersistent) {}
 
  private:
-  Maybe<LegacyPersistenceType> LegacyPersistenceTypeFromFile(nsIFile& aFile,
-                                                             const fallible_t&);
-
-  PersistenceType PersistenceTypeFromLegacyPersistentSpec(
-      const nsCString& aSpec);
-
-  PersistenceType PersistenceTypeFromSpec(const nsCString& aSpec) override;
-
   nsresult MaybeUpgradeOriginDirectory(nsIFile* aDirectory);
 
   nsresult PrepareOriginDirectory(OriginProps& aOriginProps,
                                   bool* aRemoved) override;
 
   nsresult ProcessOriginDirectory(const OriginProps& aOriginProps) override;
 };
 
-class UpgradeStorageHelperBase : public RepositoryOperationBase {
-  LazyInitializedOnce<const PersistenceType> mPersistenceType;
-
+class UpgradeStorageFrom0_0To1_0Helper final : public RepositoryOperationBase {
  public:
-  explicit UpgradeStorageHelperBase(nsIFile* aDirectory)
-      : RepositoryOperationBase(aDirectory) {}
-
-  nsresult Init();
-
- private:
-  PersistenceType PersistenceTypeFromSpec(const nsCString& aSpec) override;
-};
-
-class UpgradeStorageFrom0_0To1_0Helper final : public UpgradeStorageHelperBase {
- public:
-  explicit UpgradeStorageFrom0_0To1_0Helper(nsIFile* aDirectory)
-      : UpgradeStorageHelperBase(aDirectory) {}
+  UpgradeStorageFrom0_0To1_0Helper(nsIFile* aDirectory, bool aPersistent)
+      : RepositoryOperationBase(aDirectory, aPersistent) {}
 
  private:
   nsresult PrepareOriginDirectory(OriginProps& aOriginProps,
                                   bool* aRemoved) override;
 
   nsresult ProcessOriginDirectory(const OriginProps& aOriginProps) override;
 };
 
-class UpgradeStorageFrom1_0To2_0Helper final : public UpgradeStorageHelperBase {
+class UpgradeStorageFrom1_0To2_0Helper final : public RepositoryOperationBase {
  public:
-  explicit UpgradeStorageFrom1_0To2_0Helper(nsIFile* aDirectory)
-      : UpgradeStorageHelperBase(aDirectory) {}
+  UpgradeStorageFrom1_0To2_0Helper(nsIFile* aDirectory, bool aPersistent)
+      : RepositoryOperationBase(aDirectory, aPersistent) {}
 
  private:
   nsresult MaybeRemoveMorgueDirectory(const OriginProps& aOriginProps);
 
   /**
    * Remove the origin directory if appId is present in origin attributes.
    *
    * @param aOriginProps the properties of the origin to check.
@@ -2241,51 +2203,47 @@ class UpgradeStorageFrom1_0To2_0Helper f
   Result<bool, nsresult> MaybeRemoveAppsData(const OriginProps& aOriginProps);
 
   nsresult PrepareOriginDirectory(OriginProps& aOriginProps,
                                   bool* aRemoved) override;
 
   nsresult ProcessOriginDirectory(const OriginProps& aOriginProps) override;
 };
 
-class UpgradeStorageFrom2_0To2_1Helper final : public UpgradeStorageHelperBase {
+class UpgradeStorageFrom2_0To2_1Helper final : public RepositoryOperationBase {
  public:
-  explicit UpgradeStorageFrom2_0To2_1Helper(nsIFile* aDirectory)
-      : UpgradeStorageHelperBase(aDirectory) {}
+  UpgradeStorageFrom2_0To2_1Helper(nsIFile* aDirectory, bool aPersistent)
+      : RepositoryOperationBase(aDirectory, aPersistent) {}
 
  private:
   nsresult PrepareOriginDirectory(OriginProps& aOriginProps,
                                   bool* aRemoved) override;
 
   nsresult ProcessOriginDirectory(const OriginProps& aOriginProps) override;
 };
 
-class UpgradeStorageFrom2_1To2_2Helper final : public UpgradeStorageHelperBase {
+class UpgradeStorageFrom2_1To2_2Helper final : public RepositoryOperationBase {
  public:
-  explicit UpgradeStorageFrom2_1To2_2Helper(nsIFile* aDirectory)
-      : UpgradeStorageHelperBase(aDirectory) {}
+  UpgradeStorageFrom2_1To2_2Helper(nsIFile* aDirectory, bool aPersistent)
+      : RepositoryOperationBase(aDirectory, aPersistent) {}
 
  private:
   nsresult PrepareOriginDirectory(OriginProps& aOriginProps,
                                   bool* aRemoved) override;
 
   nsresult ProcessOriginDirectory(const OriginProps& aOriginProps) override;
 
   nsresult PrepareClientDirectory(nsIFile* aFile, const nsAString& aLeafName,
                                   bool& aRemoved) override;
 };
 
 class RestoreDirectoryMetadata2Helper final : public StorageOperationBase {
-  LazyInitializedOnce<const PersistenceType> mPersistenceType;
-
  public:
-  explicit RestoreDirectoryMetadata2Helper(nsIFile* aDirectory)
-      : StorageOperationBase(aDirectory) {}
-
-  nsresult Init();
+  RestoreDirectoryMetadata2Helper(nsIFile* aDirectory, bool aPersistent)
+      : StorageOperationBase(aDirectory, aPersistent) {}
 
   nsresult RestoreMetadata2File();
 
  private:
   nsresult ProcessOriginDirectory(const OriginProps& aOriginProps) override;
 };
 
 auto MakeSanitizedOriginCString(const nsACString& aOrigin) {
@@ -2311,18 +2269,19 @@ auto MakeSanitizedOriginString(const nsA
 Result<nsAutoString, nsresult> GetPathForStorage(
     nsIFile& aBaseDir, const nsAString& aStorageName) {
   QM_TRY_INSPECT(const auto& storageDir,
                  CloneFileAndAppend(aBaseDir, aStorageName));
 
   QM_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsAutoString, storageDir, GetPath));
 }
 
-int64_t GetLastModifiedTime(PersistenceType aPersistenceType, nsIFile& aFile) {
-  AssertIsOnIOThread();
+int64_t GetLastModifiedTime(nsIFile* aFile, bool aPersistent) {
+  AssertIsOnIOThread();
+  MOZ_ASSERT(aFile);
 
   class MOZ_STACK_CLASS Helper final {
    public:
     static nsresult GetLastModifiedTime(nsIFile* aFile, int64_t* aTimestamp) {
       AssertIsOnIOThread();
       MOZ_ASSERT(aFile);
       MOZ_ASSERT(aTimestamp);
 
@@ -2369,22 +2328,22 @@ int64_t GetLastModifiedTime(PersistenceT
           // Ignore files that got removed externally while iterating.
           break;
       }
 
       return NS_OK;
     }
   };
 
-  if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
+  if (aPersistent) {
     return PR_Now();
   }
 
   int64_t timestamp = INT64_MIN;
-  nsresult rv = Helper::GetLastModifiedTime(&aFile, &timestamp);
+  nsresult rv = Helper::GetLastModifiedTime(aFile, &timestamp);
   if (NS_FAILED(rv)) {
     timestamp = PR_Now();
   }
 
   return timestamp;
 }
 
 // Returns a bool indicating whether the directory was newly created.
@@ -4086,17 +4045,17 @@ nsresult QuotaManager::LoadQuota() {
           QM_TRY_INSPECT(const bool& updated,
                          MaybeUpdateGroupForOrigin(originMetadata));
 
           Unused << updated;
 
           // We don't need to update the .metadata-v2 file on disk here,
           // EnsureTemporaryOriginIsInitialized is responsible for doing that.
           // We just need to use correct group before initializing quota for the
-          // given origin. (Note that calling LoadFullOriginMetadataWithRestore
+          // given origin. (Note that calling GetDirectoryMetadata2WithRestore
           // below might update the group in the metadata file, but only as a
           // side-effect. The actual place we ensure consistency is in
           // EnsureTemporaryOriginIsInitialized.)
 
           QM_TRY_INSPECT(
               const auto& clientUsagesText,
               MOZ_TO_RESULT_INVOKE_TYPED(nsCString, stmt, GetUTF8String, 4));
 
@@ -4123,40 +4082,44 @@ nsresult QuotaManager::LoadQuota() {
 
             QM_TRY(OkIf(exists), Err(NS_ERROR_FAILURE));
 
             QM_TRY_INSPECT(const bool& isDirectory,
                            MOZ_TO_RESULT_INVOKE(directory, IsDirectory));
 
             QM_TRY(OkIf(isDirectory), Err(NS_ERROR_FAILURE));
 
-            // Calling LoadFullOriginMetadataWithRestore might update the group
+            // Calling GetDirectoryMetadata2WithRestore might update the group
             // in the metadata file, but only as a side-effect. The actual place
             // we ensure consistency is in EnsureTemporaryOriginIsInitialized.
 
-            QM_TRY_INSPECT(const auto& metadata,
-                           LoadFullOriginMetadataWithRestore(directory));
+            QM_TRY_INSPECT(
+                const auto& metadata,
+                GetDirectoryMetadataWithOriginMetadata2WithRestore(directory));
 
             QM_TRY(OkIf(lastAccessTime == metadata.mTimestamp),
                    Err(NS_ERROR_FAILURE));
 
             QM_TRY(OkIf(persisted == metadata.mPersisted),
                    Err(NS_ERROR_FAILURE));
 
             QM_TRY(OkIf(originMetadata.mPersistenceType ==
-                        metadata.mPersistenceType),
+                        metadata.mOriginMetadata.mPersistenceType),
                    Err(NS_ERROR_FAILURE));
 
-            QM_TRY(OkIf(originMetadata.mSuffix == metadata.mSuffix),
+            QM_TRY(OkIf(originMetadata.mSuffix ==
+                        metadata.mOriginMetadata.mSuffix),
                    Err(NS_ERROR_FAILURE));
 
-            QM_TRY(OkIf(originMetadata.mGroup == metadata.mGroup),
-                   Err(NS_ERROR_FAILURE));
-
-            QM_TRY(OkIf(originMetadata.mOrigin == metadata.mOrigin),
+            QM_TRY(
+                OkIf(originMetadata.mGroup == metadata.mOriginMetadata.mGroup),
+                Err(NS_ERROR_FAILURE));
+
+            QM_TRY(OkIf(originMetadata.mOrigin ==
+                        metadata.mOriginMetadata.mOrigin),
                    Err(NS_ERROR_FAILURE));
 
             QM_TRY(InitializeOrigin(originMetadata.mPersistenceType,
                                     originMetadata, lastAccessTime, persisted,
                                     directory));
           } else {
             InitQuotaForOrigin(originMetadata.mPersistenceType, originMetadata,
                                clientUsages, usage, lastAccessTime, persisted);
@@ -4526,119 +4489,124 @@ Result<nsCOMPtr<nsIFile>, nsresult> Quot
   QM_TRY_UNWRAP(auto directory,
                 QM_NewLocalFile(GetStoragePath(aPersistenceType)));
 
   QM_TRY(directory->Append(MakeSanitizedOriginString(aASCIIOrigin)));
 
   return directory;
 }
 
-nsresult QuotaManager::RestoreDirectoryMetadata2(nsIFile* aDirectory) {
+nsresult QuotaManager::RestoreDirectoryMetadata2(nsIFile* aDirectory,
+                                                 bool aPersistent) {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
   MOZ_ASSERT(mStorageConnection);
 
   RefPtr<RestoreDirectoryMetadata2Helper> helper =
-      new RestoreDirectoryMetadata2Helper(aDirectory);
-
-  QM_TRY(helper->Init());
+      new RestoreDirectoryMetadata2Helper(aDirectory, aPersistent);
 
   QM_TRY(helper->RestoreMetadata2File());
 
   return NS_OK;
 }
 
-Result<FullOriginMetadata, nsresult> QuotaManager::LoadFullOriginMetadata(
+Result<QuotaManager::GetDirectoryResultWithOriginMetadata, nsresult>
+QuotaManager::GetDirectoryMetadataWithOriginMetadata2(
     nsIFile* aDirectory, PersistenceType aPersistenceType) {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aDirectory);
   MOZ_ASSERT(mStorageConnection);
 
   QM_TRY_INSPECT(const auto& binaryStream,
                  GetBinaryInputStream(*aDirectory,
                                       nsLiteralString(METADATA_V2_FILE_NAME)));
 
-  FullOriginMetadata fullOriginMetadata;
-
-  QM_TRY_UNWRAP(fullOriginMetadata.mTimestamp,
-                MOZ_TO_RESULT_INVOKE(binaryStream, Read64));
-
-  QM_TRY_UNWRAP(fullOriginMetadata.mPersisted,
-                MOZ_TO_RESULT_INVOKE(binaryStream, ReadBoolean));
+  QM_TRY_INSPECT(const uint64_t& timestamp,
+                 MOZ_TO_RESULT_INVOKE(binaryStream, Read64));
+
+  QM_TRY_INSPECT(const bool& persisted,
+                 MOZ_TO_RESULT_INVOKE(binaryStream, ReadBoolean));
 
   QM_TRY_INSPECT(const bool& reservedData1,
                  MOZ_TO_RESULT_INVOKE(binaryStream, Read32));
   Unused << reservedData1;
 
   // XXX Use for the persistence type.
   QM_TRY_INSPECT(const bool& reservedData2,
                  MOZ_TO_RESULT_INVOKE(binaryStream, Read32));
   Unused << reservedData2;
 
-  fullOriginMetadata.mPersistenceType = aPersistenceType;
+  OriginMetadata originMetadata;
+
+  originMetadata.mPersistenceType = aPersistenceType;
 
   QM_TRY_UNWRAP(
-      fullOriginMetadata.mSuffix,
+      originMetadata.mSuffix,
       MOZ_TO_RESULT_INVOKE_TYPED(nsCString, binaryStream, ReadCString));
 
   QM_TRY_UNWRAP(
-      fullOriginMetadata.mGroup,
+      originMetadata.mGroup,
       MOZ_TO_RESULT_INVOKE_TYPED(nsCString, binaryStream, ReadCString));
 
   QM_TRY_UNWRAP(
-      fullOriginMetadata.mOrigin,
+      originMetadata.mOrigin,
       MOZ_TO_RESULT_INVOKE_TYPED(nsCString, binaryStream, ReadCString));
 
   // Currently unused (used to be isApp).
   QM_TRY_INSPECT(const bool& dummy,
                  MOZ_TO_RESULT_INVOKE(binaryStream, ReadBoolean));
   Unused << dummy;
 
   QM_TRY(binaryStream->Close());
 
   QM_TRY_INSPECT(const bool& updated,
-                 MaybeUpdateGroupForOrigin(fullOriginMetadata));
+                 MaybeUpdateGroupForOrigin(originMetadata));
 
   if (updated) {
     // Only overwriting .metadata-v2 (used to overwrite .metadata too) to reduce
     // I/O.
-    QM_TRY(CreateDirectoryMetadata2(*aDirectory, fullOriginMetadata.mTimestamp,
-                                    fullOriginMetadata.mPersisted,
-                                    fullOriginMetadata));
-  }
-
-  return fullOriginMetadata;
-}
-
-Result<FullOriginMetadata, nsresult>
-QuotaManager::LoadFullOriginMetadataWithRestore(nsIFile* aDirectory) {
+    QM_TRY(CreateDirectoryMetadata2(*aDirectory, timestamp, persisted,
+                                    originMetadata));
+  }
+
+  return GetDirectoryResultWithOriginMetadata{
+      static_cast<int64_t>(timestamp), persisted, std::move(originMetadata)};
+}
+
+Result<QuotaManager::GetDirectoryResultWithOriginMetadata, nsresult>
+QuotaManager::GetDirectoryMetadataWithOriginMetadata2WithRestore(
+    nsIFile* aDirectory) {
   // XXX Once the persistence type is stored in the metadata file, this block
   // for getting the persistence type from the parent directory name can be
   // removed.
   nsCOMPtr<nsIFile> parentDir;
   QM_TRY(aDirectory->GetParent(getter_AddRefs(parentDir)));
 
   const auto maybePersistenceType =
       PersistenceTypeFromFile(*parentDir, fallible);
   QM_TRY(OkIf(maybePersistenceType.isSome()), Err(NS_ERROR_FAILURE));
 
   const auto& persistenceType = maybePersistenceType.value();
 
-  QM_TRY_UNWRAP(auto maybeFirstAttemptResult,
-                ([&]() -> Result<Maybe<FullOriginMetadata>, nsresult> {
-                  QM_TRY_RETURN(
-                      LoadFullOriginMetadata(aDirectory, persistenceType)
-                          .map(Some<FullOriginMetadata, FullOriginMetadata>),
-                      Maybe<FullOriginMetadata>{});
-                }()));
+  QM_TRY_UNWRAP(
+      auto maybeFirstAttemptResult,
+      ([&]() -> Result<Maybe<GetDirectoryResultWithOriginMetadata>, nsresult> {
+        QM_TRY_RETURN(
+            GetDirectoryMetadataWithOriginMetadata2(aDirectory, persistenceType)
+                .map(Some<GetDirectoryResultWithOriginMetadata,
+                          GetDirectoryResultWithOriginMetadata>),
+            Maybe<GetDirectoryResultWithOriginMetadata>{});
+      }()));
 
   if (!maybeFirstAttemptResult) {
-    QM_TRY(RestoreDirectoryMetadata2(aDirectory));
-
-    QM_TRY_RETURN(LoadFullOriginMetadata(aDirectory, persistenceType));
+    QM_TRY(RestoreDirectoryMetadata2(
+        aDirectory, persistenceType == PERSISTENCE_TYPE_PERSISTENT));
+
+    QM_TRY_RETURN(
+        GetDirectoryMetadataWithOriginMetadata2(aDirectory, persistenceType));
   }
 
   return maybeFirstAttemptResult.extract();
 }
 
 nsresult QuotaManager::InitializeRepository(PersistenceType aPersistenceType) {
   MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY ||
              aPersistenceType == PERSISTENCE_TYPE_DEFAULT);
@@ -4657,17 +4625,17 @@ nsresult QuotaManager::InitializeReposit
 #endif
 
   const auto statusKeeperFunc = [&](const nsresult rv) {
     RECORD_IN_NIGHTLY(statusKeeper, rv);
   };
 
   struct RenameAndInitInfo {
     nsCOMPtr<nsIFile> mOriginDirectory;
-    FullOriginMetadata mFullOriginMetadata;
+    OriginMetadata mOriginMetadata;
     int64_t mTimestamp;
     bool mPersisted;
   };
   nsTArray<RenameAndInitInfo> renameAndInitInfos;
 
   QM_TRY(([&]() -> Result<Ok, nsresult> {
     QM_TRY(
         CollectEachFile(
@@ -4687,68 +4655,71 @@ nsresult QuotaManager::InitializeReposit
 
                     QM_TRY_INSPECT(const auto& dirEntryKind,
                                    GetDirEntryKind(*childDirectory));
 
                     switch (dirEntryKind) {
                       case nsIFileKind::ExistsAsDirectory: {
                         QM_TRY_UNWRAP(
                             auto metadata,
-                            LoadFullOriginMetadataWithRestore(childDirectory));
+                            GetDirectoryMetadataWithOriginMetadata2WithRestore(
+                                childDirectory));
 
                         // FIXME(tt): The check for origin name consistency can
                         // be removed once we have an upgrade to traverse origin
                         // directories and check through the directory metadata
                         // files.
-                        const auto originSanitized =
-                            MakeSanitizedOriginCString(metadata.mOrigin);
+                        const auto originSanitized = MakeSanitizedOriginCString(
+                            metadata.mOriginMetadata.mOrigin);
 
                         NS_ConvertUTF16toUTF8 utf8LeafName(leafName);
                         if (!originSanitized.Equals(utf8LeafName)) {
                           QM_WARNING(
                               "The name of the origin directory (%s) doesn't "
                               "match the sanitized origin string (%s) in the "
                               "metadata file!",
                               utf8LeafName.get(), originSanitized.get());
 
                           // If it's the known case, we try to restore the
                           // origin directory name if it's possible.
                           if (originSanitized.Equals(utf8LeafName + "."_ns)) {
                             renameAndInitInfos.AppendElement(RenameAndInitInfo{
-                                std::move(childDirectory), std::move(metadata),
+                                std::move(childDirectory),
+                                std::move(metadata.mOriginMetadata),
                                 metadata.mTimestamp, metadata.mPersisted});
                             break;
                           }
 
                           // XXXtt: Try to restore the unknown cases base on the
                           // content for their metadata files. Note that if the
                           // restore fails, QM should maintain a list and ensure
                           // they won't be accessed after initialization.
                         }
 
-                        QM_TRY(ToResult(InitializeOrigin(aPersistenceType,
-                                                         metadata,
-                                                         metadata.mTimestamp,
-                                                         metadata.mPersisted,
-                                                         childDirectory))
-                                   .orElse([&childDirectory](const nsresult rv)
-                                               -> Result<Ok, nsresult> {
-                                     if (IsDatabaseCorruptionError(rv)) {
-                                       // If the origin can't be initialized due
-                                       // to corruption, this is a permanent
-                                       // condition, and we need to remove all
-                                       // data for the origin on disk.
-
-                                       QM_TRY(childDirectory->Remove(true));
-
-                                       return Ok{};
-                                     }
-
-                                     return Err(rv);
-                                   }));
+                        QM_TRY(
+                            ToResult(InitializeOrigin(aPersistenceType,
+                                                      metadata.mOriginMetadata,
+                                                      metadata.mTimestamp,
+                                                      metadata.mPersisted,
+                                                      childDirectory))
+                                .orElse([&childDirectory](const nsresult rv)
+                                            -> Result<Ok, nsresult> {
+                                  if (IsDatabaseCorruptionError(rv)) {
+                                    // If the origin can't be initialized due to
+                                    // corruption, this is a permanent
+                                    // condition, and we need to remove all data
+                                    // for the origin on disk.
+
+                                    QM_TRY(childDirectory->Remove(true));
+
+                                    return Ok{};
+                                  }
+
+                                  return Err(rv);
+                                }));
 
                         break;
                       }
 
                       case nsIFileKind::ExistsAsFile:
                         if (IsOSMetadata(leafName) || IsDotFile(leafName)) {
                           break;
                         }
@@ -4775,36 +4746,36 @@ nsresult QuotaManager::InitializeReposit
     return Ok{};
   }()));
 
   for (const auto& info : renameAndInitInfos) {
     QM_TRY(([&]() -> Result<Ok, nsresult> {
       QM_TRY(([&directory, &info, this,
                aPersistenceType]() -> Result<Ok, nsresult> {
                const auto originDirName =
-                   MakeSanitizedOriginString(info.mFullOriginMetadata.mOrigin);
+                   MakeSanitizedOriginString(info.mOriginMetadata.mOrigin);
 
                // Check if targetDirectory exist.
                QM_TRY_INSPECT(const auto& targetDirectory,
                               CloneFileAndAppend(*directory, originDirName));
 
                QM_TRY_INSPECT(const bool& exists,
                               MOZ_TO_RESULT_INVOKE(targetDirectory, Exists));
 
                if (exists) {
                  QM_TRY(info.mOriginDirectory->Remove(true));
 
                  return Ok{};
                }
 
                QM_TRY(info.mOriginDirectory->RenameTo(nullptr, originDirName));
 
-               QM_TRY(InitializeOrigin(
-                   aPersistenceType, info.mFullOriginMetadata, info.mTimestamp,
-                   info.mPersisted, targetDirectory));
+               QM_TRY(InitializeOrigin(aPersistenceType, info.mOriginMetadata,
+                                       info.mTimestamp, info.mPersisted,
+                                       targetDirectory));
 
                return Ok{};
              }()),
              OK_IN_NIGHTLY_PROPAGATE_IN_OTHERS, statusKeeperFunc);
 
       return Ok{};
     }()));
   }
@@ -5068,19 +5039,18 @@ QuotaManager::UpgradeFromPersistentStora
         return NS_OK;
       }
     }
 
     {
       // Create real metadata files for origin directories in persistent
       // storage.
       auto helper = MakeRefPtr<CreateOrUpgradeDirectoryMetadataHelper>(
-          aPersistentStorageDir);
-
-      QM_TRY(helper->Init());
+          aPersistentStorageDir,
+          /* aPersistent */ true);
 
       QM_TRY(helper->ProcessRepository());
 
       // Upgrade metadata files for origin directories in temporary storage.
       QM_TRY_INSPECT(const auto& temporaryStorageDir,
                      QM_NewLocalFile(*mTemporaryStoragePath));
 
       QM_TRY_INSPECT(const bool& exists,
@@ -5091,19 +5061,18 @@ QuotaManager::UpgradeFromPersistentStora
                        MOZ_TO_RESULT_INVOKE(temporaryStorageDir, IsDirectory));
 
         if (!isDirectory) {
           NS_WARNING("temporary entry is not a directory!");
           return NS_OK;
         }
 
         helper = MakeRefPtr<CreateOrUpgradeDirectoryMetadataHelper>(
-            temporaryStorageDir);
-
-        QM_TRY(helper->Init());
+            temporaryStorageDir,
+            /* aPersistent */ false);
 
         QM_TRY(helper->ProcessRepository());
       }
     }
 
     // And finally rename persistent to default.
     QM_TRY(aPersistentStorageDir->RenameTo(
         nullptr, nsLiteralString(DEFAULT_DIRECTORY_NAME)));
@@ -5131,20 +5100,18 @@ nsresult QuotaManager::UpgradeStorage(co
                   QM_NewLocalFile(GetStoragePath(persistenceType)));
 
     QM_TRY_INSPECT(const bool& exists, MOZ_TO_RESULT_INVOKE(directory, Exists));
 
     if (!exists) {
       continue;
     }
 
-    RefPtr<UpgradeStorageHelperBase> helper = new Helper(directory);
-
-    QM_TRY(helper->Init());
-
+    bool persistent = persistenceType == PERSISTENCE_TYPE_PERSISTENT;
+    RefPtr<RepositoryOperationBase> helper = new Helper(directory, persistent);
     QM_TRY(helper->ProcessRepository());
   }
 
 #ifdef DEBUG
   {
     QM_TRY_INSPECT(const int32_t& storageVersion,
                    MOZ_TO_RESULT_INVOKE(aConnection, GetSchemaVersion));
 
@@ -6084,39 +6051,40 @@ QuotaManager::EnsurePersistentOriginIsIn
                                         aOriginMetadata.mOrigin));
 
     if (mInitializedOrigins.Contains(aOriginMetadata.mOrigin)) {
       return std::pair(std::move(directory), false);
     }
 
     QM_TRY_INSPECT(const bool& created, EnsureOriginDirectory(*directory));
 
-    QM_TRY_INSPECT(const int64_t& timestamp,
-                   ([this, created, &directory,
-                     &aOriginMetadata]() -> Result<int64_t, nsresult> {
-                     if (created) {
-                       const int64_t timestamp = PR_Now();
-
-                       // Only creating .metadata-v2 to reduce IO.
-                       QM_TRY(CreateDirectoryMetadata2(*directory, timestamp,
-                                                       /* aPersisted */ true,
-                                                       aOriginMetadata));
-
-                       return timestamp;
-                     }
-
-                     // Get the metadata. We only use the timestamp.
-                     QM_TRY_INSPECT(
-                         const auto& metadata,
-                         LoadFullOriginMetadataWithRestore(directory));
-
-                     MOZ_ASSERT(metadata.mTimestamp <= PR_Now());
-
-                     return metadata.mTimestamp;
-                   }()));
+    QM_TRY_INSPECT(
+        const int64_t& timestamp,
+        ([this, created, &directory,
+          &aOriginMetadata]() -> Result<int64_t, nsresult> {
+          if (created) {
+            const int64_t timestamp = PR_Now();
+
+            // Only creating .metadata-v2 to reduce IO.
+            QM_TRY(CreateDirectoryMetadata2(*directory, timestamp,
+                                            /* aPersisted */ true,
+                                            aOriginMetadata));
+
+            return timestamp;
+          }
+
+          // Get the metadata. We only use the timestamp.
+          QM_TRY_INSPECT(
+              const auto& metadata,
+              GetDirectoryMetadataWithOriginMetadata2WithRestore(directory));
+
+          MOZ_ASSERT(metadata.mTimestamp <= PR_Now());
+
+          return metadata.mTimestamp;
+        }()));
 
     QM_TRY(InitializeOrigin(PERSISTENCE_TYPE_PERSISTENT, aOriginMetadata,
                             timestamp,
                             /* aPersisted */ true, directory));
 
     mInitializedOrigins.AppendElement(aOriginMetadata.mOrigin);
 
     return std::pair(std::move(directory), created);
@@ -6158,22 +6126,22 @@ QuotaManager::EnsureTemporaryOriginIsIni
                                  /* aPersisted */ false, timestamp);
 
       // Only creating .metadata-v2 to reduce IO.
       QM_TRY(CreateDirectoryMetadata2(*directory, timestamp,
                                       /* aPersisted */ false, aOriginMetadata));
     }
 
     // TODO: If the metadata file exists and we didn't call
-    //       LoadFullOriginMetadataWithRestore for it (because the quota info
+    //       GetDirectoryMetadata2WithRestore for it (because the quota info
     //       was loaded from the cache), then the group in the metadata file
     //       may be wrong, so it should be checked and eventually updated.
     //       It's not a big deal that we are not doing it here, because the
     //       origin will be marked as "accessed", so
-    //       LoadFullOriginMetadataWithRestore will be called for the metadata
+    //       GetDirectoryMetadata2WithRestore will be called for the metadata
     //       file in next session in LoadQuotaFromCache.
 
     return std::pair(std::move(directory), created);
   }();
 
   auto& info =
       mOriginInitializationInfos.LookupOrInsert(aOriginMetadata.mOrigin);
   if (!info.mTemporaryOriginAttempted) {
@@ -8433,25 +8401,28 @@ const Atomic<bool>& GetUsageOp::GetIsCan
 // XXX Remove aPersistent
 // XXX Remove aPersistenceType once GetUsageForOrigin uses the persistence
 // type from OriginMetadata
 nsresult GetUsageOp::ProcessOrigin(QuotaManager& aQuotaManager,
                                    nsIFile& aOriginDir, const bool aPersistent,
                                    const PersistenceType aPersistenceType) {
   AssertIsOnIOThread();
 
-  QM_TRY_INSPECT(const auto& metadata,
-                 aQuotaManager.LoadFullOriginMetadataWithRestore(&aOriginDir));
+  QM_TRY_INSPECT(
+      const auto& metadata,
+      aQuotaManager.GetDirectoryMetadataWithOriginMetadata2WithRestore(
+          &aOriginDir));
 
   QM_TRY_INSPECT(const auto& usageInfo,
-                 GetUsageForOrigin(aQuotaManager, aPersistenceType, metadata));
-
-  ProcessOriginInternal(&aQuotaManager, aPersistenceType, metadata.mOrigin,
-                        metadata.mTimestamp, metadata.mPersisted,
-                        usageInfo.TotalUsage().valueOr(0));
+                 GetUsageForOrigin(aQuotaManager, aPersistenceType,
+                                   metadata.mOriginMetadata));
+
+  ProcessOriginInternal(&aQuotaManager, aPersistenceType,
+                        metadata.mOriginMetadata.mOrigin, metadata.mTimestamp,
+                        metadata.mPersisted, usageInfo.TotalUsage().valueOr(0));
 
   return NS_OK;
 }
 
 nsresult GetUsageOp::DoDirectoryWork(QuotaManager& aQuotaManager) {
   AssertIsOnIOThread();
   aQuotaManager.AssertStorageIsInitialized();
 
@@ -8976,17 +8947,19 @@ void ClearRequestBase::DeleteFiles(Quota
                    // Skip the origin directory if it doesn't match the pattern.
                    if (!originScope.Matches(OriginScope::FromOrigin(
                            NS_ConvertUTF16toUTF8(leafName)))) {
                      break;
                    }
 
                    QM_TRY_INSPECT(
                        const auto& metadata,
-                       aQuotaManager.LoadFullOriginMetadataWithRestore(file));
+                       aQuotaManager
+                           .GetDirectoryMetadataWithOriginMetadata2WithRestore(
+                               file));
 
                    if (!mClientType.IsNull()) {
                      nsAutoString clientDirectoryName;
                      QM_TRY(OkIf(Client::TypeToText(mClientType.Value(),
                                                     clientDirectoryName,
                                                     fallible)),
                             Err(NS_ERROR_FAILURE));
 
@@ -9005,37 +8978,40 @@ void ClearRequestBase::DeleteFiles(Quota
                    if (NS_FAILED((file->Remove(true)))) {
                      NS_WARNING("Failed to remove directory, retrying later.");
 
                      directoriesForRemovalRetry.AppendElement(std::move(file));
                    }
 
                    const bool initialized =
                        aPersistenceType == PERSISTENCE_TYPE_PERSISTENT
-                           ? aQuotaManager.IsOriginInitialized(metadata.mOrigin)
+                           ? aQuotaManager.IsOriginInitialized(
+                                 metadata.mOriginMetadata.mOrigin)
                            : aQuotaManager.IsTemporaryStorageInitialized();
 
                    // If it hasn't been initialized, we don't need to update the
                    // quota and notify the removing client.
                    if (!initialized) {
                      break;
                    }
 
                    if (aPersistenceType != PERSISTENCE_TYPE_PERSISTENT) {
                      if (mClientType.IsNull()) {
-                       aQuotaManager.RemoveQuotaForOrigin(aPersistenceType,
-                                                          metadata);
+                       aQuotaManager.RemoveQuotaForOrigin(
+                           aPersistenceType, metadata.mOriginMetadata);
                      } else {
                        aQuotaManager.ResetUsageForClient(
-                           aPersistenceType, metadata, mClientType.Value());
+                           aPersistenceType, metadata.mOriginMetadata,
+                           mClientType.Value());
                      }
                    }
 
                    aQuotaManager.OriginClearCompleted(
-                       aPersistenceType, metadata.mOrigin, mClientType);
+                       aPersistenceType, metadata.mOriginMetadata.mOrigin,
+                       mClientType);
 
                    break;
                  }
 
                  case nsIFileKind::ExistsAsFile:
                    // Unknown files during clearing are allowed. Just warn if we
                    // find them.
                    if (!IsOSMetadata(leafName)) {
@@ -9256,18 +9232,20 @@ nsresult PersistedOp::DoDirectoryWork(Qu
   QM_TRY_INSPECT(const auto& directory,
                  aQuotaManager.GetDirectoryForOrigin(mPersistenceType.Value(),
                                                      mOriginScope.GetOrigin()));
 
   QM_TRY_INSPECT(const bool& exists, MOZ_TO_RESULT_INVOKE(directory, Exists));
 
   if (exists) {
     // Get the metadata. We only use the persisted flag.
-    QM_TRY_INSPECT(const auto& metadata,
-                   aQuotaManager.LoadFullOriginMetadataWithRestore(directory));
+    QM_TRY_INSPECT(
+        const auto& metadata,
+        aQuotaManager.GetDirectoryMetadataWithOriginMetadata2WithRestore(
+            directory));
 
     mPersisted = metadata.mPersisted;
   } else {
     // The directory has not been created yet.
     mPersisted = false;
   }
 
   return NS_OK;
@@ -9322,18 +9300,20 @@ nsresult PersistOp::DoDirectoryWork(Quot
       timestamp = PR_Now();
     }
 
     QM_TRY(CreateDirectoryMetadata2(*directory, timestamp,
                                     /* aPersisted */ true, originMetadata));
   } else {
     // Get the metadata (restore the metadata file if necessary). We only use
     // the persisted flag.
-    QM_TRY_INSPECT(const auto& metadata,
-                   aQuotaManager.LoadFullOriginMetadataWithRestore(directory));
+    QM_TRY_INSPECT(
+        const auto& metadata,
+        aQuotaManager.GetDirectoryMetadataWithOriginMetadata2WithRestore(
+            directory));
 
     if (!metadata.mPersisted) {
       QM_TRY_INSPECT(const auto& file,
                      CloneFileAndAppend(
                          *directory, nsLiteralString(METADATA_V2_FILE_NAME)));
 
       QM_TRY_INSPECT(const auto& stream,
                      GetBinaryOutputStream(*file, kUpdateFileFlag));
@@ -9453,24 +9433,26 @@ const Atomic<bool>& ListOriginsOp::GetIs
 
 nsresult ListOriginsOp::ProcessOrigin(QuotaManager& aQuotaManager,
                                       nsIFile& aOriginDir,
                                       const bool aPersistent,
                                       const PersistenceType aPersistenceType) {
   AssertIsOnIOThread();
 
   // XXX We only use metadata.mOriginMetadata.mOrigin...
-  QM_TRY_UNWRAP(auto metadata,
-                aQuotaManager.LoadFullOriginMetadataWithRestore(&aOriginDir));
-
-  if (aQuotaManager.IsOriginInternal(metadata.mOrigin)) {
+  QM_TRY_UNWRAP(
+      auto metadata,
+      aQuotaManager.GetDirectoryMetadataWithOriginMetadata2WithRestore(
+          &aOriginDir));
+
+  if (aQuotaManager.IsOriginInternal(metadata.mOriginMetadata.mOrigin)) {
     return NS_OK;
   }
 
-  mOrigins.AppendElement(std::move(metadata.mOrigin));
+  mOrigins.AppendElement(std::move(metadata.mOriginMetadata.mOrigin));
 
   return NS_OK;
 }
 
 void ListOriginsOp::GetResponse(RequestResponse& aResponse) {
   AssertIsOnOwningThread();
 
   aResponse = ListOriginsResponse();
@@ -9680,39 +9662,35 @@ nsresult StorageOperationBase::GetDirect
   aTimestamp = timestamp;
   aSuffix = suffix;
   aGroup = group;
   aOrigin = origin;
   aIsApp = isApp;
   return NS_OK;
 }
 
-int64_t StorageOperationBase::GetOriginLastModifiedTime(
-    const OriginProps& aOriginProps) {
-  return GetLastModifiedTime(*aOriginProps.mPersistenceType,
-                             *aOriginProps.mDirectory);
-}
-
 nsresult StorageOperationBase::RemoveObsoleteOrigin(
     const OriginProps& aOriginProps) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
 
   QM_WARNING(
       "Deleting obsolete %s directory that is no longer a legal "
       "origin!",
       NS_ConvertUTF16toUTF8(aOriginProps.mLeafName).get());
 
   QM_TRY(aOriginProps.mDirectory->Remove(/* recursive */ true));
 
   return NS_OK;
 }
 
 Result<bool, nsresult> StorageOperationBase::MaybeRenameOrigin(
     const OriginProps& aOriginProps) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
 
   const nsAString& oldLeafName = aOriginProps.mLeafName;
 
   const auto newLeafName =
       MakeSanitizedOriginString(aOriginProps.mOriginMetadata.mOrigin);
 
   if (oldLeafName == newLeafName) {
     return false;
@@ -9723,17 +9701,17 @@ Result<bool, nsresult> StorageOperationB
                                  aOriginProps.mOriginMetadata));
 
   QM_TRY(CreateDirectoryMetadata2(
       *aOriginProps.mDirectory, aOriginProps.mTimestamp,
       /* aPersisted */ false, aOriginProps.mOriginMetadata));
 
   QM_TRY_INSPECT(const auto& newFile,
                  MOZ_TO_RESULT_INVOKE_TYPED(
-                     nsCOMPtr<nsIFile>, *aOriginProps.mDirectory, GetParent));
+                     nsCOMPtr<nsIFile>, aOriginProps.mDirectory, GetParent));
 
   QM_TRY(newFile->Append(newLeafName));
 
   QM_TRY_INSPECT(const bool& exists, MOZ_TO_RESULT_INVOKE(newFile, Exists));
 
   if (exists) {
     QM_WARNING(
         "Can't rename %s directory to %s, the target already exists, removing "
@@ -9762,17 +9740,17 @@ nsresult StorageOperationBase::ProcessOr
 #ifdef QM_PRINCIPALINFO_VERIFICATION_ENABLED
   nsTArray<PrincipalInfo> principalInfos;
 #endif
 
   for (auto& originProps : mOriginProps) {
     switch (originProps.mType) {
       case OriginProps::eChrome: {
         originProps.mOriginMetadata = {QuotaManager::GetInfoForChrome(),
-                                       *originProps.mPersistenceType};
+                                       PERSISTENCE_TYPE_INVALID};
         break;
       }
 
       case OriginProps::eContent: {
         RefPtr<MozURL> specURL;
         nsresult rv = MozURL::Init(getter_AddRefs(specURL), originProps.mSpec);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           // If a URL cannot be understood by MozURL during restoring or
@@ -9803,17 +9781,17 @@ nsresult StorageOperationBase::ProcessOr
         contentPrincipalInfo.originNoSuffix() = originNoSuffix;
         contentPrincipalInfo.spec() = originProps.mSpec;
         contentPrincipalInfo.baseDomain() = baseDomain;
 
         PrincipalInfo principalInfo(contentPrincipalInfo);
 
         originProps.mOriginMetadata = {
             QuotaManager::GetInfoFromValidatedPrincipalInfo(principalInfo),
-            *originProps.mPersistenceType};
+            PERSISTENCE_TYPE_INVALID};
 
 #ifdef QM_PRINCIPALINFO_VERIFICATION_ENABLED
         principalInfos.AppendElement(principalInfo);
 #endif
 
         break;
       }
 
@@ -9849,55 +9827,39 @@ nsresult StorageOperationBase::ProcessOr
 
       QM_TRY(ProcessOriginDirectory(originProps));
     }
   }
 
   return NS_OK;
 }
 
-// XXX Do the fallible initialization in a separate non-static member function
-// of StorageOperationBase and eventually get rid of this method and use a
-// normal constructor instead.
-template <typename PersistenceTypeFunc>
-nsresult StorageOperationBase::OriginProps::Init(
-    PersistenceTypeFunc&& aPersistenceTypeFunc) {
-  AssertIsOnIOThread();
+nsresult StorageOperationBase::OriginProps::Init(nsIFile* aDirectory) {
+  AssertIsOnIOThread();
+  MOZ_ASSERT(aDirectory);
 
   QM_TRY_INSPECT(
       const auto& leafName,
-      MOZ_TO_RESULT_INVOKE_TYPED(nsAutoString, *mDirectory, GetLeafName));
+      MOZ_TO_RESULT_INVOKE_TYPED(nsAutoString, aDirectory, GetLeafName));
 
   nsCString spec;
   OriginAttributes attrs;
   nsCString originalSuffix;
   OriginParser::ResultType result = OriginParser::ParseOrigin(
       NS_ConvertUTF16toUTF8(leafName), spec, &attrs, originalSuffix);
   if (NS_WARN_IF(result == OriginParser::InvalidOrigin)) {
     mType = OriginProps::eInvalid;
     return NS_OK;
   }
 
-  const auto persistenceType = [&]() -> PersistenceType {
-    // XXX We shouldn't continue with initialization if OriginParser returned
-    // anything else but ValidOrigin. Otherwise, we have to deal with empty
-    // spec when the origin is obsolete, like here. The caller should handle
-    // the errors. Until it's fixed, we have to treat obsolete origins as
-    // origins with unknown/invalid persistence type.
-    if (result != OriginParser::ValidOrigin) {
-      return PERSISTENCE_TYPE_INVALID;
-    }
-    return std::forward<PersistenceTypeFunc>(aPersistenceTypeFunc)(spec);
-  }();
-
+  mDirectory = aDirectory;
   mLeafName = leafName;
   mSpec = spec;
   mAttrs = attrs;
   mOriginalSuffix = originalSuffix;
-  mPersistenceType.init(persistenceType);
   if (result == OriginParser::ObsoleteOrigin) {
     mType = eObsolete;
   } else if (mSpec.EqualsLiteral(kChromeOrigin)) {
     mType = eChrome;
   } else {
     mType = eContent;
   }
 
@@ -10387,20 +10349,18 @@ nsresult RepositoryOperationBase::Proces
         // them.
         if (!IsOSMetadata(leafName)) {
           UNKNOWN_FILE_WARNING(leafName);
         }
 
         return mozilla::Ok{};
       },
       [&self = *this](const auto& originDir) -> Result<mozilla::Ok, nsresult> {
-        OriginProps originProps(WrapMovingNotNullUnchecked(originDir));
-        QM_TRY(originProps.Init([&self](const auto& aSpec) {
-          return self.PersistenceTypeFromSpec(aSpec);
-        }));
+        OriginProps originProps;
+        QM_TRY(originProps.Init(originDir));
         // Bypass invalid origins while upgrading
         QM_TRY(OkIf(originProps.mType != OriginProps::eInvalid), mozilla::Ok{});
 
         if (originProps.mType != OriginProps::eObsolete) {
           QM_TRY_INSPECT(
               const bool& removed,
               MOZ_TO_RESULT_INVOKE(self, PrepareOriginDirectory, originProps));
           if (removed) {
@@ -10421,16 +10381,17 @@ nsresult RepositoryOperationBase::Proces
 
   return NS_OK;
 }
 
 template <typename UpgradeMethod>
 nsresult RepositoryOperationBase::MaybeUpgradeClients(
     const OriginProps& aOriginProps, UpgradeMethod aMethod) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
   MOZ_ASSERT(aMethod);
 
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
   QM_TRY(CollectEachFileEntry(
       *aOriginProps.mDirectory,
       [](const auto& file) -> Result<mozilla::Ok, nsresult> {
@@ -10478,66 +10439,16 @@ nsresult RepositoryOperationBase::MaybeU
 nsresult RepositoryOperationBase::PrepareClientDirectory(
     nsIFile* aFile, const nsAString& aLeafName, bool& aRemoved) {
   AssertIsOnIOThread();
 
   aRemoved = false;
   return NS_OK;
 }
 
-nsresult CreateOrUpgradeDirectoryMetadataHelper::Init() {
-  AssertIsOnIOThread();
-  MOZ_ASSERT(mDirectory);
-
-  const auto maybeLegacyPersistenceType =
-      LegacyPersistenceTypeFromFile(*mDirectory, fallible);
-  QM_TRY(OkIf(maybeLegacyPersistenceType.isSome()), Err(NS_ERROR_FAILURE));
-
-  mLegacyPersistenceType.init(maybeLegacyPersistenceType.value());
-
-  return NS_OK;
-}
-
-Maybe<CreateOrUpgradeDirectoryMetadataHelper::LegacyPersistenceType>
-CreateOrUpgradeDirectoryMetadataHelper::LegacyPersistenceTypeFromFile(
-    nsIFile& aFile, const fallible_t&) {
-  nsAutoString leafName;
-  MOZ_ALWAYS_SUCCEEDS(aFile.GetLeafName(leafName));
-
-  if (leafName.Equals(u"persistent"_ns)) {
-    return Some(LegacyPersistenceType::Persistent);
-  }
-
-  if (leafName.Equals(u"temporary"_ns)) {
-    return Some(LegacyPersistenceType::Temporary);
-  }
-
-  return Nothing();
-}
-
-PersistenceType
-CreateOrUpgradeDirectoryMetadataHelper::PersistenceTypeFromLegacyPersistentSpec(
-    const nsCString& aSpec) {
-  if (QuotaManager::IsOriginInternal(aSpec)) {
-    return PERSISTENCE_TYPE_PERSISTENT;
-  }
-
-  return PERSISTENCE_TYPE_DEFAULT;
-}
-
-PersistenceType CreateOrUpgradeDirectoryMetadataHelper::PersistenceTypeFromSpec(
-    const nsCString& aSpec) {
-  switch (*mLegacyPersistenceType) {
-    case LegacyPersistenceType::Persistent:
-      return PersistenceTypeFromLegacyPersistentSpec(aSpec);
-    case LegacyPersistenceType::Temporary:
-      return PERSISTENCE_TYPE_TEMPORARY;
-  }
-}
-
 nsresult CreateOrUpgradeDirectoryMetadataHelper::MaybeUpgradeOriginDirectory(
     nsIFile* aDirectory) {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
 
   QM_TRY_INSPECT(
       const auto& metadataFile,
       CloneFileAndAppend(*aDirectory, nsLiteralString(METADATA_FILE_NAME)));
@@ -10592,53 +10503,56 @@ nsresult CreateOrUpgradeDirectoryMetadat
   }
 
   return NS_OK;
 }
 
 nsresult CreateOrUpgradeDirectoryMetadataHelper::PrepareOriginDirectory(
     OriginProps& aOriginProps, bool* aRemoved) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
   MOZ_ASSERT(aRemoved);
 
-  if (*mLegacyPersistenceType == LegacyPersistenceType::Persistent) {
-    QM_TRY(MaybeUpgradeOriginDirectory(aOriginProps.mDirectory.get()));
-
-    aOriginProps.mTimestamp = GetOriginLastModifiedTime(aOriginProps);
+  if (mPersistent) {
+    QM_TRY(MaybeUpgradeOriginDirectory(aOriginProps.mDirectory));
+
+    const bool persistent = QuotaManager::IsOriginInternal(aOriginProps.mSpec);
+    aOriginProps.mTimestamp =
+        GetLastModifiedTime(aOriginProps.mDirectory, persistent);
   } else {
     int64_t timestamp;
     nsCString group;
     nsCString origin;
     Nullable<bool> isApp;
-    nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory.get(), timestamp,
+    nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory, timestamp,
                                        group, origin, isApp);
     if (NS_FAILED(rv)) {
-      aOriginProps.mTimestamp = GetOriginLastModifiedTime(aOriginProps);
+      aOriginProps.mTimestamp =
+          GetLastModifiedTime(aOriginProps.mDirectory, mPersistent);
       aOriginProps.mNeedsRestore = true;
     } else if (!isApp.IsNull()) {
       aOriginProps.mIgnore = true;
     }
   }
 
   *aRemoved = false;
   return NS_OK;
 }
 
 nsresult CreateOrUpgradeDirectoryMetadataHelper::ProcessOriginDirectory(
     const OriginProps& aOriginProps) {
   AssertIsOnIOThread();
 
-  if (*mLegacyPersistenceType == LegacyPersistenceType::Persistent) {
+  if (mPersistent) {
     QM_TRY(CreateDirectoryMetadata(*aOriginProps.mDirectory,
                                    aOriginProps.mTimestamp,
                                    aOriginProps.mOriginMetadata));
 
     // Move internal origins to new persistent storage.
-    if (PersistenceTypeFromLegacyPersistentSpec(aOriginProps.mSpec) ==
-        PERSISTENCE_TYPE_PERSISTENT) {
+    if (QuotaManager::IsOriginInternal(aOriginProps.mSpec)) {
       if (!mPermanentStorageDir) {
         QuotaManager* quotaManager = QuotaManager::Get();
         MOZ_ASSERT(quotaManager);
 
         const nsString& permanentStoragePath =
             quotaManager->GetStoragePath(PERSISTENCE_TYPE_PERSISTENT);
 
         QM_TRY_UNWRAP(mPermanentStorageDir,
@@ -10678,49 +10592,31 @@ nsresult CreateOrUpgradeDirectoryMetadat
 
     // Currently unused (used to be isApp).
     QM_TRY(stream->WriteBoolean(false));
   }
 
   return NS_OK;
 }
 
-nsresult UpgradeStorageHelperBase::Init() {
-  AssertIsOnIOThread();
-  MOZ_ASSERT(mDirectory);
-
-  const auto maybePersistenceType =
-      PersistenceTypeFromFile(*mDirectory, fallible);
-  QM_TRY(OkIf(maybePersistenceType.isSome()), Err(NS_ERROR_FAILURE));
-
-  mPersistenceType.init(maybePersistenceType.value());
-
-  return NS_OK;
-}
-
-PersistenceType UpgradeStorageHelperBase::PersistenceTypeFromSpec(
-    const nsCString& aSpec) {
-  // There's no moving of origin directories between repositories like in the
-  // CreateOrUpgradeDirectoryMetadataHelper
-  return *mPersistenceType;
-}
-
 nsresult UpgradeStorageFrom0_0To1_0Helper::PrepareOriginDirectory(
     OriginProps& aOriginProps, bool* aRemoved) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
   MOZ_ASSERT(aRemoved);
 
   int64_t timestamp;
   nsCString group;
   nsCString origin;
   Nullable<bool> isApp;
-  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory.get(), timestamp,
-                                     group, origin, isApp);
+  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory, timestamp, group,
+                                     origin, isApp);
   if (NS_FAILED(rv) || isApp.IsNull()) {
-    aOriginProps.mTimestamp = GetOriginLastModifiedTime(aOriginProps);
+    aOriginProps.mTimestamp =
+        GetLastModifiedTime(aOriginProps.mDirectory, mPersistent);
     aOriginProps.mNeedsRestore = true;
   } else {
     aOriginProps.mTimestamp = timestamp;
   }
 
   *aRemoved = false;
   return NS_OK;
 }
@@ -10748,25 +10644,26 @@ nsresult UpgradeStorageFrom0_0To1_0Helpe
       /* aPersisted */ false, aOriginProps.mOriginMetadata));
 
   return NS_OK;
 }
 
 nsresult UpgradeStorageFrom1_0To2_0Helper::MaybeRemoveMorgueDirectory(
     const OriginProps& aOriginProps) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
 
   // The Cache API was creating top level morgue directories by accident for
   // a short time in nightly.  This unfortunately prevents all storage from
   // working.  So recover these profiles permanently by removing these corrupt
   // directories as part of this upgrade.
 
   QM_TRY_INSPECT(const auto& morgueDir,
                  MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>,
-                                            *aOriginProps.mDirectory, Clone));
+                                            aOriginProps.mDirectory, Clone));
 
   QM_TRY(morgueDir->Append(u"morgue"_ns));
 
   QM_TRY_INSPECT(const bool& exists, MOZ_TO_RESULT_INVOKE(morgueDir, Exists));
 
   if (exists) {
     QM_WARNING("Deleting accidental morgue directory!");
 
@@ -10807,16 +10704,17 @@ Result<bool, nsresult> UpgradeStorageFro
   }
 
   return false;
 }
 
 nsresult UpgradeStorageFrom1_0To2_0Helper::PrepareOriginDirectory(
     OriginProps& aOriginProps, bool* aRemoved) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
   MOZ_ASSERT(aRemoved);
 
   QM_TRY(MaybeRemoveMorgueDirectory(aOriginProps));
 
   QM_TRY(
       MaybeUpgradeClients(aOriginProps, &Client::UpgradeStorageFrom1_0To2_0));
 
   QM_TRY_INSPECT(const bool& removed, MaybeRemoveAppsData(aOriginProps));
@@ -10824,27 +10722,28 @@ nsresult UpgradeStorageFrom1_0To2_0Helpe
     *aRemoved = true;
     return NS_OK;
   }
 
   int64_t timestamp;
   nsCString group;
   nsCString origin;
   Nullable<bool> isApp;
-  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory.get(), timestamp,
-                                     group, origin, isApp);
+  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory, timestamp, group,
+                                     origin, isApp);
   if (NS_FAILED(rv) || isApp.IsNull()) {
     aOriginProps.mNeedsRestore = true;
   }
 
   nsCString suffix;
-  rv = GetDirectoryMetadata2(aOriginProps.mDirectory.get(), timestamp, suffix,
-                             group, origin, isApp.SetValue());
+  rv = GetDirectoryMetadata2(aOriginProps.mDirectory, timestamp, suffix, group,
+                             origin, isApp.SetValue());
   if (NS_FAILED(rv)) {
-    aOriginProps.mTimestamp = GetOriginLastModifiedTime(aOriginProps);
+    aOriginProps.mTimestamp =
+        GetLastModifiedTime(aOriginProps.mDirectory, mPersistent);
     aOriginProps.mNeedsRestore2 = true;
   } else {
     aOriginProps.mTimestamp = timestamp;
   }
 
   *aRemoved = false;
   return NS_OK;
 }
@@ -10873,36 +10772,38 @@ nsresult UpgradeStorageFrom1_0To2_0Helpe
   }
 
   return NS_OK;
 }
 
 nsresult UpgradeStorageFrom2_0To2_1Helper::PrepareOriginDirectory(
     OriginProps& aOriginProps, bool* aRemoved) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
   MOZ_ASSERT(aRemoved);
 
   QM_TRY(
       MaybeUpgradeClients(aOriginProps, &Client::UpgradeStorageFrom2_0To2_1));
 
   int64_t timestamp;
   nsCString group;
   nsCString origin;
   Nullable<bool> isApp;
-  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory.get(), timestamp,
-                                     group, origin, isApp);
+  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory, timestamp, group,
+                                     origin, isApp);
   if (NS_FAILED(rv) || isApp.IsNull()) {
     aOriginProps.mNeedsRestore = true;
   }
 
   nsCString suffix;
-  rv = GetDirectoryMetadata2(aOriginProps.mDirectory.get(), timestamp, suffix,
-                             group, origin, isApp.SetValue());
+  rv = GetDirectoryMetadata2(aOriginProps.mDirectory, timestamp, suffix, group,
+                             origin, isApp.SetValue());
   if (NS_FAILED(rv)) {
-    aOriginProps.mTimestamp = GetOriginLastModifiedTime(aOriginProps);
+    aOriginProps.mTimestamp =
+        GetLastModifiedTime(aOriginProps.mDirectory, mPersistent);
     aOriginProps.mNeedsRestore2 = true;
   } else {
     aOriginProps.mTimestamp = timestamp;
   }
 
   *aRemoved = false;
   return NS_OK;
 }
@@ -10924,36 +10825,38 @@ nsresult UpgradeStorageFrom2_0To2_1Helpe
   }
 
   return NS_OK;
 }
 
 nsresult UpgradeStorageFrom2_1To2_2Helper::PrepareOriginDirectory(
     OriginProps& aOriginProps, bool* aRemoved) {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aOriginProps.mDirectory);
   MOZ_ASSERT(aRemoved);
 
   QM_TRY(
       MaybeUpgradeClients(aOriginProps, &Client::UpgradeStorageFrom2_1To2_2));
 
   int64_t timestamp;
   nsCString group;
   nsCString origin;
   Nullable<bool> isApp;
-  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory.get(), timestamp,
-                                     group, origin, isApp);
+  nsresult rv = GetDirectoryMetadata(aOriginProps.mDirectory, timestamp, group,
+                                     origin, isApp);
   if (NS_FAILED(rv) || isApp.IsNull()) {
     aOriginProps.mNeedsRestore = true;
   }
 
   nsCString suffix;
-  rv = GetDirectoryMetadata2(aOriginProps.mDirectory.get(), timestamp, suffix,
-                             group, origin, isApp.SetValue());
+  rv = GetDirectoryMetadata2(aOriginProps.mDirectory, timestamp, suffix, group,
+                             origin, isApp.SetValue());
   if (NS_FAILED(rv)) {
-    aOriginProps.mTimestamp = GetOriginLastModifiedTime(aOriginProps);
+    aOriginProps.mTimestamp =
+        GetLastModifiedTime(aOriginProps.mDirectory, mPersistent);
     aOriginProps.mNeedsRestore2 = true;
   } else {
     aOriginProps.mTimestamp = timestamp;
   }
 
   *aRemoved = false;
   return NS_OK;
 }
@@ -10990,40 +10893,25 @@ nsresult UpgradeStorageFrom2_1To2_2Helpe
     aRemoved = true;
   } else {
     aRemoved = false;
   }
 
   return NS_OK;
 }
 
-nsresult RestoreDirectoryMetadata2Helper::Init() {
-  AssertIsOnIOThread();
-  MOZ_ASSERT(mDirectory);
-
-  nsCOMPtr<nsIFile> parentDir;
-  QM_TRY(mDirectory->GetParent(getter_AddRefs(parentDir)));
-
-  const auto maybePersistenceType =
-      PersistenceTypeFromFile(*parentDir, fallible);
-  QM_TRY(OkIf(maybePersistenceType.isSome()), Err(NS_ERROR_FAILURE));
-
-  mPersistenceType.init(maybePersistenceType.value());
-
-  return NS_OK;
-}
-
 nsresult RestoreDirectoryMetadata2Helper::RestoreMetadata2File() {
-  OriginProps originProps(WrapMovingNotNull(mDirectory));
-  QM_TRY(originProps.Init(
-      [&self = *this](const auto& aSpec) { return *self.mPersistenceType; }));
+  AssertIsOnIOThread();
+
+  OriginProps originProps;
+  QM_TRY(originProps.Init(mDirectory));
 
   QM_TRY(OkIf(originProps.mType != OriginProps::eInvalid), NS_ERROR_FAILURE);
 
-  originProps.mTimestamp = GetOriginLastModifiedTime(originProps);
+  originProps.mTimestamp = GetLastModifiedTime(mDirectory, mPersistent);
 
   mOriginProps.AppendElement(std::move(originProps));
 
   QM_TRY(ProcessOriginDirectories());
 
   return NS_OK;
 }
 
--- a/dom/quota/OriginMetadata.h
+++ b/dom/quota/OriginMetadata.h
@@ -41,18 +41,11 @@ struct OriginMetadata : public Principal
         mPersistenceType(aPersistenceType) {}
 
   OriginMetadata(PrincipalMetadata&& aPrincipalMetadata,
                  PersistenceType aPersistenceType)
       : PrincipalMetadata(std::move(aPrincipalMetadata)),
         mPersistenceType(aPersistenceType) {}
 };
 
-struct FullOriginMetadata : OriginMetadata {
-  bool mPersisted;
-  int64_t mTimestamp;
-
-  // XXX Only default construction is needed for now.
-};
-
 }  // namespace mozilla::dom::quota
 
 #endif  // DOM_QUOTA_ORIGINMETADATA_H_
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -220,25 +220,32 @@ class QuotaManager final : public Backgr
 
   // Called when a process is being shot down. Aborts any running operations
   // for the given process.
   void AbortOperationsForProcess(ContentParentId aContentParentId);
 
   Result<nsCOMPtr<nsIFile>, nsresult> GetDirectoryForOrigin(
       PersistenceType aPersistenceType, const nsACString& aASCIIOrigin) const;
 
-  nsresult RestoreDirectoryMetadata2(nsIFile* aDirectory);
+  nsresult RestoreDirectoryMetadata2(nsIFile* aDirectory, bool aPersistent);
+
+  struct GetDirectoryResultWithOriginMetadata {
+    int64_t mTimestamp;
+    bool mPersisted;
+    OriginMetadata mOriginMetadata;
+  };
 
   // XXX Remove aPersistenceType argument once the persistence type is stored
   // in the metadata file.
-  Result<FullOriginMetadata, nsresult> LoadFullOriginMetadata(
-      nsIFile* aDirectory, PersistenceType aPersistenceType);
+  Result<GetDirectoryResultWithOriginMetadata, nsresult>
+  GetDirectoryMetadataWithOriginMetadata2(nsIFile* aDirectory,
+                                          PersistenceType aPersistenceType);
 
-  Result<FullOriginMetadata, nsresult> LoadFullOriginMetadataWithRestore(
-      nsIFile* aDirectory);
+  Result<GetDirectoryResultWithOriginMetadata, nsresult>
+  GetDirectoryMetadataWithOriginMetadata2WithRestore(nsIFile* aDirectory);
 
   // This is the main entry point into the QuotaManager API.
   // Any storage API implementation (quota client) that participates in
   // centralized quota and storage handling should call this method to get
   // a directory lock which will protect client's files from being deleted
   // while they are still in use.
   // After a lock is acquired, client is notified via the open listener's
   // method DirectoryLockAcquired. If the lock couldn't be acquired, client