forked from mirrors/gecko-dev
Bug 1669437 - Add necessary infrastructure for independent in-memory only local storage database; r=asuth,dom-workers-and-storage-reviewers
The new infrastructure consists of a separate bridge between the content and the parent process and a separate local storage database in the parent process. The new infrastructure can be used for storing and sharing of private browsing data across content processes. This patch only creates necessary infrastructure, actual enabling of storing and sharing of data across content processes will be done in a follow-up patch. Differential Revision: https://phabricator.services.mozilla.com/D96562
This commit is contained in:
parent
adf086b335
commit
03e0a91794
16 changed files with 315 additions and 178 deletions
|
|
@ -129,6 +129,7 @@ void LocalStorageCache::Init(LocalStorageManager* aManager, bool aPersistent,
|
|||
|
||||
mInitialized = true;
|
||||
aPrincipal->OriginAttributesRef().CreateSuffix(mOriginSuffix);
|
||||
mPrivateBrowsingId = aPrincipal->GetPrivateBrowsingId();
|
||||
mPersistent = aPersistent;
|
||||
if (aQuotaOriginScope.IsEmpty()) {
|
||||
mQuotaOriginScope = Origin();
|
||||
|
|
@ -147,7 +148,7 @@ void LocalStorageCache::Init(LocalStorageManager* aManager, bool aPersistent,
|
|||
MOZ_ASSERT(mOriginSuffix.IsEmpty() !=
|
||||
StringBeginsWith(mQuotaOriginScope, "^"_ns));
|
||||
|
||||
mUsage = aManager->GetOriginUsage(mQuotaOriginScope);
|
||||
mUsage = aManager->GetOriginUsage(mQuotaOriginScope, mPrivateBrowsingId);
|
||||
}
|
||||
|
||||
void LocalStorageCache::NotifyObservers(const LocalStorage* aStorage,
|
||||
|
|
@ -214,7 +215,8 @@ void LocalStorageCache::Preload() {
|
|||
return;
|
||||
}
|
||||
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
StorageDBChild* storageChild =
|
||||
StorageDBChild::GetOrCreate(mPrivateBrowsingId);
|
||||
if (!storageChild) {
|
||||
mLoaded = true;
|
||||
mLoadResult = NS_ERROR_FAILURE;
|
||||
|
|
@ -254,7 +256,7 @@ void LocalStorageCache::WaitForPreload(Telemetry::HistogramID aTelemetryID) {
|
|||
// No need to check sDatabase for being non-null since preload is either
|
||||
// done before we've shut the DB down or when the DB could not start,
|
||||
// preload has not even be started.
|
||||
StorageDBChild::Get()->SyncPreload(this);
|
||||
StorageDBChild::Get(mPrivateBrowsingId)->SyncPreload(this);
|
||||
}
|
||||
|
||||
nsresult LocalStorageCache::GetLength(const LocalStorage* aStorage,
|
||||
|
|
@ -374,7 +376,7 @@ nsresult LocalStorageCache::SetItem(const LocalStorage* aStorage,
|
|||
#endif
|
||||
|
||||
if (Persist(aStorage)) {
|
||||
StorageDBChild* storageChild = StorageDBChild::Get();
|
||||
StorageDBChild* storageChild = StorageDBChild::Get(mPrivateBrowsingId);
|
||||
if (!storageChild) {
|
||||
NS_ERROR(
|
||||
"Writing to localStorage after the database has been shut down"
|
||||
|
|
@ -423,7 +425,7 @@ nsresult LocalStorageCache::RemoveItem(const LocalStorage* aStorage,
|
|||
#endif
|
||||
|
||||
if (Persist(aStorage)) {
|
||||
StorageDBChild* storageChild = StorageDBChild::Get();
|
||||
StorageDBChild* storageChild = StorageDBChild::Get(mPrivateBrowsingId);
|
||||
if (!storageChild) {
|
||||
NS_ERROR(
|
||||
"Writing to localStorage after the database has been shut down"
|
||||
|
|
@ -474,7 +476,7 @@ nsresult LocalStorageCache::Clear(const LocalStorage* aStorage,
|
|||
#endif
|
||||
|
||||
if (Persist(aStorage) && (refresh || hadData)) {
|
||||
StorageDBChild* storageChild = StorageDBChild::Get();
|
||||
StorageDBChild* storageChild = StorageDBChild::Get(mPrivateBrowsingId);
|
||||
if (!storageChild) {
|
||||
NS_ERROR(
|
||||
"Writing to localStorage after the database has been shut down"
|
||||
|
|
|
|||
|
|
@ -256,6 +256,9 @@ class LocalStorageCache : public LocalStorageCacheBridge {
|
|||
// Result of load from the database. Valid after mLoaded flag has been set.
|
||||
nsresult mLoadResult;
|
||||
|
||||
// Expected to be only 0 or 1.
|
||||
uint32_t mPrivateBrowsingId;
|
||||
|
||||
// Init() method has been called
|
||||
bool mInitialized : 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ LocalStorageManager::LocalStorageManager() : mCaches(8) {
|
|||
// Do this only on the child process. The thread IPC bridge
|
||||
// is also used to communicate chrome observer notifications.
|
||||
// Note: must be called after we set sSelf
|
||||
StorageDBChild::GetOrCreate();
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
StorageDBChild::GetOrCreate(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +102,7 @@ LocalStorageCache* LocalStorageManager::GetCache(
|
|||
}
|
||||
|
||||
already_AddRefed<StorageUsage> LocalStorageManager::GetOriginUsage(
|
||||
const nsACString& aOriginNoSuffix) {
|
||||
const nsACString& aOriginNoSuffix, const uint32_t aPrivateBrowsingId) {
|
||||
RefPtr<StorageUsage> usage;
|
||||
if (mUsages.Get(aOriginNoSuffix, &usage)) {
|
||||
return usage.forget();
|
||||
|
|
@ -108,7 +110,8 @@ already_AddRefed<StorageUsage> LocalStorageManager::GetOriginUsage(
|
|||
|
||||
usage = new StorageUsage(aOriginNoSuffix);
|
||||
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
StorageDBChild* storageChild =
|
||||
StorageDBChild::GetOrCreate(aPrivateBrowsingId);
|
||||
if (storageChild) {
|
||||
storageChild->AsyncGetUsage(usage);
|
||||
}
|
||||
|
|
@ -167,9 +170,12 @@ nsresult LocalStorageManager::GetStorageInternal(
|
|||
}
|
||||
|
||||
if (aCreateMode == CreateMode::CreateIfShouldPreload) {
|
||||
const uint32_t privateBrowsingId =
|
||||
aStoragePrincipal->GetPrivateBrowsingId();
|
||||
|
||||
// This is a demand to just preload the cache, if the scope has
|
||||
// no data stored, bypass creation and preload of the cache.
|
||||
StorageDBChild* db = StorageDBChild::Get();
|
||||
StorageDBChild* db = StorageDBChild::Get(privateBrowsingId);
|
||||
if (db) {
|
||||
if (!db->ShouldPreloadOrigin(LocalStorageManager::CreateOrigin(
|
||||
originAttrSuffix, originKey))) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class LocalStorageManager final : public nsIDOMStorageManager,
|
|||
|
||||
// Returns object keeping usage cache for the scope.
|
||||
already_AddRefed<StorageUsage> GetOriginUsage(
|
||||
const nsACString& aOriginNoSuffix);
|
||||
const nsACString& aOriginNoSuffix, uint32_t aPrivateBrowsingId);
|
||||
|
||||
static nsAutoCString CreateOrigin(const nsACString& aOriginSuffix,
|
||||
const nsACString& aOriginNoSuffix);
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ using namespace StorageUtils;
|
|||
|
||||
namespace { // anon
|
||||
|
||||
StorageDBThread* sStorageThread = nullptr;
|
||||
StorageDBThread* sStorageThread[2] = {nullptr, nullptr};
|
||||
|
||||
// False until we shut the storage thread down.
|
||||
bool sStorageThreadDown = false;
|
||||
bool sStorageThreadDown[2] = {false, false};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
@ -97,11 +97,14 @@ class StorageDBThread::InitHelper final : public Runnable {
|
|||
};
|
||||
|
||||
class StorageDBThread::NoteBackgroundThreadRunnable final : public Runnable {
|
||||
// Expected to be only 0 or 1.
|
||||
const uint32_t mPrivateBrowsingId;
|
||||
nsCOMPtr<nsIEventTarget> mOwningThread;
|
||||
|
||||
public:
|
||||
NoteBackgroundThreadRunnable()
|
||||
explicit NoteBackgroundThreadRunnable(const uint32_t aPrivateBrowsingId)
|
||||
: Runnable("dom::StorageDBThread::NoteBackgroundThreadRunnable"),
|
||||
mPrivateBrowsingId(aPrivateBrowsingId),
|
||||
mOwningThread(GetCurrentEventTarget()) {}
|
||||
|
||||
private:
|
||||
|
|
@ -110,7 +113,7 @@ class StorageDBThread::NoteBackgroundThreadRunnable final : public Runnable {
|
|||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
StorageDBThread::StorageDBThread()
|
||||
StorageDBThread::StorageDBThread(const uint32_t aPrivateBrowsingId)
|
||||
: mThread(nullptr),
|
||||
mThreadObserver(new ThreadObserver()),
|
||||
mStopIOThread(false),
|
||||
|
|
@ -120,36 +123,43 @@ StorageDBThread::StorageDBThread()
|
|||
mWorkerStatements(mWorkerConnection),
|
||||
mReaderStatements(mReaderConnection),
|
||||
mFlushImmediately(false),
|
||||
mPriorityCounter(0) {}
|
||||
|
||||
// static
|
||||
StorageDBThread* StorageDBThread::Get() {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
return sStorageThread;
|
||||
mPrivateBrowsingId(aPrivateBrowsingId),
|
||||
mPriorityCounter(0) {
|
||||
MOZ_ASSERT(aPrivateBrowsingId <= 1);
|
||||
}
|
||||
|
||||
// static
|
||||
StorageDBThread* StorageDBThread::GetOrCreate(const nsString& aProfilePath) {
|
||||
StorageDBThread* StorageDBThread::Get(const uint32_t aPrivateBrowsingId) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aPrivateBrowsingId <= 1);
|
||||
|
||||
if (sStorageThread || sStorageThreadDown) {
|
||||
return sStorageThread[aPrivateBrowsingId];
|
||||
}
|
||||
|
||||
// static
|
||||
StorageDBThread* StorageDBThread::GetOrCreate(
|
||||
const nsString& aProfilePath, const uint32_t aPrivateBrowsingId) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aPrivateBrowsingId <= 1);
|
||||
|
||||
StorageDBThread*& storageThread = sStorageThread[aPrivateBrowsingId];
|
||||
if (storageThread || sStorageThreadDown[aPrivateBrowsingId]) {
|
||||
// When sStorageThreadDown is at true, sStorageThread is null.
|
||||
// Checking sStorageThreadDown flag here prevents reinitialization of
|
||||
// the storage thread after shutdown.
|
||||
return sStorageThread;
|
||||
return storageThread;
|
||||
}
|
||||
|
||||
auto storageThread = MakeUnique<StorageDBThread>();
|
||||
auto newStorageThread = MakeUnique<StorageDBThread>(aPrivateBrowsingId);
|
||||
|
||||
nsresult rv = storageThread->Init(aProfilePath);
|
||||
nsresult rv = newStorageThread->Init(aProfilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sStorageThread = storageThread.release();
|
||||
storageThread = newStorageThread.release();
|
||||
|
||||
return sStorageThread;
|
||||
return storageThread;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -185,33 +195,35 @@ nsresult StorageDBThread::GetProfilePath(nsString& aProfilePath) {
|
|||
nsresult StorageDBThread::Init(const nsString& aProfilePath) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
nsresult rv;
|
||||
if (mPrivateBrowsingId == 0) {
|
||||
nsresult rv;
|
||||
|
||||
nsString profilePath;
|
||||
if (aProfilePath.IsEmpty()) {
|
||||
RefPtr<InitHelper> helper = new InitHelper();
|
||||
nsString profilePath;
|
||||
if (aProfilePath.IsEmpty()) {
|
||||
RefPtr<InitHelper> helper = new InitHelper();
|
||||
|
||||
rv = helper->SyncDispatchAndReturnProfilePath(profilePath);
|
||||
rv = helper->SyncDispatchAndReturnProfilePath(profilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
profilePath = aProfilePath;
|
||||
}
|
||||
|
||||
mDatabaseFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
profilePath = aProfilePath;
|
||||
}
|
||||
|
||||
mDatabaseFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = mDatabaseFile->InitWithPath(profilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mDatabaseFile->InitWithPath(profilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
rv = mDatabaseFile->Append(u"webappsstore.sqlite"_ns);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = mDatabaseFile->Append(u"webappsstore.sqlite"_ns);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Need to keep the lock to avoid setting mThread later then
|
||||
// the thread body executes.
|
||||
MonitorAutoLock monitor(mThreadObserver->GetMonitor());
|
||||
|
|
@ -224,7 +236,7 @@ nsresult StorageDBThread::Init(const nsString& aProfilePath) {
|
|||
}
|
||||
|
||||
RefPtr<NoteBackgroundThreadRunnable> runnable =
|
||||
new NoteBackgroundThreadRunnable();
|
||||
new NoteBackgroundThreadRunnable(mPrivateBrowsingId);
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
|
||||
|
||||
return NS_OK;
|
||||
|
|
@ -233,8 +245,6 @@ nsresult StorageDBThread::Init(const nsString& aProfilePath) {
|
|||
nsresult StorageDBThread::Shutdown() {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
sStorageThreadDown = true;
|
||||
|
||||
if (!mThread) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
|
@ -522,14 +532,24 @@ nsresult StorageDBThread::OpenDatabaseConnection() {
|
|||
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = service->OpenUnsharedDatabase(mDatabaseFile,
|
||||
getter_AddRefs(mWorkerConnection));
|
||||
if (rv == NS_ERROR_FILE_CORRUPTED) {
|
||||
// delete the db and try opening again
|
||||
rv = mDatabaseFile->Remove(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mPrivateBrowsingId == 0) {
|
||||
MOZ_ASSERT(mDatabaseFile);
|
||||
|
||||
rv = service->OpenUnsharedDatabase(mDatabaseFile,
|
||||
getter_AddRefs(mWorkerConnection));
|
||||
if (rv == NS_ERROR_FILE_CORRUPTED) {
|
||||
// delete the db and try opening again
|
||||
rv = mDatabaseFile->Remove(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = service->OpenUnsharedDatabase(mDatabaseFile,
|
||||
getter_AddRefs(mWorkerConnection));
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mPrivateBrowsingId == 1);
|
||||
|
||||
rv = service->OpenSpecialDatabase(kMozStorageMemoryStorageKey,
|
||||
"lsprivatedb"_ns,
|
||||
getter_AddRefs(mWorkerConnection));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
@ -562,16 +582,18 @@ nsresult StorageDBThread::InitDatabase() {
|
|||
|
||||
rv = StorageDBUpdater::Update(mWorkerConnection);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Update has failed, rather throw the database away and try
|
||||
// opening and setting it up again.
|
||||
rv = mWorkerConnection->Close();
|
||||
mWorkerConnection = nullptr;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mPrivateBrowsingId == 0) {
|
||||
// Update has failed, rather throw the database away and try
|
||||
// opening and setting it up again.
|
||||
rv = mWorkerConnection->Close();
|
||||
mWorkerConnection = nullptr;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDatabaseFile->Remove(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mDatabaseFile->Remove(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = OpenAndUpdateDatabase();
|
||||
rv = OpenAndUpdateDatabase();
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
|
@ -1529,7 +1551,7 @@ StorageDBThread::NoteBackgroundThreadRunnable::Run() {
|
|||
StorageObserver* observer = StorageObserver::Self();
|
||||
MOZ_ASSERT(observer);
|
||||
|
||||
observer->NoteBackgroundThread(mOwningThread);
|
||||
observer->NoteBackgroundThread(mPrivateBrowsingId, mOwningThread);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -1544,11 +1566,14 @@ StorageDBThread::ShutdownRunnable::Run() {
|
|||
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
if (sStorageThread) {
|
||||
sStorageThread->Shutdown();
|
||||
StorageDBThread*& storageThread = sStorageThread[mPrivateBrowsingId];
|
||||
if (storageThread) {
|
||||
sStorageThreadDown[mPrivateBrowsingId] = true;
|
||||
|
||||
delete sStorageThread;
|
||||
sStorageThread = nullptr;
|
||||
storageThread->Shutdown();
|
||||
|
||||
delete storageThread;
|
||||
storageThread = nullptr;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
|
||||
|
|
|
|||
|
|
@ -292,12 +292,16 @@ class StorageDBThread final {
|
|||
class NoteBackgroundThreadRunnable;
|
||||
|
||||
class ShutdownRunnable : public Runnable {
|
||||
// Expected to be only 0 or 1.
|
||||
const uint32_t mPrivateBrowsingId;
|
||||
// Only touched on the main thread.
|
||||
bool& mDone;
|
||||
|
||||
public:
|
||||
explicit ShutdownRunnable(bool& aDone)
|
||||
: Runnable("dom::StorageDBThread::ShutdownRunnable"), mDone(aDone) {
|
||||
explicit ShutdownRunnable(const uint32_t aPrivateBrowsingId, bool& aDone)
|
||||
: Runnable("dom::StorageDBThread::ShutdownRunnable"),
|
||||
mPrivateBrowsingId(aPrivateBrowsingId),
|
||||
mDone(aDone) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
|
|
@ -308,12 +312,13 @@ class StorageDBThread final {
|
|||
};
|
||||
|
||||
public:
|
||||
StorageDBThread();
|
||||
explicit StorageDBThread(uint32_t aPrivateBrowsingId);
|
||||
virtual ~StorageDBThread() = default;
|
||||
|
||||
static StorageDBThread* Get();
|
||||
static StorageDBThread* Get(uint32_t aPrivateBrowsingId);
|
||||
|
||||
static StorageDBThread* GetOrCreate(const nsString& aProfilePath);
|
||||
static StorageDBThread* GetOrCreate(const nsString& aProfilePath,
|
||||
uint32_t aPrivateBrowsingId);
|
||||
|
||||
static nsresult GetProfilePath(nsString& aProfilePath);
|
||||
|
||||
|
|
@ -429,6 +434,9 @@ class StorageDBThread final {
|
|||
// Collector of pending update operations
|
||||
PendingOperations mPendingTasks;
|
||||
|
||||
// Expected to be only 0 or 1.
|
||||
const uint32_t mPrivateBrowsingId;
|
||||
|
||||
// Counter of calls for thread priority rising.
|
||||
int32_t mPriorityCounter;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ typedef nsClassHashtable<nsCStringHashKey, nsTArray<LocalStorageCacheParent*>>
|
|||
|
||||
StaticAutoPtr<LocalStorageCacheParentHashtable> gLocalStorageCacheParents;
|
||||
|
||||
StorageDBChild* sStorageChild = nullptr;
|
||||
StorageDBChild* sStorageChild[2] = {nullptr, nullptr};
|
||||
|
||||
// False until we shut the storage child down.
|
||||
bool sStorageChildDown = false;
|
||||
bool sStorageChildDown[2] = {false, false};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
@ -111,8 +111,14 @@ mozilla::ipc::IPCResult LocalStorageCacheChild::RecvObserve(
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
class StorageDBChild::ShutdownObserver final : public nsIObserver {
|
||||
// Expected to be only 0 or 1.
|
||||
const uint32_t mPrivateBrowsingId;
|
||||
|
||||
public:
|
||||
ShutdownObserver() { MOZ_ASSERT(NS_IsMainThread()); }
|
||||
explicit ShutdownObserver(const uint32_t aPrivateBrowsingId)
|
||||
: mPrivateBrowsingId(aPrivateBrowsingId) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
|
@ -133,47 +139,55 @@ void StorageDBChild::ReleaseIPDLReference() {
|
|||
Release();
|
||||
}
|
||||
|
||||
StorageDBChild::StorageDBChild(LocalStorageManager* aManager)
|
||||
: mManager(aManager), mStatus(NS_OK), mIPCOpen(false) {
|
||||
StorageDBChild::StorageDBChild(LocalStorageManager* aManager,
|
||||
const uint32_t aPrivateBrowsingId)
|
||||
: mManager(aManager),
|
||||
mPrivateBrowsingId(aPrivateBrowsingId),
|
||||
mStatus(NS_OK),
|
||||
mIPCOpen(false) {
|
||||
MOZ_ASSERT(aPrivateBrowsingId <= 1);
|
||||
MOZ_ASSERT(!NextGenLocalStorageEnabled());
|
||||
}
|
||||
|
||||
StorageDBChild::~StorageDBChild() = default;
|
||||
|
||||
// static
|
||||
StorageDBChild* StorageDBChild::Get() {
|
||||
StorageDBChild* StorageDBChild::Get(const uint32_t aPrivateBrowsingId) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aPrivateBrowsingId <= 1);
|
||||
MOZ_ASSERT(!NextGenLocalStorageEnabled());
|
||||
|
||||
return sStorageChild;
|
||||
return sStorageChild[aPrivateBrowsingId];
|
||||
}
|
||||
|
||||
// static
|
||||
StorageDBChild* StorageDBChild::GetOrCreate() {
|
||||
StorageDBChild* StorageDBChild::GetOrCreate(const uint32_t aPrivateBrowsingId) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aPrivateBrowsingId <= 1);
|
||||
MOZ_ASSERT(!NextGenLocalStorageEnabled());
|
||||
|
||||
if (sStorageChild || sStorageChildDown) {
|
||||
StorageDBChild*& storageChild = sStorageChild[aPrivateBrowsingId];
|
||||
if (storageChild || sStorageChildDown[aPrivateBrowsingId]) {
|
||||
// When sStorageChildDown is at true, sStorageChild is null.
|
||||
// Checking sStorageChildDown flag here prevents reinitialization of
|
||||
// the storage child after shutdown.
|
||||
return sStorageChild;
|
||||
return storageChild;
|
||||
}
|
||||
|
||||
// Use LocalStorageManager::Ensure in case we're called from
|
||||
// DOMSessionStorageManager's initializer and we haven't yet initialized the
|
||||
// local storage manager.
|
||||
RefPtr<StorageDBChild> storageChild =
|
||||
new StorageDBChild(LocalStorageManager::Ensure());
|
||||
RefPtr<StorageDBChild> newStorageChild =
|
||||
new StorageDBChild(LocalStorageManager::Ensure(), aPrivateBrowsingId);
|
||||
|
||||
nsresult rv = storageChild->Init();
|
||||
nsresult rv = newStorageChild->Init();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
storageChild.forget(&sStorageChild);
|
||||
newStorageChild.forget(&storageChild);
|
||||
|
||||
return sStorageChild;
|
||||
return storageChild;
|
||||
}
|
||||
|
||||
nsTHashtable<nsCStringHashKey>& StorageDBChild::OriginsHavingData() {
|
||||
|
|
@ -194,7 +208,7 @@ nsresult StorageDBChild::Init() {
|
|||
}
|
||||
|
||||
nsString profilePath;
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (XRE_IsParentProcess() && mPrivateBrowsingId == 0) {
|
||||
nsresult rv = StorageDBThread::GetProfilePath(profilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
|
@ -203,12 +217,13 @@ nsresult StorageDBChild::Init() {
|
|||
|
||||
AddIPDLReference();
|
||||
|
||||
actor->SendPBackgroundStorageConstructor(this, profilePath);
|
||||
actor->SendPBackgroundStorageConstructor(this, profilePath,
|
||||
mPrivateBrowsingId);
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
|
||||
MOZ_ASSERT(observerService);
|
||||
|
||||
nsCOMPtr<nsIObserver> observer = new ShutdownObserver();
|
||||
nsCOMPtr<nsIObserver> observer = new ShutdownObserver(mPrivateBrowsingId);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
observerService->AddObserver(observer, "xpcom-shutdown", false));
|
||||
|
|
@ -380,7 +395,7 @@ mozilla::ipc::IPCResult StorageDBChild::RecvLoadDone(
|
|||
mozilla::ipc::IPCResult StorageDBChild::RecvLoadUsage(
|
||||
const nsCString& aOriginNoSuffix, const int64_t& aUsage) {
|
||||
RefPtr<StorageUsageBridge> scopeUsage =
|
||||
mManager->GetOriginUsage(aOriginNoSuffix);
|
||||
mManager->GetOriginUsage(aOriginNoSuffix, mPrivateBrowsingId);
|
||||
scopeUsage->LoadUsage(aUsage);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
|
@ -407,13 +422,14 @@ StorageDBChild::ShutdownObserver::Observe(nsISupports* aSubject,
|
|||
|
||||
Unused << observerService->RemoveObserver(this, "xpcom-shutdown");
|
||||
|
||||
if (sStorageChild) {
|
||||
sStorageChildDown = true;
|
||||
StorageDBChild*& storageChild = sStorageChild[mPrivateBrowsingId];
|
||||
if (storageChild) {
|
||||
sStorageChildDown[mPrivateBrowsingId] = true;
|
||||
|
||||
MOZ_ALWAYS_TRUE(sStorageChild->PBackgroundStorageChild::SendDeleteMe());
|
||||
MOZ_ALWAYS_TRUE(storageChild->PBackgroundStorageChild::SendDeleteMe());
|
||||
|
||||
NS_RELEASE(sStorageChild);
|
||||
sStorageChild = nullptr;
|
||||
NS_RELEASE(storageChild);
|
||||
storageChild = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
@ -667,8 +683,11 @@ void StorageDBParent::ReleaseIPDLReference() {
|
|||
|
||||
namespace {} // namespace
|
||||
|
||||
StorageDBParent::StorageDBParent(const nsString& aProfilePath)
|
||||
: mProfilePath(aProfilePath), mIPCOpen(false) {
|
||||
StorageDBParent::StorageDBParent(const nsString& aProfilePath,
|
||||
const uint32_t aPrivateBrowsingId)
|
||||
: mProfilePath(aProfilePath),
|
||||
mPrivateBrowsingId(aPrivateBrowsingId),
|
||||
mIPCOpen(false) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
// We are always open by IPC only
|
||||
|
|
@ -695,7 +714,7 @@ void StorageDBParent::Init() {
|
|||
mObserverSink->Start();
|
||||
}
|
||||
|
||||
StorageDBThread* storageThread = StorageDBThread::Get();
|
||||
StorageDBThread* storageThread = StorageDBThread::Get(mPrivateBrowsingId);
|
||||
if (storageThread) {
|
||||
nsTArray<nsCString> scopes;
|
||||
storageThread->GetOriginsHavingData(&scopes);
|
||||
|
|
@ -725,7 +744,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvDeleteMe() {
|
|||
mozilla::ipc::IPCResult StorageDBParent::RecvAsyncPreload(
|
||||
const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix,
|
||||
const bool& aPriority) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -738,7 +758,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvAsyncPreload(
|
|||
|
||||
mozilla::ipc::IPCResult StorageDBParent::RecvAsyncGetUsage(
|
||||
const nsCString& aOriginNoSuffix) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -833,7 +854,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvPreload(
|
|||
const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix,
|
||||
const uint32_t& aAlreadyLoadedCount, nsTArray<nsString>* aKeys,
|
||||
nsTArray<nsString>* aValues, nsresult* aRv) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -850,7 +872,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvPreload(
|
|||
mozilla::ipc::IPCResult StorageDBParent::RecvAsyncAddItem(
|
||||
const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix,
|
||||
const nsString& aKey, const nsString& aValue) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -867,7 +890,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvAsyncAddItem(
|
|||
mozilla::ipc::IPCResult StorageDBParent::RecvAsyncUpdateItem(
|
||||
const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix,
|
||||
const nsString& aKey, const nsString& aValue) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -884,7 +908,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvAsyncUpdateItem(
|
|||
mozilla::ipc::IPCResult StorageDBParent::RecvAsyncRemoveItem(
|
||||
const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix,
|
||||
const nsString& aKey) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -900,7 +925,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvAsyncRemoveItem(
|
|||
|
||||
mozilla::ipc::IPCResult StorageDBParent::RecvAsyncClear(
|
||||
const nsCString& aOriginSuffix, const nsCString& aOriginNoSuffix) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -915,7 +941,7 @@ mozilla::ipc::IPCResult StorageDBParent::RecvAsyncClear(
|
|||
}
|
||||
|
||||
mozilla::ipc::IPCResult StorageDBParent::RecvAsyncFlush() {
|
||||
StorageDBThread* storageThread = StorageDBThread::Get();
|
||||
StorageDBThread* storageThread = StorageDBThread::Get(mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -926,7 +952,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvAsyncFlush() {
|
|||
}
|
||||
|
||||
mozilla::ipc::IPCResult StorageDBParent::RecvStartup() {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -935,7 +962,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvStartup() {
|
|||
}
|
||||
|
||||
mozilla::ipc::IPCResult StorageDBParent::RecvClearAll() {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -947,7 +975,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvClearAll() {
|
|||
|
||||
mozilla::ipc::IPCResult StorageDBParent::RecvClearMatchingOrigin(
|
||||
const nsCString& aOriginNoSuffix) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -959,7 +988,8 @@ mozilla::ipc::IPCResult StorageDBParent::RecvClearMatchingOrigin(
|
|||
|
||||
mozilla::ipc::IPCResult StorageDBParent::RecvClearMatchingOriginAttributes(
|
||||
const OriginAttributesPattern& aPattern) {
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
|
||||
StorageDBThread* storageThread =
|
||||
StorageDBThread::GetOrCreate(mProfilePath, mPrivateBrowsingId);
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
|
@ -1459,14 +1489,15 @@ bool DeallocPBackgroundLocalStorageCacheParent(
|
|||
}
|
||||
|
||||
PBackgroundStorageParent* AllocPBackgroundStorageParent(
|
||||
const nsString& aProfilePath) {
|
||||
const nsString& aProfilePath, const uint32_t& aPrivateBrowsingId) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
return new StorageDBParent(aProfilePath);
|
||||
return new StorageDBParent(aProfilePath, aPrivateBrowsingId);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RecvPBackgroundStorageConstructor(
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath) {
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath,
|
||||
const uint32_t& aPrivateBrowsingId) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
|
|
|
|||
|
|
@ -100,11 +100,11 @@ class StorageDBChild final : public PBackgroundStorageChild {
|
|||
virtual ~StorageDBChild();
|
||||
|
||||
public:
|
||||
explicit StorageDBChild(LocalStorageManager* aManager);
|
||||
StorageDBChild(LocalStorageManager* aManager, uint32_t aPrivateBrowsingId);
|
||||
|
||||
static StorageDBChild* Get();
|
||||
static StorageDBChild* Get(uint32_t aPrivateBrowsingId);
|
||||
|
||||
static StorageDBChild* GetOrCreate();
|
||||
static StorageDBChild* GetOrCreate(uint32_t aPrivateBrowsingId);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(StorageDBChild);
|
||||
|
||||
|
|
@ -178,6 +178,9 @@ class StorageDBChild final : public PBackgroundStorageChild {
|
|||
// AsyncPreload call references the cache for time of the preload.
|
||||
nsTHashtable<nsRefPtrHashKey<LocalStorageCacheBridge>> mLoadingCaches;
|
||||
|
||||
// Expected to be only 0 or 1.
|
||||
const uint32_t mPrivateBrowsingId;
|
||||
|
||||
// Status of the remote database
|
||||
nsresult mStatus;
|
||||
|
||||
|
|
@ -332,7 +335,7 @@ class StorageDBParent final : public PBackgroundStorageParent {
|
|||
virtual ~StorageDBParent();
|
||||
|
||||
public:
|
||||
explicit StorageDBParent(const nsString& aProfilePath);
|
||||
StorageDBParent(const nsString& aProfilePath, uint32_t aPrivateBrowsingId);
|
||||
|
||||
void Init();
|
||||
|
||||
|
|
@ -469,6 +472,9 @@ class StorageDBParent final : public PBackgroundStorageParent {
|
|||
// Populated for the same process actors, empty for other process actors.
|
||||
nsString mProfilePath;
|
||||
|
||||
// Expected to be only 0 or 1.
|
||||
const uint32_t mPrivateBrowsingId;
|
||||
|
||||
ThreadSafeAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
|
|
@ -574,10 +580,11 @@ bool DeallocPBackgroundLocalStorageCacheParent(
|
|||
PBackgroundLocalStorageCacheParent* aActor);
|
||||
|
||||
PBackgroundStorageParent* AllocPBackgroundStorageParent(
|
||||
const nsString& aProfilePath);
|
||||
const nsString& aProfilePath, const uint32_t& aPrivateBrowsingId);
|
||||
|
||||
mozilla::ipc::IPCResult RecvPBackgroundStorageConstructor(
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath);
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath,
|
||||
const uint32_t& aPrivateBrowsingId);
|
||||
|
||||
bool DeallocPBackgroundStorageParent(PBackgroundStorageParent* aActor);
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ static const uint32_t kStartupDelay = 0;
|
|||
|
||||
const char kTestingPref[] = "dom.storage.testing";
|
||||
|
||||
constexpr auto kPrivateBrowsingPattern = u"{ \"privateBrowsingId\": 1 }"_ns;
|
||||
|
||||
NS_IMPL_ISUPPORTS(StorageObserver, nsIObserver, nsISupportsWeakReference)
|
||||
|
||||
StorageObserver* StorageObserver::sSelf = nullptr;
|
||||
|
|
@ -129,8 +131,11 @@ void StorageObserver::Notify(const char* aTopic,
|
|||
}
|
||||
}
|
||||
|
||||
void StorageObserver::NoteBackgroundThread(nsIEventTarget* aBackgroundThread) {
|
||||
mBackgroundThread = aBackgroundThread;
|
||||
void StorageObserver::NoteBackgroundThread(const uint32_t aPrivateBrowsingId,
|
||||
nsIEventTarget* aBackgroundThread) {
|
||||
MOZ_ASSERT(aPrivateBrowsingId <= 1);
|
||||
|
||||
mBackgroundThread[aPrivateBrowsingId] = aBackgroundThread;
|
||||
}
|
||||
|
||||
nsresult StorageObserver::GetOriginScope(const char16_t* aData,
|
||||
|
|
@ -198,12 +203,14 @@ StorageObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
if (timer == mDBThreadStartDelayTimer) {
|
||||
mDBThreadStartDelayTimer = nullptr;
|
||||
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate(id);
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->SendStartup();
|
||||
storageChild->SendStartup();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
@ -216,15 +223,17 @@ StorageObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
|
||||
if (!NextGenLocalStorageEnabled()) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate(id);
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->AsyncClearAll();
|
||||
storageChild->AsyncClearAll();
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
storageChild->SendClearAll();
|
||||
if (XRE_IsParentProcess()) {
|
||||
storageChild->SendClearAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -297,25 +306,29 @@ StorageObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate(id);
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->SendClearMatchingOrigin(originScope);
|
||||
storageChild->SendClearMatchingOrigin(originScope);
|
||||
}
|
||||
}
|
||||
|
||||
Notify(topic, u""_ns, originScope);
|
||||
} else {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate(id);
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->AsyncClearAll();
|
||||
storageChild->AsyncClearAll();
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
storageChild->SendClearAll();
|
||||
if (XRE_IsParentProcess()) {
|
||||
storageChild->SendClearAll();
|
||||
}
|
||||
}
|
||||
|
||||
Notify(topic);
|
||||
|
|
@ -346,7 +359,33 @@ StorageObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
Notify("private-browsing-data-cleared", u"{ \"privateBrowsingId\": 1 }"_ns);
|
||||
// We get the notification in both processes (parent and content), but the
|
||||
// clearing of the in-memory database should be triggered from the parent
|
||||
// process only to avoid creation of redundant clearing operations.
|
||||
// Also, if we create a new StorageDBChild instance late during content
|
||||
// process shutdown, then it might be leaked in debug builds because it
|
||||
// could happen that there is no chance to properly destroy it.
|
||||
if (XRE_IsParentProcess()) {
|
||||
// This doesn't use a loop with privateBrowsingId 0 and 1, since we only
|
||||
// need to clear the in-memory database which is represented by
|
||||
// privateBrowsingId 1.
|
||||
static const uint32_t id = 1;
|
||||
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate(id);
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
OriginAttributesPattern pattern;
|
||||
if (!pattern.Init(kPrivateBrowsingPattern)) {
|
||||
NS_ERROR("Cannot parse origin attributes pattern");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->SendClearMatchingOriginAttributes(pattern);
|
||||
}
|
||||
|
||||
Notify("private-browsing-data-cleared", kPrivateBrowsingPattern);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -365,12 +404,14 @@ StorageObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate(id);
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->SendClearMatchingOriginAttributes(pattern);
|
||||
storageChild->SendClearMatchingOriginAttributes(pattern);
|
||||
}
|
||||
|
||||
Notify("origin-attr-pattern-cleared", nsDependentString(aData));
|
||||
|
||||
|
|
@ -390,17 +431,19 @@ StorageObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mBackgroundThread) {
|
||||
bool done = false;
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
if (mBackgroundThread[id]) {
|
||||
bool done = false;
|
||||
|
||||
RefPtr<StorageDBThread::ShutdownRunnable> shutdownRunnable =
|
||||
new StorageDBThread::ShutdownRunnable(done);
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
mBackgroundThread->Dispatch(shutdownRunnable, NS_DISPATCH_NORMAL));
|
||||
RefPtr<StorageDBThread::ShutdownRunnable> shutdownRunnable =
|
||||
new StorageDBThread::ShutdownRunnable(id, done);
|
||||
MOZ_ALWAYS_SUCCEEDS(mBackgroundThread[id]->Dispatch(
|
||||
shutdownRunnable, NS_DISPATCH_NORMAL));
|
||||
|
||||
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return done; }));
|
||||
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return done; }));
|
||||
|
||||
mBackgroundThread = nullptr;
|
||||
mBackgroundThread[id] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
@ -412,12 +455,14 @@ StorageObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
for (const uint32_t id : {0, 1}) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate(id);
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->SendAsyncFlush();
|
||||
storageChild->SendAsyncFlush();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ class StorageObserver : public nsIObserver, public nsSupportsWeakReference {
|
|||
const nsAString& aOriginAttributesPattern = u""_ns,
|
||||
const nsACString& aOriginScope = ""_ns);
|
||||
|
||||
void NoteBackgroundThread(nsIEventTarget* aBackgroundThread);
|
||||
void NoteBackgroundThread(uint32_t aPrivateBrowsingId,
|
||||
nsIEventTarget* aBackgroundThread);
|
||||
|
||||
private:
|
||||
virtual ~StorageObserver() = default;
|
||||
|
|
@ -61,7 +62,7 @@ class StorageObserver : public nsIObserver, public nsSupportsWeakReference {
|
|||
|
||||
static StorageObserver* sSelf;
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mBackgroundThread;
|
||||
nsCOMPtr<nsIEventTarget> mBackgroundThread[2];
|
||||
|
||||
// Weak references
|
||||
nsTObserverArray<StorageObserverSink*> mSinks;
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ bool BackgroundChildImpl::DeallocPBackgroundLSSimpleRequestChild(
|
|||
|
||||
BackgroundChildImpl::PBackgroundStorageChild*
|
||||
BackgroundChildImpl::AllocPBackgroundStorageChild(
|
||||
const nsString& aProfilePath) {
|
||||
const nsString& aProfilePath, const uint32_t& aPrivateBrowsingId) {
|
||||
MOZ_CRASH("PBackgroundStorageChild actors should be manually constructed!");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,8 @@ class BackgroundChildImpl : public PBackgroundChild,
|
|||
PBackgroundLocalStorageCacheChild* aActor) override;
|
||||
|
||||
virtual PBackgroundStorageChild* AllocPBackgroundStorageChild(
|
||||
const nsString& aProfilePath) override;
|
||||
const nsString& aProfilePath,
|
||||
const uint32_t& aPrivateBrowsingId) override;
|
||||
|
||||
virtual bool DeallocPBackgroundStorageChild(
|
||||
PBackgroundStorageChild* aActor) override;
|
||||
|
|
|
|||
|
|
@ -452,20 +452,24 @@ bool BackgroundParentImpl::DeallocPBackgroundLocalStorageCacheParent(
|
|||
}
|
||||
|
||||
auto BackgroundParentImpl::AllocPBackgroundStorageParent(
|
||||
const nsString& aProfilePath) -> PBackgroundStorageParent* {
|
||||
const nsString& aProfilePath, const uint32_t& aPrivateBrowsingId)
|
||||
-> PBackgroundStorageParent* {
|
||||
AssertIsInMainOrSocketProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
return mozilla::dom::AllocPBackgroundStorageParent(aProfilePath);
|
||||
return mozilla::dom::AllocPBackgroundStorageParent(aProfilePath,
|
||||
aPrivateBrowsingId);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundStorageConstructor(
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath) {
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath,
|
||||
const uint32_t& aPrivateBrowsingId) {
|
||||
AssertIsInMainOrSocketProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
return mozilla::dom::RecvPBackgroundStorageConstructor(aActor, aProfilePath);
|
||||
return mozilla::dom::RecvPBackgroundStorageConstructor(aActor, aProfilePath,
|
||||
aPrivateBrowsingId);
|
||||
}
|
||||
|
||||
bool BackgroundParentImpl::DeallocPBackgroundStorageParent(
|
||||
|
|
|
|||
|
|
@ -130,10 +130,12 @@ class BackgroundParentImpl : public PBackgroundParent,
|
|||
PBackgroundLocalStorageCacheParent* aActor) override;
|
||||
|
||||
PBackgroundStorageParent* AllocPBackgroundStorageParent(
|
||||
const nsString& aProfilePath) override;
|
||||
const nsString& aProfilePath,
|
||||
const uint32_t& aPrivateBrowsingId) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvPBackgroundStorageConstructor(
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath) override;
|
||||
PBackgroundStorageParent* aActor, const nsString& aProfilePath,
|
||||
const uint32_t& aPrivateBrowsingId) override;
|
||||
|
||||
bool DeallocPBackgroundStorageParent(
|
||||
PBackgroundStorageParent* aActor) override;
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ parent:
|
|||
|
||||
async PBackgroundSessionStorageManager(uint64_t aTopContextId);
|
||||
|
||||
async PBackgroundStorage(nsString profilePath);
|
||||
async PBackgroundStorage(nsString profilePath, uint32_t privateBrowsingId);
|
||||
|
||||
async PVsync();
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ function cleanup() {
|
|||
}
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
|
||||
registerCleanupFunction(cleanup);
|
||||
Services.obs.addObserver(gObserver, "last-pb-context-exited");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue