Bug 1162624 - Add support for restoring corrupted or missing metadata files; r=bent
authorJan Varga <jan.varga@gmail.com>
Fri, 08 May 2015 21:05:30 +0200
changeset 274421 3d43ed34435515e4fd18937281f882bd8f4a431a
parent 274420 d732da9298fabae4350466e7817f634afa283cb9
child 274422 bf588f714b314e5bfe3cff35cb0788a71c3e2250
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs1162624
milestone40.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 1162624 - Add support for restoring corrupted or missing metadata files; r=bent
dom/indexedDB/test/unit/metadataRestore_profile.zip
dom/indexedDB/test/unit/test_metadataRestore.js
dom/indexedDB/test/unit/xpcshell-parent-process.ini
dom/quota/QuotaManager.cpp
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a01d49166efc26392a6616c375e8efc5228b246f
GIT binary patch
literal 34962
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
bb_AenPWM$F`m4uEz`tT%6zVQv`q%#fPps<U
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_metadataRestore.js
@@ -0,0 +1,109 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var testGenerator = testSteps();
+
+function testSteps()
+{
+  const openParams = [
+    // This one lives in storage/permanent/chrome
+    { dbName: "dbA",
+      dbOptions: { version: 1, storage: "persistent" } },
+
+    // This one lives in storage/temporary/http+++localhost
+    { url: "http://localhost", dbName: "dbB",
+      dbOptions: { version: 1, storage: "temporary" } },
+
+    // This one lives in storage/default/http+++localhost+81
+    { url: "http://localhost:81", dbName: "dbC",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+82
+    { url: "http://localhost:82", dbName: "dbD",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+83
+    { url: "http://localhost:83", dbName: "dbE",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+84
+    { url: "http://localhost:84", dbName: "dbF",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+85
+    { url: "http://localhost:85", dbName: "dbG",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+86
+    { url: "http://localhost:86", dbName: "dbH",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+87
+    { url: "http://localhost:87", dbName: "dbI",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+88
+    { url: "http://localhost:88", dbName: "dbJ",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+89
+    { url: "http://localhost:89", dbName: "dbK",
+      dbOptions: { version: 1, storage: "default" } },
+
+    // This one lives in storage/default/http+++localhost+90
+    { url: "http://localhost:90", dbName: "dbL",
+      dbOptions: { version: 1, storage: "default" } }
+  ];
+
+  let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
+                         .getService(SpecialPowers.Ci.nsIIOService);
+
+  let ssm = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
+                         .getService(SpecialPowers.Ci.nsIScriptSecurityManager);
+
+  function openDatabase(params) {
+    let request;
+    if ("url" in params) {
+      let uri = ios.newURI(params.url, null, null);
+      let principal = ssm.getNoAppCodebasePrincipal(uri);
+      request = indexedDB.openForPrincipal(principal, params.dbName,
+                                           params.dbOptions);
+    } else {
+      request = indexedDB.open(params.dbName, params.dbOptions);
+    }
+    return request;
+  }
+
+  clearAllDatabases(continueToNextStepSync);
+  yield undefined;
+
+  installPackagedProfile("metadataRestore_profile");
+
+  for (let params of openParams) {
+    let request = openDatabase(params);
+    request.onerror = errorHandler;
+    request.onupgradeneeded = unexpectedSuccessHandler;
+    request.onsuccess = grabEventAndContinueHandler;
+    let event = yield undefined;
+
+    is(event.type, "success", "Correct event type");
+  }
+
+  resetAllDatabases(continueToNextStepSync);
+  yield undefined;
+
+  for (let params of openParams) {
+    let request = openDatabase(params);
+    request.onerror = errorHandler;
+    request.onupgradeneeded = unexpectedSuccessHandler;
+    request.onsuccess = grabEventAndContinueHandler;
+    let event = yield undefined;
+
+    is(event.type, "success", "Correct event type");
+  }
+
+  finishTest();
+  yield undefined;
+}
--- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini
+++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
@@ -10,27 +10,29 @@ skip-if = toolkit == 'gonk'
 support-files =
   bug1056939_profile.zip
   defaultStorageUpgrade_profile.zip
   GlobalObjectsChild.js
   GlobalObjectsComponent.js
   GlobalObjectsComponent.manifest
   GlobalObjectsModule.jsm
   GlobalObjectsSandbox.js
+  metadataRestore_profile.zip
   schema18upgrade_profile.zip
   xpcshell-shared.ini
 
 [include:xpcshell-shared.ini]
 
 [test_blob_file_backed.js]
 [test_bug1056939.js]
 [test_defaultStorageUpgrade.js]
 [test_globalObjects_ipc.js]
 skip-if = toolkit == 'android'
 [test_invalidate.js]
 # disabled for the moment.
 skip-if = true
 [test_lowDiskSpace.js]
+[test_metadataRestore.js]
 [test_readwriteflush_disabled.js]
 [test_schema18upgrade.js]
 [test_temporary_storage.js]
 # bug 951017: intermittent failure on Android x86 emulator
 skip-if = os == "android" && processor == "x86"
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -568,40 +568,51 @@ class StorageDirectoryHelper final
   struct OriginProps;
 
   nsTArray<OriginProps> mOriginProps;
 
   nsCOMPtr<nsIFile> mDirectory;
   mozilla::Mutex mMutex;
   mozilla::CondVar mCondVar;
   nsresult mMainThreadResultCode;
-  bool mPersistent;
+  const bool mPersistent;
+  bool mCreate;
   bool mWaiting;
 
 public:
   StorageDirectoryHelper(nsIFile* aDirectory,
                          bool aPersistent)
     : mDirectory(aDirectory)
     , mMutex("StorageDirectoryHelper::mMutex")
     , mCondVar(mMutex, "StorageDirectoryHelper::mCondVar")
     , mMainThreadResultCode(NS_OK)
     , mPersistent(aPersistent)
+    , mCreate(true)
     , mWaiting(true)
   {
     AssertIsOnIOThread();
   }
 
   nsresult
-  CreateOrUpgradeMetadataFiles();
+  CreateOrUpgradeMetadataFiles(bool aCreate);
+
+  nsresult
+  RestoreMetadataFile();
 
 private:
   ~StorageDirectoryHelper()
   { }
 
   nsresult
+  AddOriginDirectory(nsIFile* aDirectory);
+
+  nsresult
+  ProcessOriginDirectories(bool aMove);
+
+  nsresult
   RunOnMainThread();
 
   NS_IMETHOD
   Run();
 };
 
 struct StorageDirectoryHelper::OriginProps
 {
@@ -1046,16 +1057,30 @@ CreateDirectoryMetadata(nsIFile* aDirect
 
   rv = stream->WriteBoolean(aIsApp);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
+RestoreDirectoryMetadata(nsIFile* aDirectory, bool aPersistent)
+{
+  nsRefPtr<StorageDirectoryHelper> helper =
+    new StorageDirectoryHelper(aDirectory, aPersistent);
+
+  nsresult rv = helper->RestoreMetadataFile();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
 GetDirectoryMetadataInputStream(nsIFile* aDirectory,
                                 nsIBinaryInputStream** aStream)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
   MOZ_ASSERT(aStream);
 
   nsCOMPtr<nsIFile> metadataFile;
@@ -1125,16 +1150,93 @@ GetDirectoryMetadata(nsIFile* aDirectory
   aOrigin = origin;
   if (aIsApp) {
     *aIsApp = isApp;
   }
   return NS_OK;
 }
 
 nsresult
+GetDirectoryMetadataWithRestore(nsIFile* aDirectory,
+                                bool aPersistent,
+                                int64_t* aTimestamp,
+                                nsACString& aGroup,
+                                nsACString& aOrigin,
+                                bool* aIsApp)
+{
+  nsresult rv = GetDirectoryMetadata(aDirectory,
+                                     aTimestamp,
+                                     aGroup,
+                                     aOrigin,
+                                     aIsApp);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    rv = RestoreDirectoryMetadata(aDirectory, aPersistent);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    rv = GetDirectoryMetadata(aDirectory,
+                              aTimestamp,
+                              aGroup,
+                              aOrigin,
+                              aIsApp);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+GetDirectoryMetadata(nsIFile* aDirectory, int64_t* aTimestamp)
+{
+  AssertIsOnIOThread();
+  MOZ_ASSERT(aDirectory);
+  MOZ_ASSERT(aTimestamp);
+
+  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;
+  }
+
+  *aTimestamp = timestamp;
+  return NS_OK;
+}
+
+nsresult
+GetDirectoryMetadataWithRestore(nsIFile* aDirectory,
+                                bool aPersistent,
+                                int64_t* aTimestamp)
+{
+  nsresult rv = GetDirectoryMetadata(aDirectory, aTimestamp);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    rv = RestoreDirectoryMetadata(aDirectory, aPersistent);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    rv = GetDirectoryMetadata(aDirectory, aTimestamp);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
 MaybeUpgradeOriginDirectory(nsIFile* aDirectory)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(aDirectory, "Null pointer!");
 
   nsCOMPtr<nsIFile> metadataFile;
   nsresult rv = aDirectory->Clone(getter_AddRefs(metadataFile));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1817,16 +1919,19 @@ QuotaManager::GetDirectoryForOrigin(Pers
 
   directory.forget(aDirectory);
   return NS_OK;
 }
 
 nsresult
 QuotaManager::InitializeRepository(PersistenceType aPersistenceType)
 {
+  MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY ||
+             aPersistenceType == PERSISTENCE_TYPE_DEFAULT);
+
   nsresult rv;
 
   nsCOMPtr<nsIFile> directory =
     do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -1880,18 +1985,22 @@ QuotaManager::InitializeRepository(Persi
                  NS_ConvertUTF16toUTF8(leafName).get());
       return NS_ERROR_UNEXPECTED;
     }
 
     int64_t timestamp;
     nsCString group;
     nsCString origin;
     bool isApp;
-    rv = GetDirectoryMetadata(childDirectory, &timestamp, group, origin,
-                              &isApp);
+    rv = GetDirectoryMetadataWithRestore(childDirectory,
+                                         /* aPersistent */ false,
+                                         &timestamp,
+                                         group,
+                                         origin,
+                                         &isApp);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (IsTreatedAsPersistent(aPersistenceType, isApp)) {
       continue;
     }
 
@@ -2118,17 +2227,17 @@ QuotaManager::MaybeUpgradePersistentStor
     NS_WARNING("storage/persistent shouldn't exist after the upgrade!");
     return NS_OK;
   }
 
   // Create real metadata files for origin directories in persistent storage.
   nsRefPtr<StorageDirectoryHelper> helper =
     new StorageDirectoryHelper(persistentStorageDir, /* aPersistent */ true);
 
-  rv = helper->CreateOrUpgradeMetadataFiles();
+  rv = helper->CreateOrUpgradeMetadataFiles(/* aCreate */ true);
   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))) {
@@ -2154,17 +2263,17 @@ QuotaManager::MaybeUpgradePersistentStor
     if (!isDirectory) {
       NS_WARNING("temporary entry is not a directory!");
       return NS_OK;
     }
 
     helper = new StorageDirectoryHelper(temporaryStorageDir,
                                         /* aPersistent */ false);
 
-    rv = helper->CreateOrUpgradeMetadataFiles();
+    rv = helper->CreateOrUpgradeMetadataFiles(/* aCreate */ false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   // And finally rename persistent to default.
   NS_ConvertASCIItoUTF16 defDirName(NS_LITERAL_CSTRING(kDefaultDirectoryName));
   rv = persistentStorageDir->RenameTo(nullptr, defDirName);
@@ -2273,25 +2382,23 @@ QuotaManager::EnsureOriginIsInitialized(
   if (IsTreatedAsPersistent(aPersistenceType, aIsApp)) {
     if (created) {
       timestamp = PR_Now();
 
       rv = CreateDirectoryMetadata(directory, timestamp, aGroup, aOrigin,
                                    aIsApp);
       NS_ENSURE_SUCCESS(rv, rv);
     } else {
-      nsCOMPtr<nsIBinaryInputStream> stream;
-      rv = GetDirectoryMetadataInputStream(directory, getter_AddRefs(stream));
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      uint64_t ts;
-      rv = stream->Read64(&ts);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      timestamp = ts;
+      bool persistent = aPersistenceType == PERSISTENCE_TYPE_PERSISTENT;
+      rv = GetDirectoryMetadataWithRestore(directory,
+                                           persistent,
+                                           &timestamp);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
 
       MOZ_ASSERT(timestamp <= PR_Now());
     }
 
     rv = InitializeOrigin(aPersistenceType, aGroup, aOrigin, aIsApp, timestamp,
                           directory);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -3770,21 +3877,28 @@ OriginClearRunnable::DeleteFiles(QuotaMa
     }
 
     // Skip storages for other apps.
     if (!PatternMatchesOrigin(originSanitized,
                               NS_ConvertUTF16toUTF8(leafName))) {
       continue;
     }
 
+    bool persistent = aPersistenceType == PERSISTENCE_TYPE_PERSISTENT;
+
     int64_t timestamp;
     nsCString group;
     nsCString origin;
     bool isApp;
-    rv = GetDirectoryMetadata(file, &timestamp, group, origin, &isApp);
+    rv = GetDirectoryMetadataWithRestore(file,
+                                         persistent,
+                                         &timestamp,
+                                         group,
+                                         origin,
+                                         &isApp);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
 
     for (uint32_t index = 0; index < 10; index++) {
       // We can't guarantee that this will always succeed on Windows...
       if (NS_SUCCEEDED((rv = file->Remove(true)))) {
         break;
@@ -4364,101 +4478,156 @@ SaveOriginAccessTimeRunnable::Run()
     rv = stream->Write64(mTimestamp);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 nsresult
-StorageDirectoryHelper::CreateOrUpgradeMetadataFiles()
+StorageDirectoryHelper::CreateOrUpgradeMetadataFiles(bool aCreate)
 {
   AssertIsOnIOThread();
-
-  nsresult rv;
+  MOZ_ASSERT_IF(mPersistent, aCreate);
+
+  mCreate = aCreate;
 
   nsCOMPtr<nsISimpleEnumerator> entries;
-  rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
+  nsresult rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool hasMore;
   while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
     nsCOMPtr<nsISupports> entry;
     rv = entries->GetNext(getter_AddRefs(entry));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
     MOZ_ASSERT(originDir);
 
-    nsString leafName;
-    rv = originDir->GetLeafName(leafName);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
     bool isDirectory;
     rv = originDir->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (!isDirectory) {
+      nsString leafName;
+      rv = originDir->GetLeafName(leafName);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
       if (!leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
         NS_WARNING("Something in the storage directory that doesn't belong!");
       }
       continue;
     }
 
-    if (mPersistent) {
-      rv = MaybeUpgradeOriginDirectory(originDir);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-    }
-
-    if (leafName.EqualsLiteral(kChromeOrigin)) {
-      OriginProps* originProps = mOriginProps.AppendElement();
-      originProps->mDirectory = originDir;
-      originProps->mSpec = kChromeOrigin;
-      originProps->mType = OriginProps::eChrome;
-    } else {
-      nsCString spec;
-      uint32_t appId;
-      bool inMozBrowser;
-      if (NS_WARN_IF(!OriginParser::ParseOrigin(NS_ConvertUTF16toUTF8(leafName),
-                                                &appId, &inMozBrowser, spec))) {
-        return NS_ERROR_FAILURE;
-      }
-
-      OriginProps* originProps = mOriginProps.AppendElement();
-      originProps->mDirectory = originDir;
-      originProps->mSpec = spec;
-      originProps->mAppId = appId;
-      originProps->mType = OriginProps::eContent;
-      originProps->mInMozBrowser = inMozBrowser;
-
-      if (mPersistent) {
-        int64_t timestamp = INT64_MIN;
-        rv = GetLastModifiedTime(originDir, &timestamp);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-
-        originProps->mTimestamp = timestamp;
-      }
+    rv = AddOriginDirectory(originDir);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
     }
   }
 
   if (mOriginProps.IsEmpty()) {
     return NS_OK;
   }
 
+  rv = ProcessOriginDirectories(/* aMove */ true);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+StorageDirectoryHelper::RestoreMetadataFile()
+{
+  AssertIsOnIOThread();
+  MOZ_ASSERT(mCreate);
+
+  nsresult rv = AddOriginDirectory(mDirectory);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = ProcessOriginDirectories(/* aMove */ false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+StorageDirectoryHelper::AddOriginDirectory(nsIFile* aDirectory)
+{
+  MOZ_ASSERT(aDirectory);
+
+  nsresult rv;
+
+  if (mPersistent) {
+    rv = MaybeUpgradeOriginDirectory(aDirectory);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  nsString leafName;
+  rv = aDirectory->GetLeafName(leafName);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (leafName.EqualsLiteral(kChromeOrigin)) {
+    OriginProps* originProps = mOriginProps.AppendElement();
+    originProps->mDirectory = aDirectory;
+    originProps->mSpec = kChromeOrigin;
+    originProps->mType = OriginProps::eChrome;
+  } else {
+    nsCString spec;
+    uint32_t appId;
+    bool inMozBrowser;
+    if (NS_WARN_IF(!OriginParser::ParseOrigin(NS_ConvertUTF16toUTF8(leafName),
+                                              &appId, &inMozBrowser, spec))) {
+      return NS_ERROR_FAILURE;
+    }
+
+    OriginProps* originProps = mOriginProps.AppendElement();
+    originProps->mDirectory = aDirectory;
+    originProps->mSpec = spec;
+    originProps->mAppId = appId;
+    originProps->mType = OriginProps::eContent;
+    originProps->mInMozBrowser = inMozBrowser;
+
+    if (mCreate) {
+      int64_t timestamp = INT64_MIN;
+      rv = GetLastModifiedTime(aDirectory, &timestamp);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      originProps->mTimestamp = timestamp;
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+StorageDirectoryHelper::ProcessOriginDirectories(bool aMove)
+{
+  AssertIsOnIOThread();
+  MOZ_ASSERT(!mOriginProps.IsEmpty());
+
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
 
   {
     mozilla::MutexAutoLock autolock(mMutex);
     while (mWaiting) {
       mCondVar.Wait();
     }
   }
@@ -4468,35 +4637,39 @@ StorageDirectoryHelper::CreateOrUpgradeM
   }
 
   // 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;
+
   nsCOMPtr<nsIFile> permanentStorageDir;
 
   for (uint32_t count = mOriginProps.Length(), index = 0;
        index < count;
        index++) {
     OriginProps& originProps = mOriginProps[index];
 
-    if (mPersistent) {
+    if (mCreate) {
       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 (QuotaManager::IsOriginWhitelistedForPersistentStorage(
+      if (mPersistent &&
+          aMove &&
+          QuotaManager::IsOriginWhitelistedForPersistentStorage(
                                                            originProps.mSpec)) {
         if (!permanentStorageDir) {
           permanentStorageDir =
             do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
 
@@ -4581,17 +4754,17 @@ StorageDirectoryHelper::RunOnMainThread(
                                                originProps.mAppId,
                                                originProps.mInMozBrowser,
                                                getter_AddRefs(principal));
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
 
-        if (mPersistent) {
+        if (mCreate) {
           rv = QuotaManager::GetInfoFromPrincipal(principal,
                                                   &originProps.mGroup,
                                                   &originProps.mOrigin,
                                                   &originProps.mIsApp);
         } else {
           rv = QuotaManager::GetInfoFromPrincipal(principal,
                                                   nullptr,
                                                   nullptr,