Bug 1525887 - Add set of ContentParent subscribed to BrowsingContextGroup. r=nika

Add the origin ContentParent to a CanonicalBrowsingContext's group
when a CanonicalBrowsingContext is created from IPC. With this it is
possible to keep track of all child processes associated with a
BrowsingContextGroup.

Differential Revision: https://phabricator.services.mozilla.com/D19004

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andreas Farre 2019-02-14 08:55:22 +00:00
parent f26917afec
commit 4a8d21430f
8 changed files with 54 additions and 56 deletions

View File

@ -148,6 +148,8 @@ CanonicalBrowsingContext* BrowsingContext::Canonical() {
if (XRE_IsParentProcess()) {
context = new CanonicalBrowsingContext(
aParent, aOpener, aName, aId, aOriginProcess->ChildID(), Type::Content);
context->Group()->Subscribe(aOriginProcess);
} else {
context = new BrowsingContext(aParent, aOpener, aName, aId, Type::Content);
}

View File

@ -11,35 +11,36 @@
namespace mozilla {
namespace dom {
StaticAutoPtr<nsTArray<RefPtr<BrowsingContextGroup>>>
BrowsingContextGroup::sAllGroups;
/* static */ void BrowsingContextGroup::Init() {
if (!sAllGroups) {
sAllGroups = new nsTArray<RefPtr<BrowsingContextGroup>>();
ClearOnShutdown(&sAllGroups);
}
}
bool BrowsingContextGroup::Contains(BrowsingContext* aBrowsingContext) {
return aBrowsingContext->Group() == this;
}
void BrowsingContextGroup::Register(BrowsingContext* aBrowsingContext) {
MOZ_DIAGNOSTIC_ASSERT(aBrowsingContext);
mContexts.PutEntry(aBrowsingContext);
}
void BrowsingContextGroup::Unregister(BrowsingContext* aBrowsingContext) {
MOZ_DIAGNOSTIC_ASSERT(aBrowsingContext);
mContexts.RemoveEntry(aBrowsingContext);
}
BrowsingContextGroup::BrowsingContextGroup() {
sAllGroups->AppendElement(this);
void BrowsingContextGroup::Subscribe(ContentParent* aOriginProcess) {
MOZ_DIAGNOSTIC_ASSERT(aOriginProcess);
mSubscribers.PutEntry(aOriginProcess);
aOriginProcess->OnBrowsingContextGroupSubscribe(this);
}
void BrowsingContextGroup::Unsubscribe(ContentParent* aOriginProcess) {
MOZ_DIAGNOSTIC_ASSERT(aOriginProcess);
mSubscribers.RemoveEntry(aOriginProcess);
aOriginProcess->OnBrowsingContextGroupUnsubscribe(this);
}
BrowsingContextGroup::~BrowsingContextGroup() {
if (sAllGroups) {
sAllGroups->RemoveElement(this);
for (auto iter = mSubscribers.Iter(); !iter.Done(); iter.Next()) {
nsRefPtrHashKey<ContentParent>* entry = iter.Get();
entry->GetKey()->OnBrowsingContextGroupUnsubscribe(this);
}
}
@ -52,20 +53,8 @@ JSObject* BrowsingContextGroup::WrapObject(JSContext* aCx,
return BrowsingContextGroup_Binding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContextGroup)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContextGroup)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContexts)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mToplevels)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowsingContextGroup)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContexts)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToplevels)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BrowsingContextGroup)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BrowsingContextGroup, mContexts,
mToplevels, mSubscribers)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowsingContextGroup, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(BrowsingContextGroup, Release)

View File

@ -8,6 +8,7 @@
#define mozilla_dom_BrowsingContextGroup_h
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/StaticPtr.h"
#include "nsHashKeys.h"
#include "nsTArray.h"
@ -31,13 +32,19 @@ class BrowsingContextGroup final : public nsWrapperCache {
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(BrowsingContextGroup)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(BrowsingContextGroup)
static void Init();
typedef nsTHashtable<nsRefPtrHashKey<ContentParent>> ContentParents;
// Interact with the list of BrowsingContexts.
bool Contains(BrowsingContext* aContext);
void Register(BrowsingContext* aContext);
void Unregister(BrowsingContext* aContext);
// Interact with the list of ContentParents
void Subscribe(ContentParent* aOriginProcess);
void Unsubscribe(ContentParent* aOriginProcess);
ContentParents::Iterator ContentParentsIter() { return mSubscribers.Iter(); }
// Get a reference to the list of toplevel contexts in this
// BrowsingContextGroup.
BrowsingContext::Children& Toplevels() { return mToplevels; }
@ -49,15 +56,13 @@ class BrowsingContextGroup final : public nsWrapperCache {
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
BrowsingContextGroup();
BrowsingContextGroup() = default;
private:
friend class CanonicalBrowsingContext;
~BrowsingContextGroup();
static StaticAutoPtr<nsTArray<RefPtr<BrowsingContextGroup>>> sAllGroups;
// A BrowsingContextGroup contains a series of BrowsingContext objects. They
// are addressed using a hashtable to avoid linear lookup when adding or
// removing elements from the set.
@ -65,6 +70,8 @@ class BrowsingContextGroup final : public nsWrapperCache {
// The set of toplevel browsing contexts in the current BrowsingContextGroup.
BrowsingContext::Children mToplevels;
ContentParents mSubscribers;
};
} // namespace dom

View File

@ -30,27 +30,6 @@ CanonicalBrowsingContext::CanonicalBrowsingContext(BrowsingContext* aParent,
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
}
// TODO(farre): CanonicalBrowsingContext::CleanupContexts starts from the
// list of root BrowsingContexts. This isn't enough when separate
// BrowsingContext nodes of a BrowsingContext tree, not in a crashing
// child process, are from that process and thus needs to be
// cleaned. [Bug 1472108]
/* static */ void CanonicalBrowsingContext::CleanupContexts(
uint64_t aProcessId) {
nsTArray<RefPtr<BrowsingContext>> contexts;
for (auto& group : *BrowsingContextGroup::sAllGroups) {
for (auto& context : group->Toplevels()) {
if (Cast(context)->IsOwnedByProcess(aProcessId)) {
contexts.AppendElement(context);
}
}
}
for (auto& context : contexts) {
context->Detach();
}
}
/* static */ already_AddRefed<CanonicalBrowsingContext>
CanonicalBrowsingContext::Get(uint64_t aId) {
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());

View File

@ -26,7 +26,6 @@ class WindowGlobalParent;
// parent needs.
class CanonicalBrowsingContext final : public BrowsingContext {
public:
static void CleanupContexts(uint64_t aProcessId);
static already_AddRefed<CanonicalBrowsingContext> Get(uint64_t aId);
static CanonicalBrowsingContext* Cast(BrowsingContext* aContext);
static const CanonicalBrowsingContext* Cast(const BrowsingContext* aContext);

View File

@ -16,7 +16,6 @@ namespace mozilla {
// The one time initialization for this module
nsresult InitDocShellModule() {
mozilla::dom::BrowsingContext::Init();
mozilla::dom::BrowsingContextGroup::Init();
nsresult rv = nsSHistory::Startup();
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -39,6 +39,7 @@
#include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientOpenWindowOpActors.h"
@ -1743,7 +1744,12 @@ void ContentParent::ActorDestroy(ActorDestroyReason why) {
a11y::AccessibleWrap::ReleaseContentProcessIdFor(ChildID());
#endif
CanonicalBrowsingContext::CleanupContexts(ChildID());
for (auto iter = mGroups.Iter(); !iter.Done(); iter.Next()) {
nsRefPtrHashKey<mozilla::dom::BrowsingContextGroup>* entry = iter.Get();
entry->GetKey()->Unsubscribe(this);
}
MOZ_DIAGNOSTIC_ASSERT(mGroups.IsEmpty());
}
bool ContentParent::TryToRecycle() {
@ -5820,6 +5826,16 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowPostMessage(
return IPC_OK();
}
void ContentParent::OnBrowsingContextGroupSubscribe(BrowsingContextGroup* aGroup) {
MOZ_DIAGNOSTIC_ASSERT(aGroup);
mGroups.PutEntry(aGroup);
}
void ContentParent::OnBrowsingContextGroupUnsubscribe(BrowsingContextGroup* aGroup) {
MOZ_DIAGNOSTIC_ASSERT(aGroup);
mGroups.RemoveEntry(aGroup);
}
} // namespace dom
} // namespace mozilla

View File

@ -96,6 +96,7 @@ struct TextureFactoryIdentifier;
namespace dom {
class BrowsingContextGroup;
class Element;
class TabParent;
class ClonedMessageData;
@ -122,6 +123,7 @@ class ContentParent final : public PContentParent,
typedef mozilla::ipc::URIParams URIParams;
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
typedef mozilla::dom::BrowsingContextGroup BrowsingContextGroup;
friend class mozilla::PreallocatedProcessManagerImpl;
friend class PContentParent;
@ -1191,6 +1193,9 @@ class ContentParent final : public PContentParent,
return mRecordReplayState != eNotRecordingOrReplaying;
}
void OnBrowsingContextGroupSubscribe(BrowsingContextGroup* aGroup);
void OnBrowsingContextGroupUnsubscribe(BrowsingContextGroup* aGroup);
private:
// Released in ActorDestroy; deliberately not exposed to the CC.
RefPtr<ContentParent> mSelfRef;
@ -1326,6 +1331,8 @@ class ContentParent final : public PContentParent,
// for the SetProcessSandbox IPDL message.
static bool sEarlySandboxInit;
#endif
nsTHashtable<nsRefPtrHashKey<BrowsingContextGroup>> mGroups;
};
} // namespace dom