3462 lines
121 KiB
C++
3462 lines
121 KiB
C++
/* -*- 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/. */
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "mozilla/BasePrincipal.h"
|
|
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
|
#include "mozilla/dom/quota/ClientDirectoryLock.h"
|
|
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
|
|
#include "mozilla/dom/quota/DirectoryLock.h"
|
|
#include "mozilla/dom/quota/DirectoryLockInlines.h"
|
|
#include "mozilla/dom/quota/OriginScope.h"
|
|
#include "mozilla/dom/quota/PersistenceScope.h"
|
|
#include "mozilla/dom/quota/QuotaManager.h"
|
|
#include "mozilla/dom/quota/ResultExtensions.h"
|
|
#include "mozilla/dom/quota/UniversalDirectoryLock.h"
|
|
#include "mozilla/gtest/MozAssertions.h"
|
|
#include "nsFmtString.h"
|
|
#include "prtime.h"
|
|
#include "QuotaManagerDependencyFixture.h"
|
|
#include "QuotaManagerTestHelpers.h"
|
|
|
|
namespace mozilla::dom::quota::test {
|
|
|
|
class TestQuotaManager : public QuotaManagerDependencyFixture {
|
|
public:
|
|
static void SetUpTestCase() { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
|
|
|
|
static void TearDownTestCase() { ASSERT_NO_FATAL_FAILURE(ShutdownFixture()); }
|
|
|
|
void TearDown() override {
|
|
ASSERT_NO_FATAL_FAILURE(ClearStoragesForOrigin(GetTestOriginMetadata()));
|
|
}
|
|
};
|
|
|
|
class TestQuotaManagerAndClearStorage : public TestQuotaManager {
|
|
public:
|
|
void TearDown() override { ASSERT_NO_FATAL_FAILURE(ClearStorage()); }
|
|
};
|
|
|
|
using BoolPairTestParams = std::pair<bool, bool>;
|
|
|
|
class TestQuotaManagerAndClearStorageWithBoolPair
|
|
: public TestQuotaManagerAndClearStorage,
|
|
public testing::WithParamInterface<BoolPairTestParams> {};
|
|
|
|
class TestQuotaManagerAndShutdownFixture
|
|
: public QuotaManagerDependencyFixture {
|
|
public:
|
|
void SetUp() override { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
|
|
|
|
void TearDown() override { ASSERT_NO_FATAL_FAILURE(ShutdownFixture()); }
|
|
};
|
|
|
|
TEST_F(TestQuotaManager, GetThumbnailPrivateIdentityId) {
|
|
PerformOnIOThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
const bool known = quotaManager->IsThumbnailPrivateIdentityIdKnown();
|
|
ASSERT_TRUE(known);
|
|
|
|
const uint32_t id = quotaManager->GetThumbnailPrivateIdentityId();
|
|
ASSERT_GT(id, 4u);
|
|
});
|
|
}
|
|
|
|
// Test OpenStorageDirectory when an opening of the storage directory is
|
|
// already ongoing and storage shutdown is scheduled after that.
|
|
TEST_F(TestQuotaManager, OpenStorageDirectory_OngoingWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock;
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(
|
|
quotaManager
|
|
->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](
|
|
UniversalDirectoryLockPromise::ResolveOrRejectValue&&
|
|
aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
[&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
|
|
|
|
directoryLock = std::move(aValue.ResolveValue());
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(quotaManager->IOThread(), __func__,
|
|
[](const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
[]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ASSERT_TRUE(
|
|
quotaManager->IsStorageInitializedInternal());
|
|
}();
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](
|
|
const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(
|
|
quotaManager
|
|
->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[](UniversalDirectoryLockPromise::ResolveOrRejectValue&&
|
|
aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(aValue.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenStorageDirectory when an opening of the storage directory is
|
|
// already ongoing and an exclusive directory lock is requested after that.
|
|
TEST_F(TestQuotaManager,
|
|
OpenStorageDirectory_OngoingWithExclusiveDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
|
|
ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(
|
|
quotaManager
|
|
->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](
|
|
UniversalDirectoryLockPromise::ResolveOrRejectValue&&
|
|
aValue) {
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(aValue.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(
|
|
quotaManager
|
|
->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[](UniversalDirectoryLockPromise::ResolveOrRejectValue&&
|
|
aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(aValue.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenStorageDirectory when an opening of the storage directory already
|
|
// finished.
|
|
TEST_F(TestQuotaManager, OpenStorageDirectory_Finished) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(value.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
{
|
|
auto value = Await(quotaManager->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(value.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenStorageDirectory when an opening of the storage directory already
|
|
// finished but storage shutdown has just been scheduled.
|
|
TEST_F(TestQuotaManager, OpenStorageDirectory_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(value.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(
|
|
quotaManager
|
|
->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[](UniversalDirectoryLockPromise::ResolveOrRejectValue&&
|
|
aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(aValue.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenStorageDirectory when an opening of the storage directory already
|
|
// finished and an exclusive client directory lock for a non-overlapping
|
|
// origin is acquired in between.
|
|
TEST_F(TestQuotaManager,
|
|
OpenStorageDirectory_FinishedWithExclusiveClientDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(value.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ true);
|
|
|
|
{
|
|
auto value = Await(directoryLock->Acquire());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
{
|
|
auto value = Await(quotaManager->OpenStorageDirectory(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ false));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
std::move(value.ResolveValue());
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple OpenClientDirectory behavior and verify that origin access time
|
|
// updates are triggered as expected.
|
|
TEST_F(TestQuotaManager, OpenClientDirectory_Simple) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalBefore =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ProcessPendingNormalOriginOperations();
|
|
|
|
const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalAfter =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
// XXX We currently observe only one access time update (on last access), but
|
|
// it should have been updated twice!
|
|
ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
|
|
1u);
|
|
ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
1u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple OpenClientDirectory behavior when the origin directory exists,
|
|
// and verify that access time updates are triggered on first and last access.
|
|
TEST_F(TestQuotaManager, OpenClientDirectory_Simple_OriginDirectoryExists) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
InitializeTemporaryOrigin(GetTestOriginMetadata(),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalBefore =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ProcessPendingNormalOriginOperations();
|
|
|
|
const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalAfter =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
|
|
2u);
|
|
ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
2u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirectory when the origin directory doesn't exist, and verify
|
|
// that no access time update occurs. The directory should not be created
|
|
// solely for updating access time.
|
|
TEST_F(TestQuotaManager,
|
|
OpenClientDirectory_Simple_NonExistingOriginDirectory) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
InitializeTemporaryOrigin(GetTestOriginMetadata(),
|
|
/* aCreateIfNonExistent */ false));
|
|
|
|
const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalBefore =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->OpenClientDirectory(
|
|
GetTestClientMetadata(),
|
|
/* aInitializeOrigin */ true, /* aCreateIfNonExistent */ false));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ProcessPendingNormalOriginOperations();
|
|
|
|
const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalAfter =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
// This is expected to be 0, the origin directory should not be created
|
|
// solely to update access time when, for example, LSNG explicitly requests
|
|
// that it not be created if it doesn't exist. The access time will be saved
|
|
// later.
|
|
ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
|
|
0u);
|
|
ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
0u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirectory when a clear operation is scheduled before
|
|
// releasing the directory lock. Verifies that access time updates still occur,
|
|
// even with the scheduled clear operation.
|
|
TEST_F(TestQuotaManager,
|
|
OpenClientDirectory_SimpleWithScheduledClearing_OriginDirectoryExists) {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
InitializeTemporaryOrigin(testOriginMetadata,
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalBefore =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
PerformOnBackgroundThread([testOriginMetadata]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
// This can't be awaited here, it would cause a hang, on the other hand,
|
|
// it must be scheduled before the handle is moved below.
|
|
quotaManager->ClearStoragesForOrigin(
|
|
/* aPersistenceType */ Nothing(), principalInfo);
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ProcessPendingNormalOriginOperations();
|
|
|
|
const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalAfter =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
// XXX We currently observe only one access time update, but it should have
|
|
// been updated twice!
|
|
ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
|
|
1u);
|
|
ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
1u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirectory when a client directory opening is already ongoing
|
|
// and the origin directory exists. Verifies that each opening completes only
|
|
// after the origin access time update triggered by first access has finished,
|
|
// and that access time is updated only on first and last access as expected.
|
|
TEST_F(TestQuotaManager, OpenClientDirectory_Ongoing_OriginDirectoryExists) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
InitializeTemporaryOrigin(GetTestOriginMetadata(),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalBefore =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
PerformOnBackgroundThread([saveOriginAccessTimeCountBefore,
|
|
saveOriginAccessTimeCountInternalBefore]() {
|
|
auto testClientMetadata = GetTestClientMetadata();
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle;
|
|
ClientDirectoryLockHandle directoryLockHandle2;
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(
|
|
quotaManager->OpenClientDirectory(testClientMetadata)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[saveOriginAccessTimeCountBefore, &directoryLockHandle](
|
|
QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
MOZ_RELEASE_ASSERT(quotaManager);
|
|
|
|
const auto saveOriginAccessTimeCountNow =
|
|
quotaManager->SaveOriginAccessTimeCount();
|
|
|
|
const auto saveOriginAccessTimeCountDelta =
|
|
saveOriginAccessTimeCountNow -
|
|
saveOriginAccessTimeCountBefore;
|
|
|
|
// XXX This callback should only be called once the access
|
|
// time update has completed, but it's currently triggered
|
|
// inconsistently — sometimes before the update finishes.
|
|
// For now, we allow either 0 or 1 updates to reflect this
|
|
// timing issue.
|
|
EXPECT_TRUE(saveOriginAccessTimeCountDelta == 0u ||
|
|
saveOriginAccessTimeCountDelta == 1u);
|
|
|
|
directoryLockHandle = std::move(aValue.ResolveValue());
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(quotaManager->IOThread(), __func__,
|
|
[saveOriginAccessTimeCountInternalBefore](
|
|
const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
MOZ_RELEASE_ASSERT(quotaManager);
|
|
|
|
const auto saveOriginAccessTimeCountInternalNow =
|
|
quotaManager->SaveOriginAccessTimeCountInternal();
|
|
|
|
EXPECT_EQ(saveOriginAccessTimeCountInternalNow -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
1u);
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(
|
|
quotaManager->OpenClientDirectory(testClientMetadata)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[saveOriginAccessTimeCountBefore, &directoryLockHandle2](
|
|
QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
MOZ_RELEASE_ASSERT(quotaManager);
|
|
|
|
const auto saveOriginAccessTimeCountNow =
|
|
quotaManager->SaveOriginAccessTimeCount();
|
|
|
|
const auto saveOriginAccessTimeCountDelta =
|
|
saveOriginAccessTimeCountNow -
|
|
saveOriginAccessTimeCountBefore;
|
|
|
|
// XXX This callback should only be called once the access
|
|
// time update has completed, but it's currently triggered
|
|
// inconsistently — sometimes before the update finishes.
|
|
// For now, we allow either 0 or 1 updates to reflect this
|
|
// timing issue.
|
|
EXPECT_TRUE(saveOriginAccessTimeCountDelta == 0u ||
|
|
saveOriginAccessTimeCountDelta == 1u);
|
|
|
|
directoryLockHandle2 = std::move(aValue.ResolveValue());
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(quotaManager->IOThread(), __func__,
|
|
[saveOriginAccessTimeCountInternalBefore](
|
|
const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
MOZ_RELEASE_ASSERT(quotaManager);
|
|
|
|
const auto saveOriginAccessTimeCountInternalNow =
|
|
quotaManager->SaveOriginAccessTimeCountInternal();
|
|
|
|
EXPECT_EQ(saveOriginAccessTimeCountInternalNow -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
1u);
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle2 = std::move(directoryLockHandle2);
|
|
}
|
|
});
|
|
|
|
ProcessPendingNormalOriginOperations();
|
|
|
|
const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalAfter =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
|
|
2u);
|
|
ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
2u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirctory when an opening of a client directory is already
|
|
// ongoing and storage shutdown is scheduled after that.
|
|
TEST_F(TestQuotaManager, OpenClientDirectory_OngoingWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle;
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(
|
|
quotaManager->OpenClientDirectory(GetTestClientMetadata())
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLockHandle](
|
|
QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
[&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
|
|
|
|
directoryLockHandle = std::move(aValue.ResolveValue());
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(quotaManager->IOThread(), __func__,
|
|
[](const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
[]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ASSERT_TRUE(
|
|
quotaManager->IsStorageInitializedInternal());
|
|
}();
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLockHandle](
|
|
const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
{
|
|
auto destroyingDirectoryLockHandle =
|
|
std::move(directoryLockHandle);
|
|
}
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(
|
|
quotaManager->OpenClientDirectory(GetTestClientMetadata())
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[](QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(aValue.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle =
|
|
std::move(directoryLockHandle);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirectory when an opening of a client directory is already
|
|
// ongoing and an exclusive directory lock is requested after that.
|
|
TEST_F(TestQuotaManager,
|
|
OpenClientDirectory_OngoingWithExclusiveDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
|
|
ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(
|
|
quotaManager->OpenClientDirectory(GetTestClientMetadata())
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](
|
|
QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(aValue.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle =
|
|
std::move(directoryLockHandle);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(
|
|
quotaManager->OpenClientDirectory(GetTestClientMetadata())
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[](QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(aValue.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle =
|
|
std::move(directoryLockHandle);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirectory when an opening of a client directory already
|
|
// finished.
|
|
TEST_F(TestQuotaManager, OpenClientDirectory_Finished) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirectory when an opening of a client directory already
|
|
// finished but storage shutdown has just been scheduled.
|
|
TEST_F(TestQuotaManager, OpenClientDirectory_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(
|
|
quotaManager->OpenClientDirectory(GetTestClientMetadata())
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[](QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(aValue.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle =
|
|
std::move(directoryLockHandle);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test OpenClientDirectory when an opening of a client directory already
|
|
// finished with an exclusive client directory lock for a different origin is
|
|
// acquired in between.
|
|
TEST_F(TestQuotaManager,
|
|
OpenClientDirectory_FinishedWithOtherExclusiveClientDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetOtherTestClientMetadata(),
|
|
/* aExclusive */ true);
|
|
|
|
{
|
|
auto value = Await(directoryLock->Acquire());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle =
|
|
std::move(value.ResolveValue());
|
|
|
|
{
|
|
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
|
|
}
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle;
|
|
|
|
RefPtr<BoolPromise> promise =
|
|
quotaManager
|
|
->OpenClientDirectory(GetTestClientMetadata(),
|
|
/* aInitializeOrigin */ true)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLockHandle](
|
|
QuotaManager::ClientDirectoryLockHandlePromise::
|
|
ResolveOrRejectValue&& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
[&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
|
|
|
|
directoryLockHandle = std::move(aValue.ResolveValue());
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(quotaManager->IOThread(), __func__,
|
|
[](const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
[]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryOriginInitializedInternal(
|
|
GetTestOriginMetadata()));
|
|
}();
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
})
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLockHandle](
|
|
const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
{
|
|
auto destroyingDirectoryLockHandle =
|
|
std::move(directoryLockHandle);
|
|
}
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
});
|
|
|
|
{
|
|
auto value = Await(promise);
|
|
ASSERT_TRUE(value.IsResolve());
|
|
ASSERT_TRUE(value.ResolveValue());
|
|
}
|
|
});
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ClearStoragesForOrigin(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ClientDirectoryLockHandle directoryLockHandle;
|
|
|
|
RefPtr<QuotaManager::ClientDirectoryLockHandlePromise> promise =
|
|
quotaManager->OpenClientDirectory(GetTestClientMetadata(),
|
|
/* aInitializeOrigin */ false);
|
|
|
|
{
|
|
auto value = Await(promise);
|
|
ASSERT_TRUE(value.IsReject());
|
|
ASSERT_EQ(value.RejectValue(),
|
|
NS_ERROR_DOM_QM_CLIENT_INIT_ORIGIN_UNINITIALIZED);
|
|
}
|
|
});
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple InitializeStorage.
|
|
TEST_F(TestQuotaManager, InitializeStorage_Simple) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization is already ongoing.
|
|
TEST_F(TestQuotaManager, InitializeStorage_Ongoing) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization is already ongoing and
|
|
// storage shutdown is scheduled after that.
|
|
TEST_F(TestQuotaManager, InitializeStorage_OngoingWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization is already ongoing and
|
|
// storage shutdown is scheduled after that. The tested InitializeStorage call
|
|
// is delayed to the point when storage shutdown is about to finish.
|
|
TEST_F(TestQuotaManager,
|
|
InitializeStorage_OngoingWithScheduledShutdown_Delayed) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
|
|
OriginOperationCallbackOptions callbackOptions;
|
|
callbackOptions.mWantWillFinishSync = true;
|
|
|
|
OriginOperationCallbacks callbacks;
|
|
promises.AppendElement(quotaManager->ShutdownStorage(Some(callbackOptions),
|
|
SomeRef(callbacks)));
|
|
|
|
promises.AppendElement(callbacks.mWillFinishSyncPromise.ref()->Then(
|
|
GetCurrentSerialEventTarget(), __func__,
|
|
[quotaManager = RefPtr(quotaManager)](
|
|
const ExclusiveBoolPromise::ResolveOrRejectValue& aValue) {
|
|
return InvokeAsync(
|
|
GetCurrentSerialEventTarget(), __func__,
|
|
[quotaManager]() { return quotaManager->InitializeStorage(); });
|
|
}));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization is already ongoing and
|
|
// an exclusive directory lock is requested after that.
|
|
TEST_F(TestQuotaManager, InitializeStorage_OngoingWithExclusiveDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
|
|
ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage()->Then(
|
|
GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
// The exclusive directory lock must be released when the first
|
|
// storage initialization is finished, otherwise it would endlessly
|
|
// block the second storage initialization.
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(), __func__);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization is already ongoing and
|
|
// shared client directory locks are requested after that.
|
|
// The shared client directory locks don't have to be released in this case.
|
|
TEST_F(TestQuotaManager, InitializeStorage_OngoingWithClientDirectoryLocks) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock2 =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock2->Acquire());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
DropDirectoryLock(directoryLock2);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization is already ongoing and
|
|
// shared client directory locks are requested after that with storage shutdown
|
|
// scheduled in between.
|
|
TEST_F(TestQuotaManager,
|
|
InitializeStorage_OngoingWithClientDirectoryLocksAndScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
directoryLock->OnInvalidate(
|
|
[&directoryLock]() { DropDirectoryLock(directoryLock); });
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock2 =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock2->Acquire());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock2);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization already finished.
|
|
TEST_F(TestQuotaManager, InitializeStorage_Finished) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization already finished but
|
|
// storage shutdown has just been scheduled.
|
|
TEST_F(TestQuotaManager, InitializeStorage_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization already finished and
|
|
// shared client directory locks are requested immediately after requesting
|
|
// storage initialization.
|
|
TEST_F(TestQuotaManager, InitializeStorage_FinishedWithClientDirectoryLocks) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock2 =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock2->Acquire());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
DropDirectoryLock(directoryLock2);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeStorage when a storage initialization already finished and
|
|
// shared client directory locks are requested immediatelly after requesting
|
|
// storage initialization with storage shutdown performed in between.
|
|
// The shared client directory lock is released when it gets invalidated by
|
|
// storage shutdown which then unblocks the shutdown.
|
|
TEST_F(TestQuotaManager,
|
|
InitializeStorage_FinishedWithClientDirectoryLocksAndScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
directoryLock->OnInvalidate(
|
|
[&directoryLock]() { DropDirectoryLock(directoryLock); });
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
{
|
|
auto value = Await(quotaManager->ShutdownStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_FALSE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock2 =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(directoryLock2->Acquire());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock2);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializePersistentStorage_OtherExclusiveDirectoryLockAcquired) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromSet(PERSISTENCE_TYPE_TEMPORARY,
|
|
PERSISTENCE_TYPE_DEFAULT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
{
|
|
auto value = Await(directoryLock->Acquire());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializePersistentStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializePersistentStorage when a persistent storage initialization is
|
|
// already ongoing and an exclusive directory lock is requested after that.
|
|
TEST_F(TestQuotaManager,
|
|
InitializePersistentStorage_OngoingWithExclusiveDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
|
|
ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializePersistentStorage()->Then(
|
|
GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
// The exclusive directory lock must be released when the first
|
|
// Persistent storage initialization is finished, otherwise it would
|
|
// endlessly block the second persistent storage initialization.
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(), __func__);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializePersistentStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializePersistentStorage when a persistent storage initialization
|
|
// already finished.
|
|
TEST_F(TestQuotaManager, InitializePersistentStorage_Finished) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializePersistentStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializePersistentStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializePersistentStorage_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializePersistentStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializePersistentStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializeTemporaryStorage_OtherExclusiveDirectoryLockAcquired) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
{
|
|
auto value = Await(directoryLock->Acquire());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeTemporaryStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeTemporaryStorage when a temporary storage initialization is
|
|
// already ongoing and an exclusive directory lock is requested after that.
|
|
TEST_F(TestQuotaManager,
|
|
InitializeTemporaryStorage_OngoingWithExclusiveDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
|
|
ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage()->Then(
|
|
GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
// The exclusive directory lock must be dropped when the first
|
|
// temporary storage initialization is finished, otherwise it would
|
|
// endlessly block the second temporary storage initialization.
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(), __func__);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeTemporaryStorage when a temporary storage initialization
|
|
// already finished.
|
|
TEST_F(TestQuotaManager, InitializeTemporaryStorage_Finished) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializeTemporaryStorage_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializeTemporaryGroup_OtherExclusiveDirectoryLockAcquired) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
}
|
|
|
|
{
|
|
auto value = Await(quotaManager->InitializeTemporaryStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
}
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
|
|
OriginScope::FromGroup(testOriginMetadata.mGroup),
|
|
ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
{
|
|
auto value = Await(directoryLock->Acquire());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
{
|
|
auto value =
|
|
Await(quotaManager->InitializeTemporaryGroup(testOriginMetadata));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeTemporaryGroup when a temporary group initialization is
|
|
// already ongoing and an exclusive directory lock is requested after that.
|
|
TEST_F(TestQuotaManager,
|
|
InitializeTemporaryGroup_OngoingWithExclusiveDirectoryLock) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<UniversalDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLockInternal(
|
|
PersistenceScope::CreateFromSet(PERSISTENCE_TYPE_TEMPORARY,
|
|
PERSISTENCE_TYPE_DEFAULT),
|
|
OriginScope::FromGroup(testOriginMetadata.mGroup),
|
|
ClientStorageScope::CreateFromNull(),
|
|
/* aExclusive */ true);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializeTemporaryGroup(testOriginMetadata)
|
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
[&directoryLock](
|
|
const BoolPromise::ResolveOrRejectValue& aValue) {
|
|
// The exclusive directory lock must be dropped when the
|
|
// first temporary group initialization is finished,
|
|
// otherwise it would endlessly block the second temporary
|
|
// group initialization.
|
|
DropDirectoryLock(directoryLock);
|
|
|
|
if (aValue.IsReject()) {
|
|
return BoolPromise::CreateAndReject(aValue.RejectValue(),
|
|
__func__);
|
|
}
|
|
|
|
return BoolPromise::CreateAndResolve(true, __func__);
|
|
}));
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializeTemporaryGroup(testOriginMetadata));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test InitializeTemporaryGroup when a temporary group initialization already
|
|
// finished.
|
|
TEST_F(TestQuotaManager, InitializeTemporaryGroup_Finished) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializeTemporaryGroup(testOriginMetadata));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializeTemporaryGroup(testOriginMetadata));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializeTemporaryGroup_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializeTemporaryGroup(testOriginMetadata));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializeTemporaryGroup(testOriginMetadata));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializePersistentOrigin_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestPersistentOriginMetadata();
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializePersistentOrigin(testOriginMetadata));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsPersistentOriginInitialized(testOriginMetadata));
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(
|
|
quotaManager->InitializePersistentOrigin(testOriginMetadata));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsPersistentOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
InitializeTemporaryOrigin_FinishedWithScheduledShutdown) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
|
|
testOriginMetadata,
|
|
/* aCreateIfNonExistent */ false));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
|
|
promises.Clear();
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryStorage());
|
|
promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
|
|
testOriginMetadata,
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_TRUE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Tests the availability of SaveOriginAccessTime and verifies that calling it
|
|
// does not trigger temporary storage or origin initialization.
|
|
TEST_F(TestQuotaManager, SaveOriginAccessTime_Simple) {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(testOriginMetadata));
|
|
|
|
SaveOriginAccessTime(testOriginMetadata, PR_Now());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(testOriginMetadata));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test SaveOriginAccessTime when saving of origin access time already finished
|
|
// with an exclusive client directory lock for a different client scope
|
|
// acquired in between.
|
|
TEST_F(TestQuotaManager,
|
|
SaveOriginAccessTime_FinishedWithOtherExclusiveClientDirectoryLock) {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(testOriginMetadata));
|
|
|
|
PerformOnBackgroundThread([testOriginMetadata]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
// Save origin access time first to ensure required initialization is
|
|
// complete. Otherwise, the exclusive directory lock below may not be
|
|
// acquirable.
|
|
{
|
|
int64_t timestamp = PR_Now();
|
|
|
|
auto value = Await(
|
|
quotaManager->SaveOriginAccessTime(testOriginMetadata, timestamp));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
// Acquire an exclusive directory lock for the SimpleDB quota client.
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ true);
|
|
|
|
{
|
|
auto value = Await(directoryLock->Acquire());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
// Save origin access time while the exclusive directory lock for SimpleDB
|
|
// is held. Verifies that saving origin access time uses a lock that does
|
|
// not overlap with quota client directory locks.
|
|
{
|
|
int64_t timestamp = PR_Now();
|
|
|
|
auto value = Await(
|
|
quotaManager->SaveOriginAccessTime(testOriginMetadata, timestamp));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
|
|
DropDirectoryLock(directoryLock);
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(testOriginMetadata));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple ClearStoragesForOrigin.
|
|
TEST_F(TestQuotaManager, ClearStoragesForOrigin_Simple) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
InitializeTemporaryOrigin(GetTestOriginMetadata(),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ClearStoragesForOrigin(
|
|
/* aPersistenceType */ Nothing(), principalInfo));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager, ClearStoragesForOrigin_NonExistentOriginDirectory) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ClearStoragesForOrigin(
|
|
/* aPersistenceType */ Nothing(), principalInfo));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple ClearStoragesForOriginPrefix.
|
|
TEST_F(TestQuotaManager, ClearStoragesForOriginPrefix_Simple) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetTestOriginMetadata(), /* aCreateIfNonExistent */ true));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ClearStoragesForOriginPrefix(
|
|
/* aPersistenceType */ Nothing(), principalInfo));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
ClearStoragesForOriginPrefix_NonExistentOriginDirectory) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ClearStoragesForOriginPrefix(
|
|
/* aPersistenceType */ Nothing(), principalInfo));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple ClearStoragesForOriginAttributesPattern.
|
|
TEST_F(TestQuotaManager, ClearStoragesForOriginAttributesPattern_Simple) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetTestOriginMetadata(), /* aCreateIfNonExistent */ true));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ClearStoragesForOriginAttributesPattern(
|
|
OriginAttributesPattern()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager,
|
|
ClearStoragesForOriginAttributesPattern_NonExistentOriginDirectory) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ClearStoragesForOriginAttributesPattern(
|
|
OriginAttributesPattern()));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple ShutdownStoragesForOrigin.
|
|
TEST_F(TestQuotaManager, ShutdownStoragesForOrigin_Simple) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetTestOriginMetadata(), /* aCreateIfNonExistent */ true));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ShutdownStoragesForOrigin(
|
|
/* aPersistenceType */ Nothing(), principalInfo));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager, ShutdownStoragesForOrigin_NonExistentOriginDirectory) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
|
|
QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
|
|
|
|
mozilla::ipc::PrincipalInfo principalInfo;
|
|
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
|
|
QM_TEST_FAIL);
|
|
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ShutdownStoragesForOrigin(
|
|
/* aPersistenceType */ Nothing(), principalInfo));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
|
|
ASSERT_FALSE(
|
|
quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test simple ShutdownStorage.
|
|
TEST_F(TestQuotaManager, ShutdownStorage_Simple) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
{
|
|
auto value = Await(quotaManager->ShutdownStorage());
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_FALSE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test ShutdownStorage when a storage shutdown is already ongoing.
|
|
TEST_F(TestQuotaManager, ShutdownStorage_Ongoing) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_FALSE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test ShutdownStorage when a storage shutdown is already ongoing and storage
|
|
// initialization is scheduled after that.
|
|
TEST_F(TestQuotaManager, ShutdownStorage_OngoingWithScheduledInitialization) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
promises.AppendElement(quotaManager->InitializeStorage());
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
|
|
{
|
|
auto value =
|
|
Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
|
|
ASSERT_FALSE(quotaManager->IsStorageInitialized());
|
|
}
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
// Test ShutdownStorage when a storage shutdown is already ongoing and a shared
|
|
// client directory lock is requested after that.
|
|
// The shared client directory lock doesn't have to be explicitly released
|
|
// because it gets invalidated while it's still pending which causes that any
|
|
// directory locks that were blocked by the shared client directory lock become
|
|
// unblocked.
|
|
TEST_F(TestQuotaManager, ShutdownStorage_OngoingWithClientDirectoryLock) {
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
RefPtr<ClientDirectoryLock> directoryLock =
|
|
quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
|
|
/* aExclusive */ false);
|
|
|
|
nsTArray<RefPtr<BoolPromise>> promises;
|
|
|
|
// This creates an exclusive directory lock internally.
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
|
|
// This directory lock can't be acquired yet because a storage shutdown
|
|
// (which uses an exclusive diretory lock internall) is ongoing.
|
|
promises.AppendElement(directoryLock->Acquire());
|
|
|
|
// This second ShutdownStorage invalidates the directoryLock, so that
|
|
// directory lock can't ever be successfully acquired, the promise for it
|
|
// will be rejected when the first ShutdownStorage is finished (it
|
|
// releases its exclusive directory lock);
|
|
promises.AppendElement(quotaManager->ShutdownStorage());
|
|
|
|
{
|
|
auto value = Await(
|
|
BoolPromise::AllSettled(GetCurrentSerialEventTarget(), promises));
|
|
ASSERT_TRUE(value.IsResolve());
|
|
}
|
|
});
|
|
}
|
|
|
|
// Test basic ProcessPendingNormalOriginOperations behavior when a normal
|
|
// origin operation is triggered but not explicitly awaited.
|
|
TEST_F(TestQuotaManager, ProcessPendingNormalOriginOperations_Basic) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
AssertStorageNotInitialized();
|
|
|
|
PerformOnBackgroundThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
ASSERT_FALSE(quotaManager->IsStorageInitialized());
|
|
|
|
// Intentionally do not await the returned promise to test that
|
|
// ProcessPendingNormalOriginOperations correctly processes any pending
|
|
// events and waits for the completion of any normal origin operation,
|
|
// such as the one triggered by InitializeStorage. In theory, any similar
|
|
// method could be used here, InitializeStorage was chosen for its
|
|
// simplicity.
|
|
quotaManager->InitializeStorage();
|
|
|
|
ASSERT_FALSE(quotaManager->IsStorageInitialized());
|
|
|
|
quotaManager->ProcessPendingNormalOriginOperations();
|
|
|
|
ASSERT_TRUE(quotaManager->IsStorageInitialized());
|
|
});
|
|
|
|
AssertStorageInitialized();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager, TotalDirectoryIterations_ClearingEmptyRepository) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
|
|
const auto totalDirectoryIterationsBefore = TotalDirectoryIterations();
|
|
|
|
ClearStoragesForOriginAttributesPattern(u""_ns);
|
|
|
|
const auto totalDirectoryIterationsAfter = TotalDirectoryIterations();
|
|
|
|
ASSERT_EQ(totalDirectoryIterationsAfter - totalDirectoryIterationsBefore, 0u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager, TotalDirectoryIterations_ClearingNonEmptyRepository) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
InitializeTemporaryOrigin(GetTestOriginMetadata(),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
const auto totalDirectoryIterationsBefore = TotalDirectoryIterations();
|
|
|
|
ClearStoragesForOriginAttributesPattern(u""_ns);
|
|
|
|
const auto totalDirectoryIterationsAfter = TotalDirectoryIterations();
|
|
|
|
ASSERT_EQ(totalDirectoryIterationsAfter - totalDirectoryIterationsBefore, 1u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager, SaveOriginAccessTimeCount_EmptyRepository) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
|
|
const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalBefore =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
SaveOriginAccessTime(GetTestOriginMetadata(), PR_Now());
|
|
|
|
const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalAfter =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
// Ensure access time update doesn't occur when origin doesn't exist.
|
|
ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
|
|
0u);
|
|
ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
0u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_F(TestQuotaManager, SaveOriginAccessTimeCount_OriginDirectoryExists) {
|
|
auto testOriginMetadata = GetTestOriginMetadata();
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
InitializeTemporaryOrigin(testOriginMetadata,
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalBefore =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
SaveOriginAccessTime(testOriginMetadata, PR_Now());
|
|
|
|
const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
|
|
const auto saveOriginAccessTimeCountInternalAfter =
|
|
SaveOriginAccessTimeCountInternal();
|
|
|
|
// Confirm the access time update was recorded.
|
|
ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
|
|
1u);
|
|
ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
|
|
saveOriginAccessTimeCountInternalBefore,
|
|
1u);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
|
|
}
|
|
|
|
TEST_P(TestQuotaManagerAndClearStorageWithBoolPair,
|
|
ClearStoragesForOriginAttributesPattern_ThumbnailPrivateIdentity) {
|
|
const BoolPairTestParams& param = GetParam();
|
|
|
|
const bool createThumbnailPrivateIdentityOrigins = param.first;
|
|
const bool keepTemporaryStorageInitialized = param.second;
|
|
|
|
const uint32_t thumbnailPrivateIdentityId = PerformOnIOThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
MOZ_RELEASE_ASSERT(quotaManager);
|
|
|
|
return quotaManager->GetThumbnailPrivateIdentityId();
|
|
});
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetOriginMetadata(""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
|
|
"http://www.mozilla.org"_ns),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
|
|
"http://www.mozilla.com"_ns),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
if (createThumbnailPrivateIdentityOrigins) {
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.org"_ns, "http://www.mozilla.org"_ns),
|
|
/* aCreateIfNonExistent */ true));
|
|
|
|
ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
|
|
GetOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.com"_ns, "http://www.mozilla.com"_ns),
|
|
/* aCreateIfNonExistent */ true));
|
|
}
|
|
|
|
if (!keepTemporaryStorageInitialized) {
|
|
ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
|
|
}
|
|
|
|
const auto iterationsBefore = TotalDirectoryIterations();
|
|
|
|
ClearStoragesForOriginAttributesPattern(nsFmtString(
|
|
FMT_STRING(u"{{ \"userContextId\": {} }}"), thumbnailPrivateIdentityId));
|
|
|
|
const auto iterationsAfter = TotalDirectoryIterations();
|
|
|
|
const auto iterations = iterationsAfter - iterationsBefore;
|
|
|
|
uint64_t expectedIterations = createThumbnailPrivateIdentityOrigins ? 5u
|
|
: !keepTemporaryStorageInitialized ? 3u
|
|
: 0u;
|
|
ASSERT_EQ(iterations, expectedIterations);
|
|
|
|
const auto matchesUserContextId =
|
|
[thumbnailPrivateIdentityId](const auto& origin) {
|
|
return FindInReadable(nsFmtCString(FMT_STRING("userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
origin);
|
|
};
|
|
|
|
const auto origins = ListOrigins();
|
|
|
|
const bool anyOriginsMatch =
|
|
std::any_of(origins.cbegin(), origins.cend(), matchesUserContextId);
|
|
ASSERT_FALSE(anyOriginsMatch);
|
|
|
|
const auto cachedOrigins = ListCachedOrigins();
|
|
|
|
const bool anyCachedOriginsMatch = std::any_of(
|
|
cachedOrigins.cbegin(), cachedOrigins.cend(), matchesUserContextId);
|
|
ASSERT_FALSE(anyCachedOriginsMatch);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
, TestQuotaManagerAndClearStorageWithBoolPair,
|
|
testing::Values(
|
|
std::make_pair(/* createThumbnailPrivateIdentityOrigins */ true,
|
|
/* keepTemporaryStorageInitialized */ true),
|
|
std::make_pair(/* createThumbnailPrivateIdentityOrigins */ true,
|
|
/* keepTemporaryStorageInitialized */ false),
|
|
std::make_pair(/* createThumbnailPrivateIdentityOrigins */ false,
|
|
/* keepTemporaryStorageInitialized */ true),
|
|
std::make_pair(/* createThumbnailPrivateIdentityOrigins */ false,
|
|
/* keepTemporaryStorageInitialized */ false)),
|
|
[](const testing::TestParamInfo<BoolPairTestParams>& aParam)
|
|
-> std::string {
|
|
const BoolPairTestParams& param = aParam.param;
|
|
|
|
const bool createThumbnailPrivateIdentityOrigins = param.first;
|
|
const bool keepTemporaryStorageInitialized = param.second;
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << (createThumbnailPrivateIdentityOrigins
|
|
? "CreateThumbnailPrivateIdentityOrigins"
|
|
: "NoThumbnailPrivateIdentityOrigins")
|
|
<< "_"
|
|
<< (keepTemporaryStorageInitialized ? "KeepTemporaryStorageInitialized"
|
|
: "ShutdownTemporaryStorage");
|
|
|
|
return ss.str();
|
|
});
|
|
|
|
TEST_F(TestQuotaManagerAndShutdownFixture,
|
|
ThumbnailPrivateIdentityTemporaryOriginCount) {
|
|
PerformOnIOThread([]() {
|
|
QuotaManager* quotaManager = QuotaManager::Get();
|
|
ASSERT_TRUE(quotaManager);
|
|
|
|
const uint32_t thumbnailPrivateIdentityId =
|
|
quotaManager->GetThumbnailPrivateIdentityId();
|
|
|
|
{
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(GetFullOriginMetadata(
|
|
""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
|
|
"http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
|
|
"http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
1u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.com"_ns, "http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
2u);
|
|
|
|
quotaManager->RemoveTemporaryOrigin(GetFullOriginMetadata(
|
|
""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
2u);
|
|
|
|
quotaManager->RemoveTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
|
|
"http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
2u);
|
|
|
|
quotaManager->RemoveTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
|
|
"http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
2u);
|
|
|
|
quotaManager->RemoveTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
1u);
|
|
|
|
quotaManager->RemoveTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.com"_ns, "http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
}
|
|
|
|
{
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(GetFullOriginMetadata(
|
|
""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
|
|
"http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
|
|
"http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
1u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.com"_ns, "http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
2u);
|
|
|
|
quotaManager->RemoveTemporaryOrigins(PERSISTENCE_TYPE_TEMPORARY);
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
2u);
|
|
|
|
quotaManager->RemoveTemporaryOrigins(PERSISTENCE_TYPE_DEFAULT);
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
}
|
|
|
|
{
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(GetFullOriginMetadata(
|
|
""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
|
|
"http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
|
|
"http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.org"_ns, "http://www.mozilla.org"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
1u);
|
|
|
|
quotaManager->AddTemporaryOrigin(
|
|
GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
|
|
thumbnailPrivateIdentityId),
|
|
"mozilla.com"_ns, "http://www.mozilla.com"_ns));
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
2u);
|
|
|
|
quotaManager->RemoveTemporaryOrigins();
|
|
ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
|
|
0u);
|
|
}
|
|
});
|
|
}
|
|
|
|
} // namespace mozilla::dom::quota::test
|