Bug 1599579 - Part 1: Add the ability to specify a specific BrowsingContextGroup during process switch, r=kmag

Differential Revision: https://phabricator.services.mozilla.com/D80254
This commit is contained in:
Nika Layzell 2020-07-06 20:10:43 +00:00
parent 99012368cc
commit cafcceeb34
11 changed files with 72 additions and 40 deletions

View File

@ -189,7 +189,7 @@ bool BrowsingContext::SameOriginWithTop() {
/* static */
already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached(
nsGlobalWindowInner* aParent, BrowsingContext* aOpener,
const nsAString& aName, Type aType) {
BrowsingContextGroup* aSpecificGroup, const nsAString& aName, Type aType) {
if (aParent) {
MOZ_DIAGNOSTIC_ASSERT(aParent->GetWindowContext());
MOZ_DIAGNOSTIC_ASSERT(aParent->GetBrowsingContext()->mType == aType);
@ -210,10 +210,13 @@ already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached(
aParent ? aParent->GetWindowContext() : nullptr;
// Determine which BrowsingContextGroup this context should be created in.
RefPtr<BrowsingContextGroup> group =
(aType == Type::Chrome)
? do_AddRef(BrowsingContextGroup::GetChromeGroup())
: BrowsingContextGroup::Select(parentWC, aOpener);
RefPtr<BrowsingContextGroup> group = aSpecificGroup;
if (aType == Type::Chrome) {
MOZ_DIAGNOSTIC_ASSERT(!group);
group = BrowsingContextGroup::GetChromeGroup();
} else if (!group) {
group = BrowsingContextGroup::Select(parentWC, aOpener);
}
RefPtr<BrowsingContext> context;
if (XRE_IsParentProcess()) {
@ -339,7 +342,7 @@ already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached(
already_AddRefed<BrowsingContext> BrowsingContext::CreateIndependent(
Type aType) {
RefPtr<BrowsingContext> bc(
CreateDetached(nullptr, nullptr, EmptyString(), aType));
CreateDetached(nullptr, nullptr, nullptr, EmptyString(), aType));
bc->mWindowless = bc->IsContent();
bc->mEmbeddedByThisProcess = true;
bc->EnsureAttached();

View File

@ -209,7 +209,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// DocShell, BrowserParent, or BrowserBridgeChild.
static already_AddRefed<BrowsingContext> CreateDetached(
nsGlobalWindowInner* aParent, BrowsingContext* aOpener,
const nsAString& aName, Type aType);
BrowsingContextGroup* aSpecificGroup, const nsAString& aName, Type aType);
void EnsureAttached();

View File

@ -617,11 +617,16 @@ void CanonicalBrowsingContext::PendingRemotenessChange::Finish() {
mContentParent ? u"true"_ns : u"false"_ns,
/* notify */ true);
RefPtr<BrowsingContextGroup> specificGroup;
if (mSpecificGroupId != 0) {
specificGroup = BrowsingContextGroup::GetOrCreate(mSpecificGroupId);
}
// The process has been created, hand off to nsFrameLoaderOwner to finish
// the process switch.
ErrorResult error;
frameLoaderOwner->ChangeRemotenessToProcess(mContentParent,
mReplaceBrowsingContext, error);
frameLoaderOwner->ChangeRemotenessToProcess(
mContentParent, mReplaceBrowsingContext, specificGroup, error);
if (error.Failed()) {
Cancel(error.StealNSResult());
return;
@ -803,10 +808,12 @@ void CanonicalBrowsingContext::PendingRemotenessChange::Clear() {
CanonicalBrowsingContext::PendingRemotenessChange::PendingRemotenessChange(
CanonicalBrowsingContext* aTarget, RemotenessPromise::Private* aPromise,
uint64_t aPendingSwitchId, bool aReplaceBrowsingContext)
uint64_t aPendingSwitchId, bool aReplaceBrowsingContext,
uint64_t aSpecificGroupId)
: mTarget(aTarget),
mPromise(aPromise),
mPendingSwitchId(aPendingSwitchId),
mSpecificGroupId(aSpecificGroupId),
mReplaceBrowsingContext(aReplaceBrowsingContext) {}
CanonicalBrowsingContext::PendingRemotenessChange::~PendingRemotenessChange() {
@ -817,7 +824,8 @@ CanonicalBrowsingContext::PendingRemotenessChange::~PendingRemotenessChange() {
RefPtr<CanonicalBrowsingContext::RemotenessPromise>
CanonicalBrowsingContext::ChangeRemoteness(const nsAString& aRemoteType,
uint64_t aPendingSwitchId,
bool aReplaceBrowsingContext) {
bool aReplaceBrowsingContext,
uint64_t aSpecificGroupId) {
MOZ_DIAGNOSTIC_ASSERT(IsContent(),
"cannot change the process of chrome contexts");
MOZ_DIAGNOSTIC_ASSERT(
@ -825,6 +833,8 @@ CanonicalBrowsingContext::ChangeRemoteness(const nsAString& aRemoteType,
"toplevel content must be embedded in the parent process");
MOZ_DIAGNOSTIC_ASSERT(!aReplaceBrowsingContext || IsTop(),
"Cannot replace BrowsingContext for subframes");
MOZ_DIAGNOSTIC_ASSERT(aSpecificGroupId == 0 || aReplaceBrowsingContext,
"Cannot specify group ID unless replacing BC");
// Ensure our embedder hasn't been destroyed already.
RefPtr<WindowGlobalParent> embedderWindowGlobal = GetEmbedderWindowGlobal();
@ -879,8 +889,9 @@ CanonicalBrowsingContext::ChangeRemoteness(const nsAString& aRemoteType,
// Switching to remote. Wait for new process to launch before switch.
auto promise = MakeRefPtr<RemotenessPromise::Private>(__func__);
RefPtr<PendingRemotenessChange> change = new PendingRemotenessChange(
this, promise, aPendingSwitchId, aReplaceBrowsingContext);
RefPtr<PendingRemotenessChange> change =
new PendingRemotenessChange(this, promise, aPendingSwitchId,
aReplaceBrowsingContext, aSpecificGroupId);
mPendingRemotenessChange = change;
// Call `prepareToChangeRemoteness` in parallel with starting a new process

View File

@ -155,7 +155,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
using RemotenessPromise = MozPromise<RefPtr<BrowserParent>, nsresult, false>;
RefPtr<RemotenessPromise> ChangeRemoteness(const nsAString& aRemoteType,
uint64_t aPendingSwitchId,
bool aReplaceBrowsingContext);
bool aReplaceBrowsingContext,
uint64_t aSpecificGroupId);
// Return a media controller from the top-level browsing context that can
// control all media belonging to this browsing context tree. Return nullptr
@ -218,7 +219,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
PendingRemotenessChange(CanonicalBrowsingContext* aTarget,
RemotenessPromise::Private* aPromise,
uint64_t aPendingSwitchId,
bool aReplaceBrowsingContext);
bool aReplaceBrowsingContext,
uint64_t aSpecificGroupId);
void Cancel(nsresult aRv);
@ -236,6 +238,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
RefPtr<ContentParent> mContentParent;
uint64_t mPendingSwitchId;
uint64_t mSpecificGroupId;
bool mReplaceBrowsingContext;
};

View File

@ -266,7 +266,10 @@ static bool IsTopContent(BrowsingContext* aParent, Element* aOwner) {
}
static already_AddRefed<BrowsingContext> CreateBrowsingContext(
Element* aOwner, nsIOpenWindowInfo* aOpenWindowInfo) {
Element* aOwner, nsIOpenWindowInfo* aOpenWindowInfo,
BrowsingContextGroup* aSpecificGroup) {
MOZ_ASSERT(!aOpenWindowInfo || !aSpecificGroup);
// If we've got a pending BrowserParent from the content process, use the
// BrowsingContext which was created for it.
if (aOpenWindowInfo && aOpenWindowInfo->GetNextRemoteBrowser()) {
@ -305,15 +308,18 @@ static already_AddRefed<BrowsingContext> CreateBrowsingContext(
// for the BrowsingContext, and cause no end of trouble.
if (IsTopContent(parentBC, aOwner)) {
// Create toplevel context without a parent & as Type::Content.
return BrowsingContext::CreateDetached(nullptr, opener, frameName,
return BrowsingContext::CreateDetached(nullptr, opener, aSpecificGroup,
frameName,
BrowsingContext::Type::Content);
}
MOZ_ASSERT(!aOpenWindowInfo,
"Can't have openWindowInfo for non-toplevel context");
return BrowsingContext::CreateDetached(parentInner, nullptr, frameName,
parentBC->GetType());
MOZ_ASSERT(!aSpecificGroup,
"Can't force BrowsingContextGroup for non-toplevel context");
return BrowsingContext::CreateDetached(parentInner, nullptr, nullptr,
frameName, parentBC->GetType());
}
static bool InitialLoadIsRemote(Element* aOwner) {
@ -414,8 +420,8 @@ already_AddRefed<nsFrameLoader> nsFrameLoader::Create(
doc->IsStaticDocument()),
nullptr);
RefPtr<BrowsingContext> context =
CreateBrowsingContext(aOwner, aOpenWindowInfo);
RefPtr<BrowsingContext> context = CreateBrowsingContext(
aOwner, aOpenWindowInfo, /* specificGroup */ nullptr);
NS_ENSURE_TRUE(context, nullptr);
bool isRemoteFrame = InitialLoadIsRemote(aOwner);
@ -430,8 +436,9 @@ already_AddRefed<nsFrameLoader> nsFrameLoader::Create(
/* static */
already_AddRefed<nsFrameLoader> nsFrameLoader::Recreate(
mozilla::dom::Element* aOwner, BrowsingContext* aContext, bool aIsRemote,
bool aNetworkCreated, bool aPreserveContext) {
mozilla::dom::Element* aOwner, BrowsingContext* aContext,
BrowsingContextGroup* aSpecificGroup, bool aIsRemote, bool aNetworkCreated,
bool aPreserveContext) {
NS_ENSURE_TRUE(aOwner, nullptr);
#ifdef DEBUG
@ -445,7 +452,8 @@ already_AddRefed<nsFrameLoader> nsFrameLoader::Recreate(
RefPtr<BrowsingContext> context = aContext;
if (!context || !aPreserveContext) {
context = CreateBrowsingContext(aOwner, /* openWindowInfo */ nullptr);
context = CreateBrowsingContext(aOwner, /* openWindowInfo */ nullptr,
aSpecificGroup);
if (aContext) {
MOZ_ASSERT(
XRE_IsParentProcess(),

View File

@ -99,6 +99,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
typedef mozilla::dom::BrowserParent BrowserParent;
typedef mozilla::dom::BrowserBridgeChild BrowserBridgeChild;
typedef mozilla::dom::BrowsingContext BrowsingContext;
typedef mozilla::dom::BrowsingContextGroup BrowsingContextGroup;
public:
// Called by Frame Elements to create a new FrameLoader.
@ -108,11 +109,9 @@ class nsFrameLoader final : public nsStubMutationObserver,
// Called by nsFrameLoaderOwner::ChangeRemoteness when switching out
// FrameLoaders.
static already_AddRefed<nsFrameLoader> Recreate(Element* aOwner,
BrowsingContext* aContext,
bool aIsRemote,
bool aNetworkCreated,
bool aPreserveContext);
static already_AddRefed<nsFrameLoader> Recreate(
Element* aOwner, BrowsingContext* aContext, BrowsingContextGroup* aGroup,
bool aIsRemote, bool aNetworkCreated, bool aPreserveContext);
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID)

View File

@ -86,8 +86,10 @@ nsFrameLoaderOwner::ShouldPreserveBrowsingContext(
void nsFrameLoaderOwner::ChangeRemotenessCommon(
const ChangeRemotenessContextType& aContextType,
bool aSwitchingInProgressLoad, bool aIsRemote,
bool aSwitchingInProgressLoad, bool aIsRemote, BrowsingContextGroup* aGroup,
std::function<void()>& aFrameLoaderInit, mozilla::ErrorResult& aRv) {
MOZ_ASSERT_IF(aGroup, aContextType != ChangeRemotenessContextType::PRESERVE);
RefPtr<mozilla::dom::BrowsingContext> bc;
bool networkCreated = false;
@ -133,7 +135,7 @@ void nsFrameLoaderOwner::ChangeRemotenessCommon(
}
mFrameLoader = nsFrameLoader::Recreate(
owner, bc, aIsRemote, networkCreated,
owner, bc, aGroup, aIsRemote, networkCreated,
aContextType == ChangeRemotenessContextType::PRESERVE);
if (NS_WARN_IF(!mFrameLoader)) {
aRv.Throw(NS_ERROR_FAILURE);
@ -209,7 +211,7 @@ void nsFrameLoaderOwner::ChangeRemoteness(
auto shouldPreserve = ShouldPreserveBrowsingContext(
isRemote, /* replaceBrowsingContext */ false);
ChangeRemotenessCommon(shouldPreserve, aOptions.mSwitchingInProgressLoad,
isRemote, frameLoaderInit, rv);
isRemote, /* group */ nullptr, frameLoaderInit, rv);
}
void nsFrameLoaderOwner::ChangeRemotenessWithBridge(BrowserBridgeChild* aBridge,
@ -229,13 +231,15 @@ void nsFrameLoaderOwner::ChangeRemotenessWithBridge(BrowserBridgeChild* aBridge,
ChangeRemotenessCommon(ChangeRemotenessContextType::PRESERVE,
/* inProgress */ true,
/* isRemote */ true, frameLoaderInit, rv);
/* isRemote */ true, /* group */ nullptr,
frameLoaderInit, rv);
}
void nsFrameLoaderOwner::ChangeRemotenessToProcess(
ContentParent* aContentParent, bool aReplaceBrowsingContext,
mozilla::ErrorResult& rv) {
BrowsingContextGroup* aGroup, mozilla::ErrorResult& rv) {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT_IF(aGroup, aReplaceBrowsingContext);
bool isRemote = aContentParent != nullptr;
std::function<void()> frameLoaderInit = [&] {
@ -257,7 +261,7 @@ void nsFrameLoaderOwner::ChangeRemotenessToProcess(
auto shouldPreserve =
ShouldPreserveBrowsingContext(isRemote, aReplaceBrowsingContext);
ChangeRemotenessCommon(shouldPreserve, /* inProgress */ true, isRemote,
frameLoaderInit, rv);
aGroup, frameLoaderInit, rv);
}
void nsFrameLoaderOwner::SubframeCrashed() {
@ -285,6 +289,6 @@ void nsFrameLoaderOwner::SubframeCrashed() {
};
ChangeRemotenessCommon(ChangeRemotenessContextType::PRESERVE,
/* inProgress */ false,
/* isRemote */ false, frameLoaderInit, IgnoreErrors());
/* inProgress */ false, /* isRemote */ false,
/* group */ nullptr, frameLoaderInit, IgnoreErrors());
}

View File

@ -70,6 +70,7 @@ class nsFrameLoaderOwner : public nsISupports {
// disabled for this process switch.
void ChangeRemotenessToProcess(mozilla::dom::ContentParent* aContentParent,
bool aReplaceBrowsingContext,
mozilla::dom::BrowsingContextGroup* aGroup,
mozilla::ErrorResult& rv);
void SubframeCrashed();
@ -92,6 +93,7 @@ class nsFrameLoaderOwner : public nsISupports {
void ChangeRemotenessCommon(const ChangeRemotenessContextType& aContextType,
bool aSwitchingInProgressLoad, bool aIsRemote,
mozilla::dom::BrowsingContextGroup* aGroup,
std::function<void()>& aFrameLoaderInit,
mozilla::ErrorResult& aRv);

View File

@ -941,7 +941,7 @@ nsresult ContentChild::ProvideWindowCommon(
}
RefPtr<BrowsingContext> browsingContext = BrowsingContext::CreateDetached(
nullptr, openerBC, aName, BrowsingContext::Type::Content);
nullptr, openerBC, nullptr, aName, BrowsingContext::Type::Content);
MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteTabs(true));
MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteSubframes(useRemoteSubframes));
MOZ_ALWAYS_SUCCEEDS(browsingContext->SetOriginAttributes(

View File

@ -198,8 +198,9 @@ class WindowGlobalParent final : public WindowContext,
nsITransportSecurityInfo* GetSecurityInfo() { return mSecurityInfo; }
protected:
const nsAString& GetRemoteType() override;
protected:
JSActor::Type GetSide() override { return JSActor::Type::Parent; }
// IPC messages

View File

@ -1435,7 +1435,8 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
LOG(("Process Switch: Calling ChangeRemoteness"));
browsingContext
->ChangeRemoteness(remoteType, mLoadIdentifier,
isCOOPSwitch || isLargeAllocSwitch)
isCOOPSwitch || isLargeAllocSwitch,
/* specificGroup */ 0)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[self = RefPtr{this}](BrowserParent* aBrowserParent) {