Backed out changeset a266f691a68c (bug 1784966) for causing IDB Encryption related failures CLOSED TREE

This commit is contained in:
Norisz Fay 2022-10-24 23:06:55 +03:00
Родитель 07d2c243cb
Коммит 964b5b473b
10 изменённых файлов: 82 добавлений и 362 удалений

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

@ -32,7 +32,6 @@
#include "IndexedDBCommon.h"
#include "IndexedDatabaseInlines.h"
#include "IndexedDatabaseManager.h"
#include "IndexedDBCipherKeyManager.h"
#include "KeyPath.h"
#include "MainThreadUtils.h"
#include "ProfilerHelpers.h"
@ -2385,6 +2384,7 @@ class Database final
bool IsInPrivateBrowsing() const {
AssertIsOnBackgroundThread();
return mInPrivateBrowsing;
}
@ -3750,47 +3750,6 @@ class NormalTransactionOp : public TransactionDatabaseOperationBase,
const PreprocessResponse& aResponse) final;
};
Maybe<CipherKey> IndexedDBCipherKeyManager::Get(const nsCString& aDatabaseID,
const nsCString& keyStoreID) {
auto lockedPrivateBrowsingInfoHashTable =
mPrivateBrowsingInfoHashTable.Lock();
auto dbKeyStore = lockedPrivateBrowsingInfoHashTable->Lookup(aDatabaseID);
if (!dbKeyStore) {
return Nothing();
}
return dbKeyStore->MaybeGet(keyStoreID);
}
CipherKey IndexedDBCipherKeyManager::Ensure(const nsCString& aDatabaseID,
const nsCString& keyStoreID) {
auto lockedPrivateBrowsingInfoHashTable =
mPrivateBrowsingInfoHashTable.Lock();
auto& dbKeyStore =
lockedPrivateBrowsingInfoHashTable->LookupOrInsert(aDatabaseID);
return dbKeyStore.LookupOrInsertWith(keyStoreID, [] {
// XXX Generate key using proper random data, such that we can ensure
// the use of unique IVs per key by discriminating by database's file
// id & offset.
auto keyOrErr = IndexedDBCipherStrategy::GenerateKey();
// XXX Propagate the error to the caller rather than asserting.
return keyOrErr.unwrap();
});
}
bool IndexedDBCipherKeyManager::Remove(const nsCString& aDatabaseID) {
auto lockedPrivateBrowsingInfoHashTable =
mPrivateBrowsingInfoHashTable.Lock();
return lockedPrivateBrowsingInfoHashTable->Remove(aDatabaseID);
}
// XXX Maybe we can avoid a mutex here by moving all accesses to the background
// thread.
StaticAutoPtr<IndexedDBCipherKeyManager> gIndexedDBCipherKeyManager;
class ObjectStoreAddOrPutRequestOp final : public NormalTransactionOp {
friend class TransactionBase;
@ -3806,7 +3765,7 @@ class ObjectStoreAddOrPutRequestOp final : public NormalTransactionOp {
#ifdef DEBUG
const StructuredCloneFileBase::FileType mType;
#endif
void EnsureCipherKey();
void AssertInvariants() const;
explicit StoredFileInfo(SafeRefPtr<DatabaseFileInfo> aFileInfo);
@ -3940,18 +3899,6 @@ void ObjectStoreAddOrPutRequestOp::StoredFileInfo::AssertInvariants() const {
}
}
void ObjectStoreAddOrPutRequestOp::StoredFileInfo::EnsureCipherKey() {
const auto& fileInfo = GetFileInfo();
const auto& fileMgr = fileInfo.Manager();
// no need to generate cipher keys if we are not in PBM
if (!fileMgr.IsInPrivateBrowsingMode()) return;
nsCString keyId;
keyId.AppendInt(fileInfo.Id());
gIndexedDBCipherKeyManager->Ensure(fileMgr.DatabaseID(), keyId);
}
ObjectStoreAddOrPutRequestOp::StoredFileInfo::StoredFileInfo(
SafeRefPtr<DatabaseFileInfo> aFileInfo)
: mFileInfo{WrapNotNull(std::move(aFileInfo))},
@ -3964,7 +3911,6 @@ ObjectStoreAddOrPutRequestOp::StoredFileInfo::StoredFileInfo(
AssertIsOnBackgroundThread();
AssertInvariants();
EnsureCipherKey();
MOZ_COUNT_CTOR(ObjectStoreAddOrPutRequestOp::StoredFileInfo);
}
@ -3980,7 +3926,6 @@ ObjectStoreAddOrPutRequestOp::StoredFileInfo::StoredFileInfo(
AssertIsOnBackgroundThread();
AssertInvariants();
EnsureCipherKey();
MOZ_COUNT_CTOR(ObjectStoreAddOrPutRequestOp::StoredFileInfo);
}
@ -3997,7 +3942,6 @@ ObjectStoreAddOrPutRequestOp::StoredFileInfo::StoredFileInfo(
AssertIsOnBackgroundThread();
AssertInvariants();
EnsureCipherKey();
MOZ_COUNT_CTOR(ObjectStoreAddOrPutRequestOp::StoredFileInfo);
}
@ -5611,26 +5555,19 @@ class EncryptedFileBlobImpl final : public FileBlobImpl {
}
private:
const CipherKey mKey;
const CipherKey& mKey;
};
RefPtr<BlobImpl> CreateFileBlobImpl(const Database& aDatabase,
const nsCOMPtr<nsIFile>& aNativeFile,
const DatabaseFileInfo::IdType aId) {
if (aDatabase.IsInPrivateBrowsing()) {
nsCString cipherKeyId;
cipherKeyId.AppendInt(aId);
const auto& key =
gIndexedDBCipherKeyManager->Get(aDatabase.Id(), cipherKeyId);
MOZ_RELEASE_ASSERT(key.isSome());
return MakeRefPtr<EncryptedFileBlobImpl>(aNativeFile, aId, *key);
const auto& maybeKey = aDatabase.MaybeKeyRef();
if (maybeKey) {
return MakeRefPtr<EncryptedFileBlobImpl>(aNativeFile, aId, *maybeKey);
}
auto impl = MakeRefPtr<FileBlobImpl>(aNativeFile);
impl->SetFileId(aId);
return impl;
}
@ -6075,6 +6012,12 @@ using DatabaseActorHashtable =
StaticAutoPtr<DatabaseActorHashtable> gLiveDatabaseHashtable;
using PrivateBrowsingInfoHashtable = nsTHashMap<nsCStringHashKey, CipherKey>;
// XXX Maybe we can avoid a mutex here by moving all accesses to the background
// thread.
StaticAutoPtr<DataMutex<PrivateBrowsingInfoHashtable>>
gPrivateBrowsingInfoHashtable;
StaticRefPtr<ConnectionPool> gConnectionPool;
StaticRefPtr<FileHandleThreadPool> gFileHandleThreadPool;
@ -6108,8 +6051,9 @@ void IncreaseBusyCount() {
MOZ_ASSERT(!gLiveDatabaseHashtable);
gLiveDatabaseHashtable = new DatabaseActorHashtable();
MOZ_ASSERT(!gIndexedDBCipherKeyManager);
gIndexedDBCipherKeyManager = new IndexedDBCipherKeyManager();
MOZ_ASSERT(!gPrivateBrowsingInfoHashtable);
gPrivateBrowsingInfoHashtable = new DataMutex<PrivateBrowsingInfoHashtable>(
"gPrivateBrowsingInfoHashtable");
MOZ_ASSERT(!gLoggingInfoHashtable);
gLoggingInfoHashtable = new DatabaseLoggingInfoHashtable();
@ -6157,10 +6101,11 @@ void DecreaseBusyCount() {
MOZ_ASSERT(!gLiveDatabaseHashtable->Count());
gLiveDatabaseHashtable = nullptr;
MOZ_ASSERT(gIndexedDBCipherKeyManager);
MOZ_ASSERT(gPrivateBrowsingInfoHashtable);
// XXX After we add the private browsing session end listener, we can assert
// this.
gIndexedDBCipherKeyManager = nullptr;
// MOZ_ASSERT(!gPrivateBrowsingInfoHashtable->Count());
gPrivateBrowsingInfoHashtable = nullptr;
MOZ_ASSERT(gFactoryOps);
MOZ_ASSERT(gFactoryOps->IsEmpty());
@ -12119,14 +12064,11 @@ DatabaseFileManager::MutexType DatabaseFileManager::sMutex;
DatabaseFileManager::DatabaseFileManager(
PersistenceType aPersistenceType,
const quota::OriginMetadata& aOriginMetadata,
const nsAString& aDatabaseName, const nsCString& aDatabaseID,
bool aEnforcingQuota, bool aIsInPrivateBrowsingMode)
const nsAString& aDatabaseName, bool aEnforcingQuota)
: mPersistenceType(aPersistenceType),
mOriginMetadata(aOriginMetadata),
mDatabaseName(aDatabaseName),
mDatabaseID(aDatabaseID),
mEnforcingQuota(aEnforcingQuota),
mIsInPrivateBrowsingMode(aIsInPrivateBrowsingMode) {}
mEnforcingQuota(aEnforcingQuota) {}
nsresult DatabaseFileManager::Init(nsIFile* aDirectory,
mozIStorageConnection& aConnection) {
@ -15277,7 +15219,22 @@ nsresult FactoryOp::Open() {
MOZ_ASSERT(permission == PermissionValue::kPermissionAllowed);
if (mInPrivateBrowsing) {
gIndexedDBCipherKeyManager->Ensure(mDatabaseId);
const auto lockedPrivateBrowsingInfoHashtable =
gPrivateBrowsingInfoHashtable->Lock();
lockedPrivateBrowsingInfoHashtable->LookupOrInsertWith(mDatabaseId, [] {
IndexedDBCipherStrategy cipherStrategy;
// XXX Generate key using proper random data, such that we can ensure
// the use of unique IVs per key by discriminating by database's file
// id & offset.
auto keyOrErr = cipherStrategy.GenerateKey();
// XXX Propagate the error to the caller rather than asserting.
MOZ_RELEASE_ASSERT(keyOrErr.isOk());
return keyOrErr.unwrap();
});
}
mState = State::FinishOpen;
@ -15885,11 +15842,19 @@ nsresult OpenDatabaseOp::DoDatabaseWork() {
CloneFileAndAppend(*dbDirectory, databaseFilenameBase +
kFileManagerDirectoryNameSuffix));
Maybe<const CipherKey> maybeKey =
mInPrivateBrowsing ? gIndexedDBCipherKeyManager->Get(mDatabaseId)
: Nothing();
Maybe<const CipherKey> maybeKey;
if (mInPrivateBrowsing) {
CipherKey key;
MOZ_RELEASE_ASSERT(mInPrivateBrowsing == maybeKey.isSome());
{
const auto lockedPrivateBrowsingInfoHashtable =
gPrivateBrowsingInfoHashtable->Lock();
MOZ_ALWAYS_TRUE(
lockedPrivateBrowsingInfoHashtable->Get(mDatabaseId, &key));
}
maybeKey.emplace(std::move(key));
}
QM_TRY_UNWRAP(
NotNull<nsCOMPtr<mozIStorageConnection>> connection,
@ -15932,8 +15897,7 @@ nsresult OpenDatabaseOp::DoDatabaseWork() {
if (!fileManager) {
fileManager = MakeSafeRefPtr<DatabaseFileManager>(
persistenceType, mOriginMetadata, databaseName, mDatabaseId,
mEnforcingQuota, mInPrivateBrowsing);
persistenceType, mOriginMetadata, databaseName, mEnforcingQuota);
QM_TRY(MOZ_TO_RESULT(fileManager->Init(fmDirectory, *connection)));
@ -16593,11 +16557,19 @@ void OpenDatabaseOp::EnsureDatabaseActor() {
mMetadata = info->mMetadata.clonePtr();
}
Maybe<const CipherKey> maybeKey =
mInPrivateBrowsing ? gIndexedDBCipherKeyManager->Get(mDatabaseId)
: Nothing();
Maybe<const CipherKey> maybeKey;
if (mInPrivateBrowsing) {
CipherKey key;
MOZ_RELEASE_ASSERT(mInPrivateBrowsing == maybeKey.isSome());
{
const auto lockedPrivateBrowsingInfoHashtable =
gPrivateBrowsingInfoHashtable->Lock();
MOZ_ALWAYS_TRUE(
lockedPrivateBrowsingInfoHashtable->Get(mDatabaseId, &key));
}
maybeKey.emplace(std::move(key));
}
// XXX Shouldn't Manager() return already_AddRefed when
// PBackgroundIDBFactoryParent is declared refcounted?
@ -16900,11 +16872,16 @@ void DeleteDatabaseOp::LoadPreviousVersion(nsIFile& aDatabaseFile) {
return;
}
const auto maybeKey = mInPrivateBrowsing
? gIndexedDBCipherKeyManager->Get(mDatabaseId)
: Nothing();
const auto maybeKey = [this]() -> Maybe<const CipherKey> {
CipherKey key;
MOZ_RELEASE_ASSERT(mInPrivateBrowsing == maybeKey.isSome());
const auto lockedPrivateBrowsingInfoHashtable =
gPrivateBrowsingInfoHashtable->Lock();
if (!lockedPrivateBrowsingInfoHashtable->Get(mDatabaseId, &key)) {
return Nothing{};
}
return Some(std::move(key));
}();
// Pass -1 as the directoryLockId to disable quota checking, since we might
// temporarily exceed quota before deleting the database.
@ -17175,11 +17152,6 @@ nsresult DeleteDatabaseOp::VersionChangeOp::RunOnIOThread() {
return rv;
}
if (mDeleteDatabaseOp->mInPrivateBrowsing) {
MOZ_ASSERT(
gIndexedDBCipherKeyManager->Remove(mDeleteDatabaseOp->mDatabaseId));
}
rv = mOwningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@ -19555,22 +19527,11 @@ nsresult ObjectStoreAddOrPutRequestOp::DoDatabaseWork(
QM_TRY(OkIf(journalFile), NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR,
IDB_REPORT_INTERNAL_ERR_LAMBDA);
nsCString fileKeyId;
fileKeyId.AppendInt(fileInfo.Id());
const auto maybeKey =
Transaction()
.GetDatabase()
.GetFileManager()
.IsInPrivateBrowsingMode()
? gIndexedDBCipherKeyManager->Get(
Transaction().GetDatabase().Id(), fileKeyId)
: Nothing();
QM_TRY(
MOZ_TO_RESULT(fileHelper->CreateFileFromStream(
*file, *journalFile, *inputStream,
storedFileInfo.ShouldCompress(), maybeKey))
storedFileInfo.ShouldCompress(),
Transaction().GetDatabase().MaybeKeyRef()))
.mapErr([](const nsresult rv) {
if (NS_ERROR_GET_MODULE(rv) !=
NS_ERROR_MODULE_DOM_INDEXEDDB) {

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

@ -20,7 +20,6 @@
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/dom/indexedDB/Key.h"
#include "mozilla/dom/quota/IPCStreamCipherStrategy.h"
#include "IndexedDBCipherKeyManager.h"
#include "nscore.h"
#include "nsISupports.h"
#include "nsStringFwd.h"
@ -40,6 +39,9 @@ struct StructuredCloneReadInfoParent;
extern const nsLiteralString kJournalDirectoryName;
using IndexedDBCipherStrategy = quota::IPCStreamCipherStrategy;
using CipherKey = IndexedDBCipherStrategy::KeyType;
// At the moment, the encrypted stream block size is assumed to be unchangeable
// between encrypting and decrypting blobs. This assumptions holds as long as we
// only encrypt in private browsing mode, but when we support encryption for

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

@ -28,13 +28,11 @@ class DatabaseFileManager final
const PersistenceType mPersistenceType;
const quota::OriginMetadata mOriginMetadata;
const nsString mDatabaseName;
const nsCString mDatabaseID;
LazyInitializedOnce<const nsString> mDirectoryPath;
LazyInitializedOnce<const nsString> mJournalDirectoryPath;
const bool mEnforcingQuota;
const bool mIsInPrivateBrowsingMode;
// Lock protecting DatabaseFileManager.mFileInfos.
// It's s also used to atomically update DatabaseFileInfo.mRefCnt and
@ -61,9 +59,7 @@ class DatabaseFileManager final
DatabaseFileManager(PersistenceType aPersistenceType,
const quota::OriginMetadata& aOriginMetadata,
const nsAString& aDatabaseName,
const nsCString& aDatabaseID, bool aEnforcingQuota,
bool aIsInPrivateBrowsingMode);
const nsAString& aDatabaseName, bool aEnforcingQuota);
PersistenceType Type() const { return mPersistenceType; }
@ -74,8 +70,7 @@ class DatabaseFileManager final
const nsACString& Origin() const { return mOriginMetadata.mOrigin; }
const nsAString& DatabaseName() const { return mDatabaseName; }
const nsCString& DatabaseID() const { return mDatabaseID; }
auto IsInPrivateBrowsingMode() const { return mIsInPrivateBrowsingMode; }
bool EnforcingQuota() const { return mEnforcingQuota; }
nsresult Init(nsIFile* aDirectory, mozIStorageConnection& aConnection);

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

@ -1,52 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_indexeddbcipherKeyManager_h
#define mozilla_dom_indexeddbcipherKeyManager_h
#include "mozilla/dom/quota/IPCStreamCipherStrategy.h"
#include "mozilla/DataMutex.h"
#include "nsTHashMap.h"
namespace mozilla::dom::indexedDB {
namespace {
using IndexedDBCipherStrategy = quota::IPCStreamCipherStrategy;
using CipherKey = IndexedDBCipherStrategy::KeyType;
class IndexedDBCipherKeyManager {
// This helper class is used by IndexedDB operations to store/retrieve cipher
// keys in private browsing mode. All data in IndexedDB must be encrypted
// using a cipher key and unique IV (Initialization Vector). While there's a
// separate cipher key for every blob file; any normal key/value pairs get
// encrypted using the commmon database key. All keys pertaining to a single
// database get stored together using the database id in a hashmap. We are
// using a 2-level hashmap here; keys get stored effectively at level 2.
// Looking up at level 1 using database id gives us access to hashmap of keys
// corresponding to that database which we could use to look up the common
// database key and blob keys using "default" and blob file ids respectively.
public:
using PrivateBrowsingInfoHashtable =
nsTHashMap<nsCStringHashKey, nsTHashMap<nsCStringHashKey, CipherKey>>;
IndexedDBCipherKeyManager()
: mPrivateBrowsingInfoHashTable("IndexedDBCipherKeyManager"){};
Maybe<CipherKey> Get(const nsCString& aDatabaseID,
const nsCString& keyStoreID = "default"_ns);
CipherKey Ensure(const nsCString& aDatabaseID,
const nsCString& keyStoreID = "default"_ns);
bool Remove(const nsCString& aDatabaseID);
private:
DataMutex<PrivateBrowsingInfoHashtable> mPrivateBrowsingInfoHashTable;
};
} // namespace
} // namespace mozilla::dom::indexedDB
#endif // IndexedDBCipherKeyManager_h

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

@ -2862,8 +2862,7 @@ nsresult UpgradeFileIdsFunction::Init(nsIFile* aFMDirectory,
// purpose is to store file ids without adding more complexity or code
// duplication.
auto fileManager = MakeSafeRefPtr<DatabaseFileManager>(
PERSISTENCE_TYPE_INVALID, quota::OriginMetadata{}, u""_ns, ""_ns, false,
false);
PERSISTENCE_TYPE_INVALID, quota::OriginMetadata{}, u""_ns, false);
nsresult rv = fileManager->Init(aFMDirectory, aConnection);
if (NS_WARN_IF(NS_FAILED(rv))) {

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

@ -1,3 +0,0 @@
[DEFAULT]
[test_IDB_encryption_PBM.py]

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

@ -1,139 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os
import re
from marionette_driver import Wait
from marionette_harness import MarionetteTestCase
INDEXED_DB_PBM_PREF = "dom.indexedDB.privateBrowsing.enabled"
class IDBEncryptionPBM(MarionetteTestCase):
"""
Bug1784966: Ensure IDB data gets encrypted in Private Browsing Mode.
We need to ensure data inside both sqlite fields and blob files under
*.sqllite gets encrypted.
"""
def setUp(self):
super(IDBEncryptionPBM, self).setUp()
self.IDBName = "IDBTest"
self.IDBStoreName = "IDBTestStore"
self.IDBVersion = 1
self.IDBValue = "test_IDB_Encryption_PBM"
self.profilePath = self.marionette.instance.profile.profile
self.defaultPrefValue = self.marionette.get_pref(INDEXED_DB_PBM_PREF)
self.marionette.set_pref(INDEXED_DB_PBM_PREF, True)
# Navigate by opening a new private window
pbmWindowHandle = self.marionette.open(type="window", private=True)["handle"]
self.marionette.switch_to_window(pbmWindowHandle)
self.marionette.navigate(
self.marionette.absolute_url("dom/indexedDB/basicIDB_PBM.html")
)
self.idbStoragePath = self.getIDBStoragePath()
def tearDown(self):
super(IDBEncryptionPBM, self).setUp()
self.marionette.set_pref(INDEXED_DB_PBM_PREF, self.defaultPrefValue)
# closes the new private window we opened in the setUp and referred by 'pbmWindowHandle'
self.marionette.close()
def test_ensure_encrypted_blob(self):
self.marionette.execute_script(
"""
const [idb, store, key, value] = arguments;
const blobValue = new Blob([value], {type:'text/plain'});
window.wrappedJSObject.addDataIntoIDB(idb, store, key, blobValue);
""",
script_args=(self.IDBName, self.IDBStoreName, "blobKey", self.IDBValue),
)
Wait(self.marionette, timeout=60).until(
lambda _: self.sqliteWALReleased(),
message="WAL still around even after 60s",
)
idbBlobDir = self.findDirObj(self.idbStoragePath, ".files", False)
if idbBlobDir is None:
raise Exception(f"unable to find '.files' dir in {self.idbStoragePath}")
# seems like there's a timing issue here. There are sometimes no blob file
# even after WAL is released. Allowing some buffer time and ensuring blob file
# exists before validating it's contents
idbBlobPath = os.path.join(idbBlobDir, "1")
Wait(self.marionette, timeout=10).until(
lambda _: os.path.exists(idbBlobPath),
message="Blob file does not exist even after waiting 10s",
)
foundRawValue = False
with open(idbBlobPath, "rb") as f_binary:
foundRawValue = (
re.search(self.IDBValue.encode("ascii"), f_binary.read()) is not None
)
self.assertFalse(foundRawValue, "Blob file did not get encrypted")
def test_ensure_encrpted_sqlite_data(self):
self.marionette.execute_script(
"""
const [idb, store, key, value] = arguments;
window.wrappedJSObject.addDataIntoIDB(idb, store, key, value);
""",
script_args=(self.IDBName, self.IDBStoreName, "textKey", self.IDBValue),
)
Wait(self.marionette, timeout=60).until(
lambda _: self.sqliteWALReleased(),
message="WAL still around even after 60s",
)
sqliteDBFile = self.findDirObj(self.idbStoragePath, ".sqlite", True)
self.assertIsNotNone(
sqliteDBFile, f"unable to find .sqlite file in {self.idbStoragePath}"
)
foundRawValue = False
with open(sqliteDBFile, "rb") as f_binary:
foundRawValue = (
re.search(self.IDBValue.encode("ascii"), f_binary.read()) is not None
)
self.assertFalse(foundRawValue, "sqlite data did not get encrypted")
def getIDBStoragePath(self):
origin = (
self.marionette.absolute_url("")[:-1].replace(":", "+").replace("/", "+")
)
# origin directory under storage is suffice'd with '^privateBrowsingId=1' for PBM
originDir = origin + "^privateBrowsingId=1"
return os.path.join(self.profilePath, "storage", "default", originDir, "idb")
def findDirObj(self, path, pattern, isFile):
for obj in os.scandir(path):
if obj.path.endswith(pattern) and (obj.is_file() == isFile):
return obj.path
return None
def sqliteWALReleased(self):
"""
checks if .sqlite-wal has been cleared or not.
returns False if idbStoragePath does not exist
"""
if not os.path.exists(self.idbStoragePath):
return False
return self.findDirObj(self.idbStoragePath, ".sqlite-wal", True) is None

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

@ -797,15 +797,13 @@ nsresult Connection::initialize(nsIFileURL* aFileURL,
nsAutoCString query;
rv = aFileURL->GetQuery(query);
NS_ENSURE_SUCCESS(rv, rv);
const char* const vfs =
!URLParams::Parse(query,
[](const nsAString& aName, const nsAString& aValue) {
return !aName.EqualsLiteral("key");
})
URLParams::Parse(query,
[](const nsAString& aName, const nsAString& aValue) {
return aName.EqualsLiteral("key");
})
? GetObfuscatingVFSName()
: GetTelemetryVFSName(exclusive);
int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, vfs);
if (srv != SQLITE_OK) {
mDBConn = nullptr;

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

@ -3,7 +3,6 @@
# DOM tests
[include:../../../../../dom/cache/test/marionette/manifest.ini]
[include:../../../../../dom/indexedDB/test/marionette/manifest.ini]
[include:../../../../../dom/workers/test/marionette/manifest.ini]
# browser tests

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

@ -1,40 +0,0 @@
<html>
<head>
<script>
async function ensureIDB(name, ver, store) {
return new Promise((resolve, reject) => {
let createObjectStore = (db, store) => {
db.createObjectStore(store);
};
var req = indexedDB.open(name, ver);
req.onerror = reject;
req.onsuccess = (event) => {
resolve(req.result);
};
req.onupgradeneeded = function (event) {
let db = event.target.result;
createObjectStore(db, store);
};
});
};
async function addDataIntoIDB(idb, store, key, value) {
let db = await ensureIDB(idb, 1, store);
await (new Promise((resolve, reject) => {
var transaction = db.transaction([store], "readwrite");
var put = transaction.objectStore(store).put(value, key);
put.onsuccess = resolve();
}));
closeIDB(db)
};
function closeIDB(db) {
db.close();
}
</script>
</head>
</html>