Bug 1314361: Part 7b - Strip addonId from existing quota storage origins. r?janv
MozReview-Commit-ID: ABBe4LmbSmi
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -158,17 +158,17 @@ class VersionChangeTransaction;
******************************************************************************/
// If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
// schema version.
static_assert(JS_STRUCTURED_CLONE_VERSION == 8,
"Need to update the major schema version.");
// Major schema version. Bump for almost everything.
-const uint32_t kMajorSchemaVersion = 25;
+const uint32_t kMajorSchemaVersion = 26;
// Minor schema version. Should almost always be 0 (maybe bump on release
// branches if we have to).
const uint32_t kMinorSchemaVersion = 0;
// The schema version we store in the SQLite database is a (signed) 32-bit
// integer. The major version is left-shifted 4 bits so the max value is
// 0xFFFFFFF. The minor version occupies the lower 4 bits and its max is 0xF.
@@ -4126,16 +4126,103 @@ UpgradeSchemaFrom24_0To25_0(mozIStorageC
nsresult rv = aConnection->SetSchemaVersion(MakeSchemaVersion(25, 0));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
+class StripObsoleteOriginAttributesFunction final
+ : public mozIStorageFunction
+{
+public:
+ NS_DECL_ISUPPORTS
+
+private:
+ ~StripObsoleteOriginAttributesFunction()
+ { }
+
+ NS_IMETHOD
+ OnFunctionCall(mozIStorageValueArray* aArguments,
+ nsIVariant** aResult) override
+ {
+ MOZ_ASSERT(aArguments);
+ MOZ_ASSERT(aResult);
+
+ PROFILER_LABEL("IndexedDB",
+ "StripObsoleteOriginAttributesFunction::OnFunctionCall",
+ js::ProfileEntry::Category::STORAGE);
+
+ nsCString origin;
+ nsresult rv = aArguments->GetUTF8String(0, origin);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ // Deserialize and re-serialize to automatically drop any obsolete origin
+ // attributes.
+ OriginAttributes oa;
+ nsCString newOrigin;
+ bool ok = oa.PopulateFromOrigin(origin, newOrigin);
+ if (NS_WARN_IF(!ok)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsAutoCString newSuffix;
+ oa.CreateSuffix(newSuffix);
+ newOrigin.Append(newSuffix);
+
+ nsCOMPtr<nsIVariant> result = new mozilla::storage::TextVariant(
+ NS_ConvertUTF8toUTF16(newOrigin));
+
+ result.forget(aResult);
+ return NS_OK;
+ }
+};
+
+nsresult
+UpgradeSchemaFrom25_0To26_0(mozIStorageConnection* aConnection)
+{
+ AssertIsOnIOThread();
+ MOZ_ASSERT(aConnection);
+
+ PROFILER_LABEL("IndexedDB",
+ "UpgradeSchemaFrom25_0To26_0",
+ js::ProfileEntry::Category::STORAGE);
+
+ NS_NAMED_LITERAL_CSTRING(functionName, "strip_obsolete_attributes");
+
+ nsCOMPtr<mozIStorageFunction> stripObsoleteAttributes = new StripObsoleteOriginAttributesFunction();
+
+ nsresult rv = aConnection->CreateFunction(functionName, 1, stripObsoleteAttributes);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+ "UPDATE DATABASE "
+ " SET origin = strip_obsolete_attributes(origin) "
+ " WHERE origin LIKE '%^%' "
+ ";"
+ ));
+
+ rv = aConnection->RemoveFunction(functionName);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = aConnection->SetSchemaVersion(MakeSchemaVersion(26, 0));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ return NS_OK;
+}
+
nsresult
GetDatabaseFileURL(nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
uint32_t aTelemetryId,
nsIFileURL** aResult)
{
@@ -4632,17 +4719,17 @@ CreateStorageConnection(nsIFile* aDBFile
}
rv = stmt->Execute();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
// This logic needs to change next time we change the schema!
- static_assert(kSQLiteSchemaVersion == int32_t((25 << 4) + 0),
+ static_assert(kSQLiteSchemaVersion == int32_t((26 << 4) + 0),
"Upgrade function needed due to schema version increase.");
while (schemaVersion != kSQLiteSchemaVersion) {
if (schemaVersion == 4) {
rv = UpgradeSchemaFrom4To5(connection);
} else if (schemaVersion == 5) {
rv = UpgradeSchemaFrom5To6(connection);
} else if (schemaVersion == 6) {
@@ -4680,16 +4767,18 @@ CreateStorageConnection(nsIFile* aDBFile
} else if (schemaVersion == MakeSchemaVersion(21, 0)) {
rv = UpgradeSchemaFrom21_0To22_0(connection);
} else if (schemaVersion == MakeSchemaVersion(22, 0)) {
rv = UpgradeSchemaFrom22_0To23_0(connection, aOrigin);
} else if (schemaVersion == MakeSchemaVersion(23, 0)) {
rv = UpgradeSchemaFrom23_0To24_0(connection);
} else if (schemaVersion == MakeSchemaVersion(24, 0)) {
rv = UpgradeSchemaFrom24_0To25_0(connection);
+ } else if (schemaVersion == MakeSchemaVersion(25, 0)) {
+ rv = UpgradeSchemaFrom25_0To26_0(connection);
} else {
IDB_WARNING("Unable to open IndexedDB database, no upgrade path is "
"available!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -19327,16 +19416,17 @@ AutoProgressHandler::OnProgress(mozIStor
}
/*******************************************************************************
* Local class implementations
******************************************************************************/
NS_IMPL_ISUPPORTS(CompressDataBlobsFunction, mozIStorageFunction)
NS_IMPL_ISUPPORTS(EncodeKeysFunction, mozIStorageFunction)
+NS_IMPL_ISUPPORTS(StripObsoleteOriginAttributesFunction, mozIStorageFunction);
#if !defined(MOZ_B2G)
nsresult
UpgradeFileIdsFunction::Init(nsIFile* aFMDirectory,
mozIStorageConnection* aConnection)
{
// This file manager doesn't need real origin info, etc. The only purpose is
new file mode 100644
index 0000000000000000000000000000000000000000..f05ff4f24aa119ddc415fd067fc96079b6e27056
GIT binary patch
literal 11853
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
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_obsoleteOriginAttributesUpgrade.js
@@ -0,0 +1,71 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+Components.utils.import("resource://gre/modules/FileUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+var testGenerator = testSteps();
+
+function* testSteps()
+{
+ const openParams = [
+ { url: "moz-extension://8ea6d31b-917c-431f-a204-15b95e904d4f",
+ dbName: "Hello.", dbVersion: 1 },
+ { url: "moz-extension://8ea6d31b-917c-431f-a204-15b95e904d4f",
+ dbName: "Hello.", dbOptions: { version: 1, storage: "temporary" } },
+ { url: "moz-extension://8ea6d31b-917c-431f-a204-15b95e904d4f",
+ dbName: "Hello.", dbOptions: { version: 1, storage: "permanent" } },
+ ];
+
+ function openDatabase(params) {
+ let uri = Services.io.newURI(params.url);
+ let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
+ return indexedDB.openForPrincipal(principal, params.dbName,
+ params.dbVersion);
+ }
+
+ clearAllDatabases(continueToNextStepSync);
+ yield;
+
+ installPackagedProfile("obsoleteOriginAttributes_profile");
+
+ for (let params of openParams) {
+ let request = openDatabase(params);
+ request.onerror = errorHandler;
+ request.onupgradeneeded = unexpectedSuccessHandler;
+ request.onsuccess = grabEventAndContinueHandler;
+ let event = yield;
+
+ is(event.type, "success", "Correct event type");
+ }
+
+ resetAllDatabases(continueToNextStepSync);
+ yield;
+
+ for (let params of openParams) {
+ let request = openDatabase(params);
+ request.onerror = errorHandler;
+ request.onupgradeneeded = unexpectedSuccessHandler;
+ request.onsuccess = grabEventAndContinueHandler;
+ let event = yield;
+
+ is(event.type, "success", "Correct event type");
+ }
+
+ const OLD_NAME = "moz-extension+++8ea6d31b-917c-431f-a204-15b95e904d4f^addonId=indexedDB-test%40kmaglione.mozilla.com";
+ const NEW_NAME = "moz-extension+++8ea6d31b-917c-431f-a204-15b95e904d4f";
+
+ for (let subdir of ["default", "temporary", "permanent"]) {
+ let file = FileUtils.getFile("ProfD", ["storage", subdir, OLD_NAME]);
+ ok(!file.exists(), `Old ${subdir} storage directory should not exist`);
+
+ file.leafName = NEW_NAME;
+ ok(file.exists(), `New ${subdir} storage directory should exist`);
+ }
+
+ finishTest();
+ yield;
+}
+
--- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini
+++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
@@ -8,16 +8,17 @@ head = xpcshell-head-parent-process.js
tail =
skip-if = toolkit == 'gonk'
support-files =
bug1056939_profile.zip
defaultStorageUpgrade_profile.zip
idbSubdirUpgrade1_profile.zip
idbSubdirUpgrade2_profile.zip
mutableFileUpgrade_profile.zip
+ obsoleteOriginAttributes_profile.zip
oldDirectories_profile.zip
GlobalObjectsChild.js
GlobalObjectsComponent.js
GlobalObjectsComponent.manifest
GlobalObjectsModule.jsm
GlobalObjectsSandbox.js
metadata2Restore_profile.zip
metadataRestore_profile.zip
@@ -28,16 +29,17 @@ support-files =
storagePersistentUpgrade_profile.zip
wasm_recompile_profile.zip
xpcshell-shared.ini
[include:xpcshell-shared.ini]
[test_bad_origin_directory.js]
skip-if = release_or_beta
+[test_obsoleteOriginAttributesUpgrade.js]
[test_blob_file_backed.js]
[test_bug1056939.js]
[test_cleanup_transaction.js]
[test_database_close_without_onclose.js]
[test_database_onclose.js]
[test_defaultStorageUpgrade.js]
[test_file_copy_failure.js]
[test_idbSubdirUpgrade.js]
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -116,17 +116,17 @@ namespace {
/*******************************************************************************
* Constants
******************************************************************************/
const uint32_t kSQLitePageSizeOverride = 512;
// Major storage version. Bump for backwards-incompatible changes.
-const uint32_t kMajorStorageVersion = 1;
+const uint32_t kMajorStorageVersion = 2;
// Minor storage version. Bump for backwards-compatible changes.
const uint32_t kMinorStorageVersion = 0;
// The storage version we store in the SQLite database is a (signed) 32-bit
// integer. The major version is left-shifted 16 bits so the max value is
// 0xFFFF. The minor version occupies the lower 16 bits and its max is 0xFFFF.
static_assert(kMajorStorageVersion <= 0xFFFF,
@@ -175,24 +175,22 @@ enum AppId {
// origin.
#define METADATA_FILE_NAME ".metadata"
#define METADATA_V2_FILE_NAME ".metadata-v2"
/******************************************************************************
* SQLite functions
******************************************************************************/
-#if 0
int32_t
MakeStorageVersion(uint32_t aMajorStorageVersion,
uint32_t aMinorStorageVersion)
{
return int32_t((aMajorStorageVersion << 16) + aMinorStorageVersion);
}
-#endif
uint32_t
GetMajorStorageVersion(int32_t aStorageVersion)
{
return uint32_t(aStorageVersion >> 16);
}
@@ -1540,16 +1538,40 @@ public:
nsresult
RestoreMetadata2File();
private:
virtual nsresult
DoProcessOriginDirectories();
};
+class UpdateDirectoryMetadataOriginHelper final
+ : public StorageDirectoryHelper
+{
+public:
+ explicit UpdateDirectoryMetadataOriginHelper(nsIFile* aDirectory)
+ : StorageDirectoryHelper(aDirectory)
+ { }
+
+ nsresult
+ UpgradeMetadataFiles();
+
+private:
+ nsresult
+ GetDirectoryMetadata2(nsIFile* aDirectory,
+ int64_t* aTimestamp,
+ nsACString& aSuffix,
+ nsACString& aGroup,
+ nsACString& aOrigin,
+ bool* aIsApp);
+
+ virtual nsresult
+ DoProcessOriginDirectories() override;
+};
+
class OriginKey : public nsAutoCString
{
public:
OriginKey(PersistenceType aPersistenceType,
const nsACString& aOrigin)
{
PersistenceTypeToText(aPersistenceType, *this);
Append(':');
@@ -4184,45 +4206,60 @@ QuotaManager::UpgradeStorageFrom0_0To1_0
rv = aConnection->SetSchemaVersion(kStorageVersion);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
-#if 0
nsresult
QuotaManager::UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection)
{
AssertIsOnIOThread();
MOZ_ASSERT(aConnection);
nsresult rv;
-
-#ifdef DEBUG
- {
- int32_t storageVersion;
- rv = aConnection->GetSchemaVersion(&storageVersion);
+ for (const PersistenceType persistenceType : kAllPersistenceTypes) {
+ nsCOMPtr<nsIFile> directory =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = directory->InitWithPath(GetStoragePath(persistenceType));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
- MOZ_ASSERT(storageVersion == MakeStorageVersion(1, 0));
- }
-#endif
+ bool exists;
+ rv = directory->Exists(&exists);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ if (!exists) {
+ continue;
+ }
+
+ RefPtr<UpdateDirectoryMetadataOriginHelper> helper =
+ new UpdateDirectoryMetadataOriginHelper(directory);
+
+ rv = helper->UpgradeMetadataFiles();
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
rv = aConnection->SetSchemaVersion(MakeStorageVersion(2, 0));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
-#endif
nsresult
QuotaManager::EnsureStorageIsInitialized()
{
AssertIsOnIOThread();
if (mStorageInitialized) {
return NS_OK;
@@ -4351,26 +4388,24 @@ QuotaManager::EnsureStorageIsInitialized
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(NS_SUCCEEDED(connection->GetSchemaVersion(&storageVersion)));
MOZ_ASSERT(storageVersion == kStorageVersion);
} else {
// This logic needs to change next time we change the storage!
- static_assert(kStorageVersion == int32_t((1 << 16) + 0),
+ static_assert(kStorageVersion == int32_t((2 << 16) + 0),
"Upgrade function needed due to storage version increase.");
while (storageVersion != kStorageVersion) {
if (storageVersion == 0) {
rv = UpgradeStorageFrom0_0To1_0(connection);
-#if 0
} else if (storageVersion == MakeStorageVersion(1, 0)) {
rv = UpgradeStorageFrom1_0To2_0(connection);
-#endif
} else {
NS_WARNING("Unable to initialize storage, no upgrade path is "
"available!");
return NS_ERROR_FAILURE;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -7711,11 +7746,231 @@ RestoreDirectoryMetadata2Helper::DoProce
originProps.mIsApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
+nsresult
+UpdateDirectoryMetadataOriginHelper::GetDirectoryMetadata2(nsIFile* aDirectory,
+ int64_t* aTimestamp,
+ nsACString& aSuffix,
+ nsACString& aGroup,
+ nsACString& aOrigin,
+ bool* aIsApp)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+ MOZ_ASSERT(aDirectory);
+ MOZ_ASSERT(aTimestamp);
+ MOZ_ASSERT(aIsApp);
+
+ nsCOMPtr<nsIBinaryInputStream> binaryStream;
+ nsresult rv = GetBinaryInputStream(aDirectory,
+ NS_LITERAL_STRING(METADATA_V2_FILE_NAME),
+ getter_AddRefs(binaryStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint64_t timestamp;
+ rv = binaryStream->Read64(×tamp);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool persisted;
+ rv = binaryStream->ReadBoolean(&persisted);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t reservedData1;
+ rv = binaryStream->Read32(&reservedData1);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t reservedData2;
+ rv = binaryStream->Read32(&reservedData2);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString suffix;
+ rv = binaryStream->ReadCString(suffix);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString group;
+ rv = binaryStream->ReadCString(group);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString origin;
+ rv = binaryStream->ReadCString(origin);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool isApp;
+ rv = binaryStream->ReadBoolean(&isApp);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aTimestamp = timestamp;
+ aSuffix = suffix;
+ aGroup = group;
+ aOrigin = origin;
+ *aIsApp = isApp;
+ return NS_OK;
+}
+
+nsresult
+UpdateDirectoryMetadataOriginHelper::UpgradeMetadataFiles()
+{
+ AssertIsOnIOThread();
+
+ bool exists;
+ nsresult rv = mDirectory->Exists(&exists);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (!exists) {
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = mDirectory->GetDirectoryEntries(getter_AddRefs(entries));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ bool hasMore;
+ while (NS_SUCCEEDED(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);
+
+ 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)) {
+ QM_WARNING("Something (%s) in the storage directory that doesn't belong!",
+ NS_ConvertUTF16toUTF8(leafName).get());
+
+ }
+ continue;
+ }
+
+ OriginProps* originProps;
+ rv = AddOriginDirectory(originDir, &originProps);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsresult rv = GetDirectoryMetadata2(originDir,
+ &originProps->mTimestamp,
+ originProps->mSuffix,
+ originProps->mGroup,
+ originProps->mOrigin,
+ &originProps->mIsApp);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ // This isn't a fatal error. If we fail to read the metadata file, we fall
+ // back to the metadata extracted from the directory name.
+ QM_WARNING("Origin directory %s is missing metadata file",
+ originProps->mOrigin.get());
+ }
+ }
+
+ if (mOriginProps.IsEmpty()) {
+ return NS_OK;
+ }
+
+ rv = ProcessOriginDirectories();
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+UpdateDirectoryMetadataOriginHelper::DoProcessOriginDirectories()
+{
+ AssertIsOnIOThread();
+
+ for (auto& originProps : mOriginProps) {
+ nsresult rv;
+
+ // Attempt to rename the directory to the new origin.
+ nsAutoCString newOrigin(originProps.mOrigin);
+ SanitizeOriginString(newOrigin);
+
+ NS_ConvertUTF8toUTF16 newLeafName(newOrigin);
+
+ nsString oldLeafName;
+ rv = originProps.mDirectory->GetLeafName(oldLeafName);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (oldLeafName == newLeafName) {
+ continue;
+ }
+
+ nsCOMPtr<nsIFile> newFile;
+ rv = originProps.mDirectory->GetParent(getter_AddRefs(newFile));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = newFile->Append(newLeafName);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ bool exists;
+ rv = newFile->Exists(&exists);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (exists) {
+ QM_WARNING("Origin directory with addonId attribute (%s) clashes with existing origin (%s)",
+ NS_ConvertUTF16toUTF8(oldLeafName).get(), newOrigin.get());
+ continue;
+ }
+
+ rv = CreateDirectoryMetadata(originProps.mDirectory,
+ originProps.mTimestamp,
+ originProps.mSuffix,
+ originProps.mGroup,
+ originProps.mOrigin,
+ originProps.mIsApp);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = CreateDirectoryMetadata2(originProps.mDirectory,
+ originProps.mTimestamp,
+ originProps.mSuffix,
+ originProps.mGroup,
+ originProps.mOrigin,
+ originProps.mIsApp);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = originProps.mDirectory->RenameTo(nullptr, newLeafName);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+
+ return NS_OK;
+}
+
} // namespace quota
} // namespace dom
} // namespace mozilla
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -452,20 +452,18 @@ private:
MaybeUpgradePersistentStorageDirectory();
nsresult
MaybeRemoveOldDirectories();
nsresult
UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection);
-#if 0
nsresult
UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection);
-#endif
nsresult
InitializeRepository(PersistenceType aPersistenceType);
nsresult
InitializeOrigin(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,