Bug 1962126 - QM: Add support for initializing corresponding client in OpenClientDirectory; r=dom-storage-reviewers,jstutte

Adds support for client initialization in QuotaManager::OpenClientDirectory.
This ensures that client directories are properly ensured as part of the
OpenClientDirectory flow.

Some xpcshell tests were updated to install profiles with pre-created origin
directories and data. This is necessary because OpenClientDirectory now fails
when called for LSNG preloading if the corresponding origin has not yet been
initialized, due to the addition of client initialization.

This change completes the work for integrating client initialization into
OpenClientDirectory, and may enable future optimization, such as avoiding the
need for clients to hop to the QuotaManager I/O thread after the promise
returned by OpenClientDirectory is resolved.

Differential Revision: https://phabricator.services.mozilla.com/D246574
This commit is contained in:
Jan Varga
2025-05-16 17:52:07 +00:00
committed by jvarga@mozilla.com
parent d39d6950b9
commit d54e57ba4a
4 changed files with 79 additions and 14 deletions

View File

@@ -6,6 +6,9 @@
const { PrincipalUtils } = ChromeUtils.importESModule(
"resource://testing-common/dom/quota/test/modules/PrincipalUtils.sys.mjs"
);
const { QuotaUtils } = ChromeUtils.importESModule(
"resource://testing-common/dom/quota/test/modules/QuotaUtils.sys.mjs"
);
const { TestUtils } = ChromeUtils.importESModule(
"resource://testing-common/TestUtils.sys.mjs"
);
@@ -13,6 +16,17 @@ const { TestUtils } = ChromeUtils.importESModule(
add_task(async function testSteps() {
const principal = PrincipalUtils.createPrincipal("https://example.com");
info("Clearing");
{
const request = Services.qms.clear();
await QuotaUtils.requestFinished(request);
}
info("Installing package");
installPackage("somedata_profile");
info("Starting database opening");
const openPromise = Services.domStorageManager.preload(principal);

View File

@@ -6,6 +6,9 @@
const { PrincipalUtils } = ChromeUtils.importESModule(
"resource://testing-common/dom/quota/test/modules/PrincipalUtils.sys.mjs"
);
const { QuotaUtils } = ChromeUtils.importESModule(
"resource://testing-common/dom/quota/test/modules/QuotaUtils.sys.mjs"
);
const { TestUtils } = ChromeUtils.importESModule(
"resource://testing-common/TestUtils.sys.mjs"
);
@@ -13,6 +16,17 @@ const { TestUtils } = ChromeUtils.importESModule(
add_task(async function testSteps() {
const principal = PrincipalUtils.createPrincipal("https://example.com");
info("Clearing");
{
const request = Services.qms.clear();
await QuotaUtils.requestFinished(request);
}
info("Installing package");
installPackage("somedata_profile");
info("Starting database opening");
const openPromise = Services.domStorageManager.preload(principal);

View File

@@ -5558,6 +5558,15 @@ QuotaManager::OpenClientDirectory(
MakeBackInserter(promises));
}
RefPtr<UniversalDirectoryLock> clientInitDirectoryLock =
CreateDirectoryLockInternal(
PersistenceScope::CreateFromValue(aClientMetadata.mPersistenceType),
OriginScope::FromOrigin(aClientMetadata),
ClientStorageScope::CreateFromClient(aClientMetadata.mClientType),
/* aExclusive */ false);
promises.AppendElement(clientInitDirectoryLock->Acquire());
RefPtr<ClientDirectoryLock> clientDirectoryLock =
CreateDirectoryLock(aClientMetadata, /* aExclusive */ false);
@@ -5608,6 +5617,23 @@ QuotaManager::OpenClientDirectory(
aClientMetadata, aCreateIfNonExistent,
std::move(originDirectoryLock));
}))
->Then(
GetCurrentSerialEventTarget(), __func__,
MaybeInitialize(
std::move(clientInitDirectoryLock),
[self = RefPtr(this), aClientMetadata,
aCreateIfNonExistent](RefPtr<UniversalDirectoryLock>
clientInitDirectoryLock) mutable {
if (aClientMetadata.mPersistenceType ==
PERSISTENCE_TYPE_PERSISTENT) {
return self->InitializePersistentClient(
aClientMetadata, std::move(clientInitDirectoryLock));
}
return self->InitializeTemporaryClient(
aClientMetadata, aCreateIfNonExistent,
std::move(clientInitDirectoryLock));
}))
->Then(
GetCurrentSerialEventTarget(), __func__,
[clientDirectoryLock = std::move(clientDirectoryLock)](

View File

@@ -1178,7 +1178,7 @@ TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
auto backgroundTest = [](bool aInitializeOrigin) {
PerformOnBackgroundThread([]() {
QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager);
@@ -1186,7 +1186,8 @@ TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
RefPtr<BoolPromise> promise =
quotaManager
->OpenClientDirectory(GetTestClientMetadata(), aInitializeOrigin)
->OpenClientDirectory(GetTestClientMetadata(),
/* aInitializeOrigin */ true)
->Then(GetCurrentSerialEventTarget(), __func__,
[&directoryLockHandle](
QuotaManager::ClientDirectoryLockHandlePromise::
@@ -1203,21 +1204,19 @@ TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
return BoolPromise::CreateAndResolve(true, __func__);
})
->Then(quotaManager->IOThread(), __func__,
[aInitializeOrigin](
const BoolPromise::ResolveOrRejectValue& aValue) {
[](const BoolPromise::ResolveOrRejectValue& aValue) {
if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(),
__func__);
}
[aInitializeOrigin]() {
[]() {
QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager);
ASSERT_EQ(
ASSERT_TRUE(
quotaManager->IsTemporaryOriginInitializedInternal(
GetTestOriginMetadata()),
aInitializeOrigin);
GetTestOriginMetadata()));
}();
return BoolPromise::CreateAndResolve(true, __func__);
@@ -1243,17 +1242,29 @@ TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
ASSERT_TRUE(value.IsResolve());
ASSERT_TRUE(value.ResolveValue());
}
};
ASSERT_NO_FATAL_FAILURE(
PerformOnBackgroundThread(backgroundTest, /* aInitializeOrigin */ true));
});
ASSERT_NO_FATAL_FAILURE(
AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
ASSERT_NO_FATAL_FAILURE(ClearStoragesForOrigin(GetTestOriginMetadata()));
ASSERT_NO_FATAL_FAILURE(
PerformOnBackgroundThread(backgroundTest, /* aInitializeOrigin */ false));
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()));