Bug 1919555 - LSNG: Convert PBackgroundLSDatabase to a top level actor; r=dom-storage-reviewers,asuth

The conversion will allow:
- returning an endpoint instead of a datastore id when datastore preparation is
  done
- binding the child actor to a different event target

Long term, it would be possible to bind the parent actor to a dedicated task
queue or existing LS thread, helping to relieve the PBackground thread.

Differential Revision: https://phabricator.services.mozilla.com/D222417
This commit is contained in:
Jan Varga
2024-10-03 11:26:38 +00:00
parent 202f4356a5
commit 8e03593460
10 changed files with 99 additions and 61 deletions

View File

@@ -38,14 +38,14 @@ LSDatabaseChild::~LSDatabaseChild() {
MOZ_COUNT_DTOR(LSDatabaseChild);
}
void LSDatabaseChild::SendDelete() {
void LSDatabaseChild::Shutdown() {
AssertIsOnOwningThread();
if (mDatabase) {
mDatabase->ClearActor();
mDatabase = nullptr;
MOZ_ALWAYS_TRUE(PBackgroundLSDatabaseChild::Send__delete__(this));
Close();
}
}

View File

@@ -45,16 +45,16 @@ class LSSnapshot;
* Most of the interesting bits happen via PBackgroundLSSnapshot.
*
* Mutual raw pointers are maintained between LSDatabase and this class that are
* cleared at either (expected) when the child starts the deletion process
* (SendDelete) or unexpected actor death (ActorDestroy).
* cleared at either (expected) when the child starts the shutdown process
* (Shutdown) or unexpected actor death (ActorDestroy).
*
* See `PBackgroundLSDatabase.ipdl` for more information.
*
*
* ## Low-Level Lifecycle ##
* - Created by LSObject::EnsureDatabase if it had to create a database.
* - Deletion begun by LSDatabase's destructor invoking SendDelete which sends
* __delete__ which destroys the actor.
* - Shutdown begun by LSDatabase's destructor invoking Shutdown which destroys
* the actor.
*/
class LSDatabaseChild final : public PBackgroundLSDatabaseChild {
friend class mozilla::ipc::BackgroundChildImpl;
@@ -76,7 +76,7 @@ class LSDatabaseChild final : public PBackgroundLSDatabaseChild {
~LSDatabaseChild();
void SendDelete();
void Shutdown();
// IPDL methods are only called by IPDL.
void ActorDestroy(ActorDestroyReason aWhy) override;

View File

@@ -2791,6 +2791,10 @@ using PrivateDatastoreHashtable =
// window actually goes away.
UniquePtr<PrivateDatastoreHashtable> gPrivateDatastores;
using DatabaseArray = nsTArray<Database*>;
StaticAutoPtr<DatabaseArray> gDatabases;
using LiveDatabaseArray = nsTArray<NotNull<CheckedUnsafePtr<Database>>>;
StaticAutoPtr<LiveDatabaseArray> gLiveDatabases;
@@ -3202,6 +3206,8 @@ void InitializeLocalStorage() {
#endif
}
namespace {
already_AddRefed<PBackgroundLSDatabaseParent> AllocPBackgroundLSDatabaseParent(
const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId,
const uint64_t& aDatastoreId) {
@@ -3225,14 +3231,14 @@ already_AddRefed<PBackgroundLSDatabaseParent> AllocPBackgroundLSDatabaseParent(
// If we ever decide to return null from this point on, we need to make sure
// that the datastore is closed and the prepared datastore is removed from the
// gPreparedDatastores hashtable.
// We also assume that IPDL must call RecvPBackgroundLSDatabaseConstructor
// once we return a valid actor in this method.
// We also assume that RecvCreateBackgroundLSDatabaseParent must call
// RecvPBackgroundLSDatabaseConstructor once we return a valid actor in this
// method.
RefPtr<Database> database =
new Database(aPrincipalInfo, preparedDatastore->GetContentParentId(),
preparedDatastore->Origin(), aPrivateBrowsingId);
// Transfer ownership to IPDL.
return database.forget();
}
@@ -3246,8 +3252,8 @@ bool RecvPBackgroundLSDatabaseConstructor(PBackgroundLSDatabaseParent* aActor,
MOZ_ASSERT(gPreparedDatastores->Get(aDatastoreId));
MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread());
// The actor is now completely built (it has a manager, channel and it's
// registered as a subprotocol).
// The actor is now completely built (it has a channel and it's registered
// as a top level protocol).
// ActorDestroy will be called if we fail here.
mozilla::UniquePtr<PreparedDatastore> preparedDatastore;
@@ -3268,6 +3274,25 @@ bool RecvPBackgroundLSDatabaseConstructor(PBackgroundLSDatabaseParent* aActor,
return true;
}
} // namespace
bool RecvCreateBackgroundLSDatabaseParent(
const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId,
const uint64_t& aDatastoreId,
Endpoint<PBackgroundLSDatabaseParent>&& aParentEndpoint) {
RefPtr<PBackgroundLSDatabaseParent> parent = AllocPBackgroundLSDatabaseParent(
aPrincipalInfo, aPrivateBrowsingId, aDatastoreId);
if (!parent) {
return false;
}
// Transfer ownership to IPDL.
MOZ_ALWAYS_TRUE(aParentEndpoint.Bind(parent));
return RecvPBackgroundLSDatabaseConstructor(parent, aPrincipalInfo,
aPrivateBrowsingId, aDatastoreId);
}
PBackgroundLSObserverParent* AllocPBackgroundLSObserverParent(
const uint64_t& aObserverId) {
AssertIsOnBackgroundThread();
@@ -5305,12 +5330,25 @@ Database::Database(const PrincipalInfo& aPrincipalInfo,
#endif
{
AssertIsOnOwningThread();
if (!gDatabases) {
gDatabases = new DatabaseArray();
}
gDatabases->AppendElement(this);
}
Database::~Database() {
AssertIsOnOwningThread();
MOZ_ASSERT_IF(mActorWasAlive, mAllowedToClose);
MOZ_ASSERT_IF(mActorWasAlive, mActorDestroyed);
MOZ_ASSERT(gDatabases);
gDatabases->RemoveElement(this);
if (gDatabases->IsEmpty()) {
gDatabases = nullptr;
}
}
void Database::SetActorAlive(Datastore* aDatastore) {
@@ -5387,7 +5425,7 @@ void Database::ForceKill() {
return;
}
Unused << PBackgroundLSDatabaseParent::Send__delete__(this);
Close();
}
void Database::Stringify(nsACString& aResult) const {
@@ -5398,7 +5436,7 @@ void Database::Stringify(nsACString& aResult) const {
aResult.Append(kQuotaGenericDelimiter);
aResult.AppendLiteral("OtherProcessActor:");
aResult.AppendInt(BackgroundParent::IsOtherProcessActor(Manager()));
aResult.AppendInt(mContentParentId.isSome());
aResult.Append(kQuotaGenericDelimiter);
aResult.AppendLiteral("Origin:");
@@ -8859,6 +8897,18 @@ void QuotaClient::FinalizeShutdown() {
gConnectionThread = nullptr;
}
if (gDatabases) {
nsTArray<RefPtr<Database>> databases;
for (const auto& database : *gDatabases) {
databases.AppendElement(database);
}
for (const auto& database : databases) {
database->Close();
}
}
}
Result<UniquePtr<ArchivedOriginScope>, nsresult>

View File

@@ -14,6 +14,8 @@ namespace mozilla {
namespace ipc {
template <class T>
class Endpoint;
class PBackgroundParent;
class PrincipalInfo;
@@ -36,14 +38,10 @@ class Client;
void InitializeLocalStorage();
already_AddRefed<PBackgroundLSDatabaseParent> AllocPBackgroundLSDatabaseParent(
bool RecvCreateBackgroundLSDatabaseParent(
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const uint32_t& aPrivateBrowsingId, const uint64_t& aDatastoreId);
bool RecvPBackgroundLSDatabaseConstructor(
PBackgroundLSDatabaseParent* aActor,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const uint32_t& aPrivateBrowsingId, const uint64_t& aDatastoreId);
const uint32_t& aPrivateBrowsingId, const uint64_t& aDatastoreId,
mozilla::ipc::Endpoint<PBackgroundLSDatabaseParent>&& aParentEndpoint);
PBackgroundLSObserverParent* AllocPBackgroundLSObserverParent(
const uint64_t& aObserverId);

View File

@@ -98,8 +98,8 @@ LSDatabase::~LSDatabase() {
}
if (mActor) {
mActor->SendDelete();
MOZ_ASSERT(!mActor, "SendDelete should have cleared!");
mActor->Shutdown();
MOZ_ASSERT(!mActor, "Shutdown should have cleared!");
}
}

View File

@@ -938,8 +938,16 @@ nsresult LSObject::EnsureDatabase() {
RefPtr<LSDatabaseChild> actor = new LSDatabaseChild(database);
MOZ_ALWAYS_TRUE(backgroundActor->SendPBackgroundLSDatabaseConstructor(
actor, *mStoragePrincipalInfo, mPrivateBrowsingId, datastoreId));
mozilla::ipc::Endpoint<PBackgroundLSDatabaseParent> parentEndpoint;
mozilla::ipc::Endpoint<PBackgroundLSDatabaseChild> childEndpoint;
MOZ_ALWAYS_SUCCEEDS(
PBackgroundLSDatabase::CreateEndpoints(&parentEndpoint, &childEndpoint));
MOZ_ALWAYS_TRUE(childEndpoint.Bind(actor));
MOZ_ALWAYS_TRUE(backgroundActor->SendCreateBackgroundLSDatabaseParent(
*mStoragePrincipalInfo, mPrivateBrowsingId, datastoreId,
std::move(parentEndpoint)));
database->SetActor(actor);

View File

@@ -2,7 +2,6 @@
* 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 protocol PBackground;
include protocol PBackgroundLSSnapshot;
include PBackgroundLSSharedTypes;
@@ -92,10 +91,9 @@ struct LSSnapshotInitInfo
* ContentParent::AboutToLoadHttpDocumentForChild, the central place
* for pre-loading.)
*/
[ChildImpl=virtual, ParentImpl=virtual]
[ChildImpl=virtual, ParentImpl=virtual, ChildProc=anydom]
sync protocol PBackgroundLSDatabase
{
manager PBackground;
manages PBackgroundLSSnapshot;
parent:
@@ -153,9 +151,6 @@ child:
* ContentParent::ShutDownProcess.
*/
async RequestAllowToClose();
both:
async __delete__();
};
} // namespace dom

View File

@@ -274,29 +274,20 @@ BackgroundParentImpl::RecvPBackgroundSDBConnectionConstructor(
return IPC_OK();
}
already_AddRefed<BackgroundParentImpl::PBackgroundLSDatabaseParent>
BackgroundParentImpl::AllocPBackgroundLSDatabaseParent(
const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId,
const uint64_t& aDatastoreId) {
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
return mozilla::dom::AllocPBackgroundLSDatabaseParent(
aPrincipalInfo, aPrivateBrowsingId, aDatastoreId);
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPBackgroundLSDatabaseConstructor(
PBackgroundLSDatabaseParent* aActor, const PrincipalInfo& aPrincipalInfo,
const uint32_t& aPrivateBrowsingId, const uint64_t& aDatastoreId) {
BackgroundParentImpl::RecvCreateBackgroundLSDatabaseParent(
const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId,
const uint64_t& aDatastoreId,
Endpoint<PBackgroundLSDatabaseParent>&& aParentEndpoint) {
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
if (!mozilla::dom::RecvPBackgroundLSDatabaseConstructor(
aActor, aPrincipalInfo, aPrivateBrowsingId, aDatastoreId)) {
if (!mozilla::dom::RecvCreateBackgroundLSDatabaseParent(
aPrincipalInfo, aPrivateBrowsingId, aDatastoreId,
std::move(aParentEndpoint))) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}

View File

@@ -56,15 +56,10 @@ class BackgroundParentImpl : public PBackgroundParent {
const PersistenceType& aPersistenceType,
const PrincipalInfo& aPrincipalInfo) override;
already_AddRefed<PBackgroundLSDatabaseParent>
AllocPBackgroundLSDatabaseParent(const PrincipalInfo& aPrincipalInfo,
const uint32_t& aPrivateBrowsingId,
const uint64_t& aDatastoreId) override;
mozilla::ipc::IPCResult RecvPBackgroundLSDatabaseConstructor(
PBackgroundLSDatabaseParent* aActor, const PrincipalInfo& aPrincipalInfo,
const uint32_t& aPrivateBrowsingId,
const uint64_t& aDatastoreId) override;
mozilla::ipc::IPCResult RecvCreateBackgroundLSDatabaseParent(
const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId,
const uint64_t& aDatastoreId,
Endpoint<PBackgroundLSDatabaseParent>&& aParentEndpoint) override;
PBackgroundLSObserverParent* AllocPBackgroundLSObserverParent(
const uint64_t& aObserverId) override;

View File

@@ -86,7 +86,6 @@ sync protocol PBackground
manages PBackgroundIDBFactory;
manages PBackgroundIndexedDBUtils;
manages PBackgroundSDBConnection;
manages PBackgroundLSDatabase;
manages PBackgroundLSObserver;
manages PBackgroundLSRequest;
manages PBackgroundLSSimpleRequest;
@@ -139,9 +138,11 @@ parent:
async PBackgroundSDBConnection(PersistenceType persistenceType,
PrincipalInfo principalInfo);
async PBackgroundLSDatabase(PrincipalInfo principalInfo,
uint32_t privateBrowsingId,
uint64_t datastoreId);
async CreateBackgroundLSDatabaseParent(
PrincipalInfo principalInfo,
uint32_t privateBrowsingId,
uint64_t datastoreId,
Endpoint<PBackgroundLSDatabaseParent> aParentEndpoint);
async PBackgroundLSObserver(uint64_t observerId);