Bug 1546305 - LSNG: Add temporary support for downgrading; r=asuth

Differential Revision: https://phabricator.services.mozilla.com/D28800
This commit is contained in:
Jan Varga 2019-04-25 11:25:52 +02:00
Родитель c0cc4f7980
Коммит 4d4622f55f
8 изменённых файлов: 624 добавлений и 37 удалений

Двоичный файл не отображается.

Просмотреть файл

@ -223,6 +223,8 @@ enum AppId {
#define LS_ARCHIVE_FILE_NAME "ls-archive.sqlite"
#define LS_ARCHIVE_TMP_FILE_NAME "ls-archive-tmp.sqlite"
const uint32_t kLocalStorageArchiveVersion = 1;
const char kProfileDoChangeTopic[] = "profile-do-change";
/******************************************************************************
@ -325,6 +327,158 @@ nsresult CreateWebAppsStoreConnection(nsIFile* aWebAppsStoreFile,
return NS_OK;
}
nsresult GetLocalStorageArchiveFile(const nsAString& aDirectoryPath,
nsIFile** aLsArchiveFile) {
AssertIsOnIOThread();
MOZ_ASSERT(!aDirectoryPath.IsEmpty());
MOZ_ASSERT(aLsArchiveFile);
nsCOMPtr<nsIFile> lsArchiveFile;
nsresult rv =
NS_NewLocalFile(aDirectoryPath, false, getter_AddRefs(lsArchiveFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveFile->Append(NS_LITERAL_STRING(LS_ARCHIVE_FILE_NAME));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
lsArchiveFile.forget(aLsArchiveFile);
return NS_OK;
}
nsresult GetLocalStorageArchiveTmpFile(const nsAString& aDirectoryPath,
nsIFile** aLsArchiveTmpFile) {
AssertIsOnIOThread();
MOZ_ASSERT(!aDirectoryPath.IsEmpty());
MOZ_ASSERT(aLsArchiveTmpFile);
nsCOMPtr<nsIFile> lsArchiveTmpFile;
nsresult rv =
NS_NewLocalFile(aDirectoryPath, false, getter_AddRefs(lsArchiveTmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveTmpFile->Append(NS_LITERAL_STRING(LS_ARCHIVE_TMP_FILE_NAME));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
lsArchiveTmpFile.forget(aLsArchiveTmpFile);
return NS_OK;
}
nsresult InitializeLocalStorageArchive(mozIStorageConnection* aConnection,
uint32_t aVersion) {
AssertIsOnIOThread();
MOZ_ASSERT(aConnection);
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE database(version INTEGER NOT NULL DEFAULT 0);"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<mozIStorageStatement> stmt;
rv = aConnection->CreateStatement(
NS_LITERAL_CSTRING("INSERT INTO database (version) VALUES (:version)"),
getter_AddRefs(stmt));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("version"), aVersion);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->Execute();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult IsLocalStorageArchiveInitialized(mozIStorageConnection* aConnection,
bool& aInitialized) {
AssertIsOnIOThread();
MOZ_ASSERT(aConnection);
bool exists;
nsresult rv =
aConnection->TableExists(NS_LITERAL_CSTRING("database"), &exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aInitialized = exists;
return NS_OK;
}
nsresult LoadLocalStorageArchiveVersion(mozIStorageConnection* aConnection,
uint32_t& aVersion) {
AssertIsOnIOThread();
MOZ_ASSERT(aConnection);
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(
NS_LITERAL_CSTRING("SELECT version FROM database"), getter_AddRefs(stmt));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool hasResult;
rv = stmt->ExecuteStep(&hasResult);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (NS_WARN_IF(!hasResult)) {
return NS_ERROR_FILE_CORRUPTED;
}
int32_t version;
rv = stmt->GetInt32(0, &version);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aVersion = version;
return NS_OK;
}
/*
nsresult SaveLocalStorageArchiveVersion(mozIStorageConnection* aConnection,
uint32_t aVersion) {
AssertIsOnIOThread();
MOZ_ASSERT(aConnection);
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(
NS_LITERAL_CSTRING("UPDATE database SET version = :version;"),
getter_AddRefs(stmt));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("version"), aVersion);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->Execute();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
*/
/******************************************************************************
* Quota manager class declarations
******************************************************************************/
@ -4553,13 +4707,8 @@ nsresult QuotaManager::MaybeRemoveLocalStorageData() {
// Cleanup the tmp file first, if there's any.
nsCOMPtr<nsIFile> lsArchiveTmpFile;
nsresult rv =
NS_NewLocalFile(mStoragePath, false, getter_AddRefs(lsArchiveTmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveTmpFile->Append(NS_LITERAL_STRING(LS_ARCHIVE_TMP_FILE_NAME));
nsresult rv = GetLocalStorageArchiveTmpFile(mStoragePath,
getter_AddRefs(lsArchiveTmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -4579,12 +4728,7 @@ nsresult QuotaManager::MaybeRemoveLocalStorageData() {
// Now check the real archive file.
nsCOMPtr<nsIFile> lsArchiveFile;
rv = NS_NewLocalFile(mStoragePath, false, getter_AddRefs(lsArchiveFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveFile->Append(NS_LITERAL_STRING(LS_ARCHIVE_FILE_NAME));
rv = GetLocalStorageArchiveFile(mStoragePath, getter_AddRefs(lsArchiveFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -4740,33 +4884,27 @@ nsresult QuotaManager::MaybeRemoveLocalStorageDirectories() {
return NS_OK;
}
nsresult QuotaManager::MaybeCreateLocalStorageArchive() {
nsresult QuotaManager::CreateLocalStorageArchiveConnectionFromWebAppsStore(
mozIStorageConnection** aConnection) {
AssertIsOnIOThread();
MOZ_ASSERT(CachedNextGenLocalStorageEnabled());
MOZ_ASSERT(aConnection);
// Check if the archive was already successfully created.
nsCOMPtr<nsIFile> lsArchiveFile;
nsresult rv =
NS_NewLocalFile(mStoragePath, false, getter_AddRefs(lsArchiveFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveFile->Append(NS_LITERAL_STRING(LS_ARCHIVE_FILE_NAME));
GetLocalStorageArchiveFile(mStoragePath, getter_AddRefs(lsArchiveFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
#ifdef DEBUG
bool exists;
rv = lsArchiveFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (exists) {
// ls-archive.sqlite already exists, nothing to create.
return NS_OK;
}
MOZ_ASSERT(!exists);
#endif
// Get the storage service first, we will need it at multiple places.
nsCOMPtr<mozIStorageService> ss =
@ -4856,12 +4994,8 @@ nsresult QuotaManager::MaybeCreateLocalStorageArchive() {
}
nsCOMPtr<nsIFile> lsArchiveTmpFile;
rv = NS_NewLocalFile(mStoragePath, false, getter_AddRefs(lsArchiveTmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveTmpFile->Append(NS_LITERAL_STRING(LS_ARCHIVE_TMP_FILE_NAME));
rv = GetLocalStorageArchiveTmpFile(mStoragePath,
getter_AddRefs(lsArchiveTmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -4895,6 +5029,15 @@ nsresult QuotaManager::MaybeCreateLocalStorageArchive() {
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<mozIStorageConnection> lsArchiveConnection;
rv = ss->OpenUnsharedDatabase(lsArchiveFile,
getter_AddRefs(lsArchiveConnection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
lsArchiveConnection.forget(aConnection);
} else {
// If webappsstore database is not useable, just create an empty archive.
@ -4923,11 +5066,227 @@ nsresult QuotaManager::MaybeCreateLocalStorageArchive() {
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
lsArchiveConnection.forget(aConnection);
}
return NS_OK;
}
nsresult QuotaManager::CreateLocalStorageArchiveConnection(
mozIStorageConnection** aConnection, bool& aNewlyCreated) {
AssertIsOnIOThread();
MOZ_ASSERT(CachedNextGenLocalStorageEnabled());
MOZ_ASSERT(aConnection);
nsCOMPtr<nsIFile> lsArchiveTmpFile;
nsresult rv = GetLocalStorageArchiveTmpFile(mStoragePath,
getter_AddRefs(lsArchiveTmpFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool exists;
rv = lsArchiveTmpFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (exists) {
rv = lsArchiveTmpFile->Remove(false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// Check if the archive was already successfully created.
nsCOMPtr<nsIFile> lsArchiveFile;
rv = GetLocalStorageArchiveFile(mStoragePath, getter_AddRefs(lsArchiveFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (exists) {
bool removed = false;
bool isDirectory;
rv = lsArchiveFile->IsDirectory(&isDirectory);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (isDirectory) {
rv = lsArchiveFile->Remove(true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
removed = true;
}
nsCOMPtr<mozIStorageService> ss =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<mozIStorageConnection> connection;
rv = ss->OpenUnsharedDatabase(lsArchiveFile, getter_AddRefs(connection));
if (!removed && rv == NS_ERROR_FILE_CORRUPTED) {
rv = lsArchiveFile->Remove(false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
removed = true;
rv = ss->OpenUnsharedDatabase(lsArchiveFile, getter_AddRefs(connection));
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = StorageDBUpdater::Update(connection);
if (!removed && NS_FAILED(rv)) {
rv = connection->Close();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lsArchiveFile->Remove(false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
removed = true;
rv = ss->OpenUnsharedDatabase(lsArchiveFile, getter_AddRefs(connection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = StorageDBUpdater::Update(connection);
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
connection.forget(aConnection);
aNewlyCreated = removed;
return NS_OK;
}
nsCOMPtr<mozIStorageConnection> connection;
rv = CreateLocalStorageArchiveConnectionFromWebAppsStore(
getter_AddRefs(connection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
connection.forget(aConnection);
aNewlyCreated = true;
return NS_OK;
}
nsresult QuotaManager::RecreateLocalStorageArchive(
nsCOMPtr<mozIStorageConnection>& aConnection) {
AssertIsOnIOThread();
MOZ_ASSERT(CachedNextGenLocalStorageEnabled());
// Close local storage archive connection. We are going to remove underlying
// file.
nsresult rv = aConnection->Close();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = MaybeRemoveLocalStorageDirectories();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIFile> lsArchiveFile;
rv = GetLocalStorageArchiveFile(mStoragePath, getter_AddRefs(lsArchiveFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
#ifdef DEBUG
bool exists;
rv = lsArchiveFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(exists);
#endif
rv = lsArchiveFile->Remove(false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = CreateLocalStorageArchiveConnectionFromWebAppsStore(
getter_AddRefs(aConnection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult QuotaManager::DowngradeLocalStorageArchive(
nsCOMPtr<mozIStorageConnection>& aConnection) {
AssertIsOnIOThread();
MOZ_ASSERT(CachedNextGenLocalStorageEnabled());
nsresult rv = RecreateLocalStorageArchive(aConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = InitializeLocalStorageArchive(aConnection, kLocalStorageArchiveVersion);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult QuotaManager::UpgradeLocalStorageArchiveFrom0To1(
nsCOMPtr<mozIStorageConnection>& aConnection) {
AssertIsOnIOThread();
MOZ_ASSERT(CachedNextGenLocalStorageEnabled());
nsresult rv = RecreateLocalStorageArchive(aConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = InitializeLocalStorageArchive(aConnection, 1);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
/*
nsresult QuotaManager::UpgradeLocalStorageArchiveFrom1To2(
nsCOMPtr<mozIStorageConnection>& aConnection) {
nsresult rv = SaveLocalStorageArchiveVersion(aConnection, 2);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
*/
#ifdef DEBUG
void QuotaManager::AssertStorageIsInitialized() const {
@ -5103,12 +5462,87 @@ nsresult QuotaManager::EnsureStorageIsInitialized() {
}
if (CachedNextGenLocalStorageEnabled()) {
rv = MaybeCreateLocalStorageArchive();
nsCOMPtr<mozIStorageConnection> connection;
bool newlyCreated;
rv = CreateLocalStorageArchiveConnection(getter_AddRefs(connection),
newlyCreated);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
uint32_t version = 0;
if (!newlyCreated) {
bool initialized;
rv = IsLocalStorageArchiveInitialized(connection, initialized);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (initialized) {
rv = LoadLocalStorageArchiveVersion(connection, version);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
}
if (version > kLocalStorageArchiveVersion) {
rv = DowngradeLocalStorageArchive(connection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = LoadLocalStorageArchiveVersion(connection, version);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(version == kLocalStorageArchiveVersion);
} else if (version != kLocalStorageArchiveVersion) {
if (newlyCreated) {
MOZ_ASSERT(version == 0);
rv = InitializeLocalStorageArchive(connection,
kLocalStorageArchiveVersion);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
static_assert(kLocalStorageArchiveVersion == 1,
"Upgrade function needed due to LocalStorage archive "
"version increase.");
while (version != kLocalStorageArchiveVersion) {
if (version == 0) {
rv = UpgradeLocalStorageArchiveFrom0To1(connection);
} /* else if (version == 1) {
rv = UpgradeLocalStorageArchiveFrom1To2(connection);
} */ else {
QM_WARNING(
"Unable to initialize LocalStorage archive, no upgrade path is "
"available!");
return NS_ERROR_FAILURE;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = LoadLocalStorageArchiveVersion(connection, version);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
MOZ_ASSERT(version == kLocalStorageArchiveVersion);
}
}
} else {
rv = MaybeRemoveLocalStorageData();
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
mStorageInitialized = true;

Просмотреть файл

@ -425,7 +425,25 @@ class QuotaManager final : public BackgroundThreadObject {
nsresult MaybeRemoveLocalStorageDirectories();
nsresult MaybeCreateLocalStorageArchive();
nsresult CreateLocalStorageArchiveConnectionFromWebAppsStore(
mozIStorageConnection** aConnection);
nsresult CreateLocalStorageArchiveConnection(
mozIStorageConnection** aConnection, bool& aNewlyCreated);
nsresult RecreateLocalStorageArchive(
nsCOMPtr<mozIStorageConnection>& aConnection);
nsresult DowngradeLocalStorageArchive(
nsCOMPtr<mozIStorageConnection>& aConnection);
nsresult UpgradeLocalStorageArchiveFrom0To1(
nsCOMPtr<mozIStorageConnection>& aConnection);
/*
nsresult UpgradeLocalStorageArchiveFrom1To2(
nsCOMPtr<mozIStorageConnection>& aConnection);
*/
nsresult InitializeRepository(PersistenceType aPersistenceType);

Двоичные данные
dom/quota/test/unit/localStorageArchive1upgrade_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/localStorageArchiveDowngrade_profile.zip Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,65 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* This test is mainly to verify that local storage directories are removed
* during local storage archive upgrade from version 0 to version 1.
* See bug 1546305.
*/
async function testSteps() {
const lsDirs = [
"storage/default/http+++example.com/ls",
"storage/default/http+++localhost/ls",
"storage/default/http+++www.mozilla.org/ls",
];
info("Clearing");
let request = clear();
await requestFinished(request);
info("Installing package");
// The profile contains three initialized origin directories with local
// storage data, local storage archive, a script for origin initialization,
// the storage database and the web apps store database:
// - storage/default/https+++example.com
// - storage/default/https+++localhost
// - storage/default/https+++www.mozilla.org
// - storage/ls-archive.sqlite
// - create_db.js
// - storage.sqlite
// - webappsstore.sqlite
// The file create_db.js in the package was run locally (with a build that
// doesn't support local storage archive upgrades), specifically it was
// temporarily added to xpcshell.ini and then executed:
// mach xpcshell-test --interactive dom/localstorage/test/unit/create_db.js
// Note: to make it become the profile in the test, additional manual steps
// are needed.
// 1. Remove the folder "storage/temporary".
installPackage("localStorageArchive1upgrade_profile");
info("Checking ls dirs");
for (let lsDir of lsDirs) {
let dir = getRelativeFile(lsDir);
exists = dir.exists();
ok(exists, "ls directory does exist");
}
request = init();
request = await requestFinished(request);
info("Checking ls dirs");
for (let lsDir of lsDirs) {
let dir = getRelativeFile(lsDir);
exists = dir.exists();
ok(!exists, "ls directory doesn't exist");
}
}

Просмотреть файл

@ -0,0 +1,66 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* This test is mainly to verify that local storage directories are removed
* during local storage archive downgrade from any future version to current
* version. See bug 1546305.
*/
async function testSteps() {
const lsDirs = [
"storage/default/http+++example.com/ls",
"storage/default/http+++localhost/ls",
"storage/default/http+++www.mozilla.org/ls",
];
info("Clearing");
let request = clear();
await requestFinished(request);
info("Installing package");
// The profile contains three initialized origin directories with local
// storage data, local storage archive, a script for origin initialization,
// the storage database and the web apps store database:
// - storage/default/https+++example.com
// - storage/default/https+++localhost
// - storage/default/https+++www.mozilla.org
// - storage/ls-archive.sqlite
// - create_db.js
// - storage.sqlite
// - webappsstore.sqlite
// The file create_db.js in the package was run locally (with a build that
// supports local storage archive upgrades and local storage archive version
// set to max integer), specifically it was temporarily added to xpcshell.ini
// and then executed:
// mach xpcshell-test --interactive dom/localstorage/test/unit/create_db.js
// Note: to make it become the profile in the test, additional manual steps
// are needed.
// 1. Remove the folder "storage/temporary".
installPackage("localStorageArchiveDowngrade_profile");
info("Checking ls dirs");
for (let lsDir of lsDirs) {
let dir = getRelativeFile(lsDir);
exists = dir.exists();
ok(exists, "ls directory does exist");
}
request = init();
request = await requestFinished(request);
info("Checking ls dirs");
for (let lsDir of lsDirs) {
let dir = getRelativeFile(lsDir);
exists = dir.exists();
ok(!exists, "ls directory doesn't exist");
}
}

Просмотреть файл

@ -13,6 +13,8 @@ support-files =
groupMismatch_profile.zip
idbSubdirUpgrade1_profile.zip
idbSubdirUpgrade2_profile.zip
localStorageArchive1upgrade_profile.zip
localStorageArchiveDowngrade_profile.zip
morgueCleanup_profile.zip
obsoleteOriginAttributes_profile.zip
originAttributesUpgrade_profile.zip
@ -34,6 +36,8 @@ support-files =
[test_idbSubdirUpgrade.js]
[test_initTemporaryStorage.js]
[test_listInitializedOrigins.js]
[test_localStorageArchive1upgrade.js]
[test_localStorageArchiveDowngrade.js]
[test_morgueCleanup.js]
[test_obsoleteOriginAttributesUpgrade.js]
[test_obsoleteOrigins.js]