Bug 1195930 - Part 2: Refactor StorageDirectoryHelper to a base class and two separate final classes, improve correctness of default storage upgrade and add support for resource urls; r=asuth
authorJan Varga <jan.varga@gmail.com>
Sun, 05 Jun 2016 21:42:01 +0200
changeset 339561 ab62788c946c129b5884a5d95a8bf0a9497925a3
parent 339560 f3acbafcc10ddc8102b3edf5208e9eb44d3727fa
child 339562 47147d38a9d84651db42e7c5040b5ff21e2b2ce5
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1195930
milestone49.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 1195930 - Part 2: Refactor StorageDirectoryHelper to a base class and two separate final classes, improve correctness of default storage upgrade and add support for resource urls; r=asuth
dom/indexedDB/test/unit/defaultStorageUpgrade_profile.zip
dom/indexedDB/test/unit/test_defaultStorageUpgrade.js
dom/quota/ActorsParent.cpp
index 1a7d61a4f624cca3888fa5fa92f0c5f937abc741..588a9970597a5e1e1b84915b9ead980253288a00
GIT binary patch
literal 78093
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
OlqDG$UiM-C_WuDsx|*{9
--- a/dom/indexedDB/test/unit/test_defaultStorageUpgrade.js
+++ b/dom/indexedDB/test/unit/test_defaultStorageUpgrade.js
@@ -70,16 +70,40 @@ function testSteps()
     { url: "file:///Users/joe/c///index.html", dbName: "dbR", dbVersion: 1 },
 
     // This one lives in storage/default/file++++++index.html
     { url: "file:///+/index.html", dbName: "dbS", dbVersion: 1 },
 
     // This one lives in storage/default/file++++++index.html
     { url: "file://///index.html", dbName: "dbS", dbVersion: 1 },
 
+    // This one lives in storage/permanent/resource+++fx-share-addon-at-mozilla-dot-org-fx-share-addon-data
+    { url: "resource://fx-share-addon-at-mozilla-dot-org-fx-share-addon-data",
+      dbName: "dbU", dbOptions: { version: 1, storage: "persistent" } },
+
+    // This one lives in storage/temporary/http+++localhost+81
+    // The .metadata file was intentionally removed for this origin directory
+    // to test restoring during upgrade.
+    { url: "http://localhost:81", dbName: "dbV",
+      dbOptions: { version: 1, storage: "temporary" } },
+
+    // This one lives in storage/temporary/http+++localhost+82
+    // The .metadata file was intentionally truncated for this origin directory
+    // to test restoring during upgrade.
+    { url: "http://localhost:82", dbName: "dbW",
+      dbOptions: { version: 1, storage: "temporary" } },
+
+    // This one lives in storage/temporary/1007+f+app+++system.gaiamobile.org
+    { appId: 1007, inIsolatedMozBrowser: false, url: "app://system.gaiamobile.org",
+      dbName: "dbX", dbOptions: { version: 1, storage: "temporary" } },
+
+    // This one lives in storage/temporary/1007+t+https+++developer.cdn.mozilla.net
+    { appId: 1007, inIsolatedMozBrowser: true, url: "https://developer.cdn.mozilla.net",
+      dbName: "dbY", dbOptions: { version: 1, storage: "temporary" } },
+
     // This one lives in storage/temporary/http+++localhost
     { url: "http://localhost", dbName: "dbZ",
       dbOptions: { version: 1, storage: "temporary" } }
   ];
 
   let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
                          .getService(SpecialPowers.Ci.nsIIOService);
 
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -135,16 +135,17 @@ static_assert(
 static_assert(
   static_cast<uint32_t>(StorageType::Default) ==
   static_cast<uint32_t>(PERSISTENCE_TYPE_DEFAULT),
   "Enum values should match.");
 
 const char kChromeOrigin[] = "chrome";
 const char kAboutHomeOrigin[] = "moz-safe-about:home";
 const char kIndexedDBOriginPrefix[] = "indexeddb://";
+const char kResourceOriginPrefix[] = "resource://";
 
 #define INDEXEDDB_DIRECTORY_NAME "indexedDB"
 #define STORAGE_DIRECTORY_NAME "storage"
 #define PERSISTENT_DIRECTORY_NAME "persistent"
 #define PERMANENT_DIRECTORY_NAME "permanent"
 #define TEMPORARY_DIRECTORY_NAME "temporary"
 #define DEFAULT_DIRECTORY_NAME "default"
 
@@ -1231,61 +1232,57 @@ mozilla::Atomic<bool> gShutdown(false);
 // Constants for temporary storage limit computing.
 static const int32_t kDefaultFixedLimitKB = -1;
 static const uint32_t kDefaultChunkSizeKB = 10 * 1024;
 int32_t gFixedLimitKB = kDefaultFixedLimitKB;
 uint32_t gChunkSizeKB = kDefaultChunkSizeKB;
 
 bool gTestingEnabled = false;
 
-class StorageDirectoryHelper final
+class StorageDirectoryHelper
   : public Runnable
 {
+  mozilla::Mutex mMutex;
+  mozilla::CondVar mCondVar;
+  nsresult mMainThreadResultCode;
+  bool mWaiting;
+
+protected:
   struct OriginProps;
 
   nsTArray<OriginProps> mOriginProps;
 
   nsCOMPtr<nsIFile> mDirectory;
-  mozilla::Mutex mMutex;
-  mozilla::CondVar mCondVar;
-  nsresult mMainThreadResultCode;
-  const bool mPersistent;
-  bool mCreate;
-  bool mWaiting;
 
 public:
-  StorageDirectoryHelper(nsIFile* aDirectory,
-                         bool aPersistent)
-    : mDirectory(aDirectory)
-    , mMutex("StorageDirectoryHelper::mMutex")
+  StorageDirectoryHelper(nsIFile* aDirectory)
+    : mMutex("StorageDirectoryHelper::mMutex")
     , mCondVar(mMutex, "StorageDirectoryHelper::mCondVar")
     , mMainThreadResultCode(NS_OK)
-    , mPersistent(aPersistent)
-    , mCreate(true)
     , mWaiting(true)
+    , mDirectory(aDirectory)
   {
     AssertIsOnIOThread();
   }
 
-  nsresult
-  CreateOrUpgradeMetadataFiles(bool aCreate);
-
-  nsresult
-  RestoreMetadataFile();
-
-private:
+protected:
   ~StorageDirectoryHelper()
   { }
 
   nsresult
-  AddOriginDirectory(nsIFile* aDirectory);
+  AddOriginDirectory(nsIFile* aDirectory,
+                     OriginProps** aOriginProps);
 
   nsresult
-  ProcessOriginDirectories(bool aMove);
-
+  ProcessOriginDirectories();
+
+  virtual nsresult
+  DoProcessOriginDirectories() = 0;
+
+private:
   nsresult
   RunOnMainThread();
 
   NS_IMETHOD
   Run();
 };
 
 struct StorageDirectoryHelper::OriginProps
@@ -1300,22 +1297,26 @@ struct StorageDirectoryHelper::OriginPro
   nsCString mSpec;
   PrincipalOriginAttributes mAttrs;
   int64_t mTimestamp;
   nsCString mGroup;
   nsCString mOrigin;
 
   Type mType;
   bool mIsApp;
+  bool mNeedsRestore;
+  bool mIgnore;
 
 public:
   explicit OriginProps()
     : mTimestamp(0)
     , mType(eContent)
     , mIsApp(false)
+    , mNeedsRestore(false)
+    , mIgnore(false)
   { }
 };
 
 class MOZ_STACK_CLASS OriginParser final
 {
   static bool
   IgnoreWhitespace(char16_t /* aChar */)
   {
@@ -1391,16 +1392,63 @@ private:
 
   void
   HandleToken(const nsDependentCSubstring& aToken);
 
   void
   HandleTrailingSeparator();
 };
 
+class CreateOrUpgradeDirectoryMetadataHelper final
+  : public StorageDirectoryHelper
+{
+  const bool mPersistent;
+
+public:
+  CreateOrUpgradeDirectoryMetadataHelper(nsIFile* aDirectory,
+                                         bool aPersistent)
+    : StorageDirectoryHelper(aDirectory)
+    , mPersistent(aPersistent)
+  { }
+
+  nsresult
+  CreateOrUpgradeMetadataFiles();
+
+private:
+  nsresult
+  GetDirectoryMetadata(nsIFile* aDirectory,
+                       int64_t* aTimestamp,
+                       nsACString& aGroup,
+                       nsACString& aOrigin,
+                       bool* aHasIsApp);
+
+  virtual nsresult
+  DoProcessOriginDirectories();
+};
+
+class RestoreDirectoryMetadataHelper final
+  : public StorageDirectoryHelper
+{
+  const bool mPersistent;
+
+public:
+  RestoreDirectoryMetadataHelper(nsIFile* aDirectory,
+                                 bool aPersistent)
+    : StorageDirectoryHelper(aDirectory)
+    , mPersistent(aPersistent)
+  { }
+
+  nsresult
+  RestoreMetadataFile();
+
+private:
+  virtual nsresult
+  DoProcessOriginDirectories();
+};
+
 class OriginKey : public nsAutoCString
 {
 public:
   OriginKey(PersistenceType aPersistenceType,
             const nsACString& aOrigin)
   {
     PersistenceTypeToText(aPersistenceType, *this);
     Append(':');
@@ -1699,18 +1747,18 @@ CreateDirectoryMetadata(nsIFile* aDirect
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 RestoreDirectoryMetadata(nsIFile* aDirectory, bool aPersistent)
 {
-  RefPtr<StorageDirectoryHelper> helper =
-    new StorageDirectoryHelper(aDirectory, aPersistent);
+  RefPtr<RestoreDirectoryMetadataHelper> helper =
+    new RestoreDirectoryMetadataHelper(aDirectory, aPersistent);
 
   nsresult rv = helper->RestoreMetadataFile();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
@@ -3694,20 +3742,21 @@ QuotaManager::MaybeUpgradePersistentStor
   }
 
   if (exists) {
     NS_WARNING("storage/persistent shouldn't exist after the upgrade!");
     return NS_OK;
   }
 
   // Create real metadata files for origin directories in persistent storage.
-  RefPtr<StorageDirectoryHelper> helper =
-    new StorageDirectoryHelper(persistentStorageDir, /* aPersistent */ true);
-
-  rv = helper->CreateOrUpgradeMetadataFiles(/* aCreate */ true);
+  RefPtr<CreateOrUpgradeDirectoryMetadataHelper> helper =
+    new CreateOrUpgradeDirectoryMetadataHelper(persistentStorageDir,
+                                               /* aPersistent */ true);
+
+  rv = helper->CreateOrUpgradeMetadataFiles();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Upgrade metadata files for origin directories in temporary storage.
   nsCOMPtr<nsIFile> temporaryStorageDir =
     do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -3730,20 +3779,21 @@ QuotaManager::MaybeUpgradePersistentStor
       return rv;
     }
 
     if (!isDirectory) {
       NS_WARNING("temporary entry is not a directory!");
       return NS_OK;
     }
 
-    helper = new StorageDirectoryHelper(temporaryStorageDir,
-                                        /* aPersistent */ false);
-
-    rv = helper->CreateOrUpgradeMetadataFiles(/* aCreate */ false);
+    helper =
+      new CreateOrUpgradeDirectoryMetadataHelper(temporaryStorageDir,
+                                                 /* aPersistent */ false);
+
+    rv = helper->CreateOrUpgradeMetadataFiles();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   // And finally rename persistent to default.
   rv = persistentStorageDir->RenameTo(nullptr, NS_LITERAL_STRING(DEFAULT_DIRECTORY_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -4234,17 +4284,18 @@ QuotaManager::GetInfoForChrome(nsACStrin
 // static
 bool
 QuotaManager::IsOriginWhitelistedForPersistentStorage(const nsACString& aOrigin)
 {
   // The first prompt and quota tracking is not required for these origins in
   // persistent storage.
   if (aOrigin.EqualsLiteral(kChromeOrigin) ||
       aOrigin.EqualsLiteral(kAboutHomeOrigin) ||
-      StringBeginsWith(aOrigin, nsDependentCString(kIndexedDBOriginPrefix))) {
+      StringBeginsWith(aOrigin, nsDependentCString(kIndexedDBOriginPrefix)) ||
+      StringBeginsWith(aOrigin, nsDependentCString(kResourceOriginPrefix))) {
     return true;
   }
 
   return false;
 }
 
 // static
 bool
@@ -5882,22 +5933,19 @@ OriginClearOp::GetResponse(RequestRespon
   if (mApp) {
     aResponse = ClearAppResponse();
   } else {
     aResponse = ClearOriginResponse();
   }
 }
 
 nsresult
-StorageDirectoryHelper::CreateOrUpgradeMetadataFiles(bool aCreate)
+CreateOrUpgradeDirectoryMetadataHelper::CreateOrUpgradeMetadataFiles()
 {
   AssertIsOnIOThread();
-  MOZ_ASSERT_IF(mPersistent, aCreate);
-
-  mCreate = aCreate;
 
   nsCOMPtr<nsISimpleEnumerator> entries;
   nsresult rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool hasMore;
@@ -5941,109 +5989,158 @@ StorageDirectoryHelper::CreateOrUpgradeM
       if (!leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
         QM_WARNING("Something (%s) in the storage directory that doesn't belong!",
                    NS_ConvertUTF16toUTF8(leafName).get());
 
       }
       continue;
     }
 
-    rv = AddOriginDirectory(originDir);
+    if (mPersistent) {
+      rv = MaybeUpgradeOriginDirectory(originDir);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+
+    OriginProps* originProps;
+    rv = AddOriginDirectory(originDir, &originProps);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
+
+    if (!mPersistent) {
+      int64_t timestamp;
+      nsCString group;
+      nsCString origin;
+      bool hasIsApp;
+      rv = GetDirectoryMetadata(originDir,
+                                &timestamp,
+                                group,
+                                origin,
+                                &hasIsApp);
+      if (NS_FAILED(rv)) {
+        timestamp = INT64_MIN;
+        rv = GetLastModifiedTime(originDir, &timestamp);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+
+        originProps->mTimestamp = timestamp;
+        originProps->mNeedsRestore = true;
+      } else if (hasIsApp) {
+        originProps->mIgnore = true;
+      }
+    }
+    else if (!QuotaManager::IsOriginWhitelistedForPersistentStorage(
+                                                          originProps->mSpec)) {
+      int64_t timestamp = INT64_MIN;
+      rv = GetLastModifiedTime(originDir, &timestamp);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      originProps->mTimestamp = timestamp;
+    }
   }
 
   if (mOriginProps.IsEmpty()) {
     return NS_OK;
   }
 
-  rv = ProcessOriginDirectories(/* aMove */ true);
+  rv = ProcessOriginDirectories();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 nsresult
-StorageDirectoryHelper::RestoreMetadataFile()
+RestoreDirectoryMetadataHelper::RestoreMetadataFile()
 {
   AssertIsOnIOThread();
-  MOZ_ASSERT(mCreate);
-
-  nsresult rv = AddOriginDirectory(mDirectory);
+
+  nsresult rv;
+
+  if (mPersistent) {
+    rv = MaybeUpgradeOriginDirectory(mDirectory);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  OriginProps* originProps;
+  rv = AddOriginDirectory(mDirectory, &originProps);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  rv = ProcessOriginDirectories(/* aMove */ false);
+  if (!mPersistent) {
+    int64_t timestamp = INT64_MIN;
+    rv = GetLastModifiedTime(mDirectory, &timestamp);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    originProps->mTimestamp = timestamp;
+  }
+
+  rv = ProcessOriginDirectories();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 nsresult
-StorageDirectoryHelper::AddOriginDirectory(nsIFile* aDirectory)
+StorageDirectoryHelper::AddOriginDirectory(nsIFile* aDirectory,
+                                           OriginProps** aOriginProps)
 {
   MOZ_ASSERT(aDirectory);
 
-  nsresult rv;
-
-  if (mPersistent) {
-    rv = MaybeUpgradeOriginDirectory(aDirectory);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-  }
+  OriginProps* originProps;
 
   nsString leafName;
-  rv = aDirectory->GetLeafName(leafName);
+  nsresult rv = aDirectory->GetLeafName(leafName);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (leafName.EqualsLiteral(kChromeOrigin)) {
-    OriginProps* originProps = mOriginProps.AppendElement();
+    originProps = mOriginProps.AppendElement();
     originProps->mDirectory = aDirectory;
     originProps->mSpec = kChromeOrigin;
     originProps->mType = OriginProps::eChrome;
   } else {
     nsCString spec;
     PrincipalOriginAttributes attrs;
     bool result = OriginParser::ParseOrigin(NS_ConvertUTF16toUTF8(leafName),
                                             spec, &attrs);
     if (NS_WARN_IF(!result)) {
       return NS_ERROR_FAILURE;
     }
 
-    OriginProps* originProps = mOriginProps.AppendElement();
+    originProps = mOriginProps.AppendElement();
     originProps->mDirectory = aDirectory;
     originProps->mSpec = spec;
     originProps->mAttrs = attrs;
     originProps->mType = OriginProps::eContent;
-
-    if (mCreate) {
-      int64_t timestamp = INT64_MIN;
-      rv = GetLastModifiedTime(aDirectory, &timestamp);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-
-      originProps->mTimestamp = timestamp;
-    }
+  }
+
+  if (aOriginProps) {
+    *aOriginProps = originProps;
   }
 
   return NS_OK;
 }
 
 nsresult
-StorageDirectoryHelper::ProcessOriginDirectories(bool aMove)
+StorageDirectoryHelper::ProcessOriginDirectories()
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(!mOriginProps.IsEmpty());
 
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
 
   {
     mozilla::MutexAutoLock autolock(mMutex);
@@ -6057,39 +6154,50 @@ StorageDirectoryHelper::ProcessOriginDir
   }
 
   // Verify that the bounce to the main thread didn't start the shutdown
   // sequence.
   if (NS_WARN_IF(QuotaManager::IsShuttingDown())) {
     return NS_ERROR_FAILURE;
   }
 
+  nsresult rv = DoProcessOriginDirectories();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+CreateOrUpgradeDirectoryMetadataHelper::DoProcessOriginDirectories()
+{
+  AssertIsOnIOThread();
+
   nsresult rv;
 
   nsCOMPtr<nsIFile> permanentStorageDir;
 
   for (uint32_t count = mOriginProps.Length(), index = 0;
        index < count;
        index++) {
     OriginProps& originProps = mOriginProps[index];
 
-    if (mCreate) {
+    if (mPersistent) {
       rv = CreateDirectoryMetadata(originProps.mDirectory,
                                    originProps.mTimestamp,
                                    originProps.mGroup,
                                    originProps.mOrigin,
                                    originProps.mIsApp);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       // Move whitelisted origins to new persistent storage.
-      if (mPersistent &&
-          aMove &&
-          QuotaManager::IsOriginWhitelistedForPersistentStorage(
+      if (QuotaManager::IsOriginWhitelistedForPersistentStorage(
                                                            originProps.mSpec)) {
         if (!permanentStorageDir) {
           permanentStorageDir =
             do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
 
@@ -6135,17 +6243,26 @@ StorageDirectoryHelper::ProcessOriginDir
           rv = originProps.mDirectory->Remove(/* recursive */ true);
         } else {
           rv = originProps.mDirectory->MoveTo(permanentStorageDir, EmptyString());
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
-    } else {
+    } else if (originProps.mNeedsRestore) {
+      rv = CreateDirectoryMetadata(originProps.mDirectory,
+                                   originProps.mTimestamp,
+                                   originProps.mGroup,
+                                   originProps.mOrigin,
+                                   originProps.mIsApp);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    } else if (!originProps.mIgnore) {
       nsCOMPtr<nsIBinaryOutputStream> stream;
       rv = GetDirectoryMetadataOutputStream(originProps.mDirectory,
                                             kAppendFileFlag,
                                             getter_AddRefs(stream));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
@@ -6157,16 +6274,36 @@ StorageDirectoryHelper::ProcessOriginDir
       }
     }
   }
 
   return NS_OK;
 }
 
 nsresult
+RestoreDirectoryMetadataHelper::DoProcessOriginDirectories()
+{
+  AssertIsOnIOThread();
+  MOZ_ASSERT(mOriginProps.Length() == 1);
+
+  OriginProps& originProps = mOriginProps[0];
+
+  nsresult rv = CreateDirectoryMetadata(originProps.mDirectory,
+                                        originProps.mTimestamp,
+                                        originProps.mGroup,
+                                        originProps.mOrigin,
+                                        originProps.mIsApp);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
 StorageDirectoryHelper::RunOnMainThread()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mOriginProps.IsEmpty());
 
   nsresult rv;
 
   nsCOMPtr<nsIScriptSecurityManager> secMan =
@@ -6196,27 +6333,20 @@ StorageDirectoryHelper::RunOnMainThread(
         }
 
         nsCOMPtr<nsIPrincipal> principal =
           BasePrincipal::CreateCodebasePrincipal(uri, originProps.mAttrs);
         if (NS_WARN_IF(!principal)) {
           return NS_ERROR_FAILURE;
         }
 
-        if (mCreate) {
-          rv = QuotaManager::GetInfoFromPrincipal(principal,
-                                                  &originProps.mGroup,
-                                                  &originProps.mOrigin,
-                                                  &originProps.mIsApp);
-        } else {
-          rv = QuotaManager::GetInfoFromPrincipal(principal,
-                                                  nullptr,
-                                                  nullptr,
-                                                  &originProps.mIsApp);
-        }
+        rv = QuotaManager::GetInfoFromPrincipal(principal,
+                                                &originProps.mGroup,
+                                                &originProps.mOrigin,
+                                                &originProps.mIsApp);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
 
         break;
       }
 
       default:
@@ -6339,17 +6469,18 @@ OriginParser::HandleSchema(const nsDepen
 
   bool isMozSafeAbout = false;
   bool isFile = false;
   if (aToken.EqualsLiteral("http") ||
       aToken.EqualsLiteral("https") ||
       (isMozSafeAbout = aToken.EqualsLiteral("moz-safe-about")) ||
       aToken.EqualsLiteral("indexeddb") ||
       (isFile = aToken.EqualsLiteral("file")) ||
-      aToken.EqualsLiteral("app")) {
+      aToken.EqualsLiteral("app") ||
+      aToken.EqualsLiteral("resource")) {
     mSchema = aToken;
 
     if (isMozSafeAbout) {
       mSchemaType = eMozSafeAbout;
       mState = eExpectingHost;
     } else {
       if (isFile) {
         mSchemaType = eFile;
@@ -6607,11 +6738,59 @@ OriginParser::HandleTrailingSeparator()
   MOZ_ASSERT(mState == eComplete);
   MOZ_ASSERT(mSchemaType == eFile);
 
   mPathnameComponents.AppendElement(EmptyCString());
 
   mState = eHandledTrailingSeparator;
 }
 
+nsresult
+CreateOrUpgradeDirectoryMetadataHelper::GetDirectoryMetadata(
+                                                            nsIFile* aDirectory,
+                                                            int64_t* aTimestamp,
+                                                            nsACString& aGroup,
+                                                            nsACString& aOrigin,
+                                                            bool* aHasIsApp)
+{
+  AssertIsOnIOThread();
+  MOZ_ASSERT(aDirectory);
+  MOZ_ASSERT(aTimestamp);
+  MOZ_ASSERT(aHasIsApp);
+
+  nsCOMPtr<nsIBinaryInputStream> binaryStream;
+  nsresult rv =
+    GetDirectoryMetadataInputStream(aDirectory, getter_AddRefs(binaryStream));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  uint64_t timestamp;
+  rv = binaryStream->Read64(&timestamp);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCString group;
+  rv = binaryStream->ReadCString(group);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCString origin;
+  rv = binaryStream->ReadCString(origin);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  bool dummyIsApp;
+  bool hasIsApp = NS_SUCCEEDED(binaryStream->ReadBoolean(&dummyIsApp));
+
+  *aTimestamp = timestamp;
+  aGroup = group;
+  aOrigin = origin;
+  *aHasIsApp = hasIsApp;
+  return NS_OK;
+}
+
 } // namespace quota
 } // namespace dom
 } // namespace mozilla