Bug 1701001 - Part 2: Add "is popup" field to browsing context. r=smaug

Add BrowsingContext::FieldValues.mIsPopupRequested, and pass "is popup"
value calculated before opening window/tab to BrowsingContext::CreateDetached.

Other code path that is unrelated to content-priv window.open uses the
default value false.

Differential Revision: https://phabricator.services.mozilla.com/D129411
This commit is contained in:
Tooru Fujisawa 2021-11-06 01:19:14 +00:00
parent f11f62dcaf
commit 4d7bcb01be
10 changed files with 55 additions and 30 deletions

View file

@ -294,7 +294,7 @@ bool BrowsingContext::SameOriginWithTop() {
already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached( already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached(
nsGlobalWindowInner* aParent, BrowsingContext* aOpener, nsGlobalWindowInner* aParent, BrowsingContext* aOpener,
BrowsingContextGroup* aSpecificGroup, const nsAString& aName, Type aType, BrowsingContextGroup* aSpecificGroup, const nsAString& aName, Type aType,
bool aCreatedDynamically) { bool aIsPopupRequested, bool aCreatedDynamically) {
if (aParent) { if (aParent) {
MOZ_DIAGNOSTIC_ASSERT(aParent->GetWindowContext()); MOZ_DIAGNOSTIC_ASSERT(aParent->GetWindowContext());
MOZ_DIAGNOSTIC_ASSERT(aParent->GetBrowsingContext()->mType == aType); MOZ_DIAGNOSTIC_ASSERT(aParent->GetBrowsingContext()->mType == aType);
@ -410,6 +410,8 @@ already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached(
fields.mAllowJavascript = inherit ? inherit->GetAllowJavascript() : true; fields.mAllowJavascript = inherit ? inherit->GetAllowJavascript() : true;
fields.mIsPopupRequested = aIsPopupRequested;
if (!parentBC) { if (!parentBC) {
fields.mShouldDelayMediaFromStart = fields.mShouldDelayMediaFromStart =
StaticPrefs::media_block_autoplay_until_in_foreground(); StaticPrefs::media_block_autoplay_until_in_foreground();
@ -454,7 +456,7 @@ already_AddRefed<BrowsingContext> BrowsingContext::CreateIndependent(
"BCs created in the content process must be related to " "BCs created in the content process must be related to "
"some BrowserChild"); "some BrowserChild");
RefPtr<BrowsingContext> bc( RefPtr<BrowsingContext> bc(
CreateDetached(nullptr, nullptr, nullptr, u""_ns, aType)); CreateDetached(nullptr, nullptr, nullptr, u""_ns, aType, false));
bc->mWindowless = bc->IsContent(); bc->mWindowless = bc->IsContent();
bc->mEmbeddedByThisProcess = true; bc->mEmbeddedByThisProcess = true;
bc->EnsureAttached(); bc->EnsureAttached();

View file

@ -156,6 +156,14 @@ enum class ExplicitActiveStatus : uint8_t {
FIELD(ForceEnableTrackingProtection, bool) \ FIELD(ForceEnableTrackingProtection, bool) \
FIELD(UseGlobalHistory, bool) \ FIELD(UseGlobalHistory, bool) \
FIELD(FullscreenAllowedByOwner, bool) \ FIELD(FullscreenAllowedByOwner, bool) \
/* \
* "is popup" in the spec. \
* Set only on top browsing contexts. \
* This doesn't indicate whether this is actually a popup or not, \
* but whether this browsing context is created by requesting popup or not. \
* See also: nsWindowWatcher::ShouldOpenPopup. \
*/ \
FIELD(IsPopupRequested, bool) \
/* These field are used to store the states of autoplay media request on \ /* These field are used to store the states of autoplay media request on \
* GeckoView only, and it would only be modified on the top level browsing \ * GeckoView only, and it would only be modified on the top level browsing \
* context. */ \ * context. */ \
@ -283,7 +291,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
static already_AddRefed<BrowsingContext> CreateDetached( static already_AddRefed<BrowsingContext> CreateDetached(
nsGlobalWindowInner* aParent, BrowsingContext* aOpener, nsGlobalWindowInner* aParent, BrowsingContext* aOpener,
BrowsingContextGroup* aSpecificGroup, const nsAString& aName, Type aType, BrowsingContextGroup* aSpecificGroup, const nsAString& aName, Type aType,
bool aCreatedDynamically = false); bool aIsPopupRequested, bool aCreatedDynamically = false);
void EnsureAttached(); void EnsureAttached();

View file

@ -345,9 +345,9 @@ static already_AddRefed<BrowsingContext> CreateBrowsingContext(
// for the BrowsingContext, and cause no end of trouble. // for the BrowsingContext, and cause no end of trouble.
if (IsTopContent(parentBC, aOwner)) { if (IsTopContent(parentBC, aOwner)) {
// Create toplevel context without a parent & as Type::Content. // Create toplevel context without a parent & as Type::Content.
return BrowsingContext::CreateDetached(nullptr, opener, aSpecificGroup, return BrowsingContext::CreateDetached(
frameName, nullptr, opener, aSpecificGroup, frameName,
BrowsingContext::Type::Content); BrowsingContext::Type::Content, false);
} }
MOZ_ASSERT(!aOpenWindowInfo, MOZ_ASSERT(!aOpenWindowInfo,
@ -356,7 +356,7 @@ static already_AddRefed<BrowsingContext> CreateBrowsingContext(
MOZ_ASSERT(!aSpecificGroup, MOZ_ASSERT(!aSpecificGroup,
"Can't force BrowsingContextGroup for non-toplevel context"); "Can't force BrowsingContextGroup for non-toplevel context");
return BrowsingContext::CreateDetached(parentInner, nullptr, nullptr, return BrowsingContext::CreateDetached(parentInner, nullptr, nullptr,
frameName, parentBC->GetType(), frameName, parentBC->GetType(), false,
!aNetworkCreated); !aNetworkCreated);
} }

View file

@ -818,7 +818,7 @@ BrowserChild::ProvideWindow(nsIOpenWindowInfo* aOpenWindowInfo,
uint32_t aChromeFlags, bool aCalledFromJS, uint32_t aChromeFlags, bool aCalledFromJS,
nsIURI* aURI, const nsAString& aName, nsIURI* aURI, const nsAString& aName,
const nsACString& aFeatures, bool aForceNoOpener, const nsACString& aFeatures, bool aForceNoOpener,
bool aForceNoReferrer, bool aForceNoReferrer, bool aIsPopupRequested,
nsDocShellLoadState* aLoadState, bool* aWindowIsNew, nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
BrowsingContext** aReturn) { BrowsingContext** aReturn) {
*aReturn = nullptr; *aReturn = nullptr;
@ -848,10 +848,10 @@ BrowserChild::ProvideWindow(nsIOpenWindowInfo* aOpenWindowInfo,
// open window call was canceled. It's important that we pass this error // open window call was canceled. It's important that we pass this error
// code back to our caller. // code back to our caller.
ContentChild* cc = ContentChild::GetSingleton(); ContentChild* cc = ContentChild::GetSingleton();
return cc->ProvideWindowCommon(this, aOpenWindowInfo, aChromeFlags, return cc->ProvideWindowCommon(
aCalledFromJS, aURI, aName, aFeatures, this, aOpenWindowInfo, aChromeFlags, aCalledFromJS, aURI, aName,
aForceNoOpener, aForceNoReferrer, aLoadState, aFeatures, aForceNoOpener, aForceNoReferrer, aIsPopupRequested,
aWindowIsNew, aReturn); aLoadState, aWindowIsNew, aReturn);
} }
void BrowserChild::DestroyWindow() { void BrowserChild::DestroyWindow() {

View file

@ -968,7 +968,8 @@ nsresult ContentChild::ProvideWindowCommon(
BrowserChild* aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo, BrowserChild* aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo,
uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI, uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI,
const nsAString& aName, const nsACString& aFeatures, bool aForceNoOpener, const nsAString& aName, const nsACString& aFeatures, bool aForceNoOpener,
bool aForceNoReferrer, nsDocShellLoadState* aLoadState, bool* aWindowIsNew, bool aForceNoReferrer, bool aIsPopupRequested,
nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
BrowsingContext** aReturn) { BrowsingContext** aReturn) {
MOZ_DIAGNOSTIC_ASSERT(aTabOpener, "We must have a tab opener"); MOZ_DIAGNOSTIC_ASSERT(aTabOpener, "We must have a tab opener");
@ -1058,7 +1059,8 @@ nsresult ContentChild::ProvideWindowCommon(
} }
RefPtr<BrowsingContext> browsingContext = BrowsingContext::CreateDetached( RefPtr<BrowsingContext> browsingContext = BrowsingContext::CreateDetached(
nullptr, openerBC, nullptr, aName, BrowsingContext::Type::Content); nullptr, openerBC, nullptr, aName, BrowsingContext::Type::Content,
aIsPopupRequested);
MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteTabs(true)); MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteTabs(true));
MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteSubframes(useRemoteSubframes)); MOZ_ALWAYS_SUCCEEDS(browsingContext->SetRemoteSubframes(useRemoteSubframes));
MOZ_ALWAYS_SUCCEEDS(browsingContext->SetOriginAttributes( MOZ_ALWAYS_SUCCEEDS(browsingContext->SetOriginAttributes(

View file

@ -115,8 +115,9 @@ class ContentChild final : public PContentChild,
BrowserChild* aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo, BrowserChild* aTabOpener, nsIOpenWindowInfo* aOpenWindowInfo,
uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI, uint32_t aChromeFlags, bool aCalledFromJS, nsIURI* aURI,
const nsAString& aName, const nsACString& aFeatures, bool aForceNoOpener, const nsAString& aName, const nsACString& aFeatures, bool aForceNoOpener,
bool aForceNoReferrer, nsDocShellLoadState* aLoadState, bool aForceNoReferrer, bool aIsPopupRequested,
bool* aWindowIsNew, BrowsingContext** aReturn); nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
BrowsingContext** aReturn);
void Init(base::ProcessId aParentPid, const char* aParentBuildID, void Init(base::ProcessId aParentPid, const char* aParentBuildID,
mozilla::ipc::ScopedPort aPort, uint64_t aChildID, mozilla::ipc::ScopedPort aPort, uint64_t aChildID,

View file

@ -69,6 +69,10 @@ interface nsIWindowProvider : nsISupports
* the feature string to the window it returns in any way it sees fit. * the feature string to the window it returns in any way it sees fit.
* See the nsIWindowWatcher interface for details on feature strings. * See the nsIWindowWatcher interface for details on feature strings.
* *
* @param aIsPopupRequested True if this window is opened by window.open
* with requesting a popup window. This doesn't necessarily mean
* whether the actual window is shown as minimal popup or not.
*
* @param aLoadState Specify setup information of the load in the new window * @param aLoadState Specify setup information of the load in the new window
* *
* @param aWindowIsNew [out] Whether the window being returned was just * @param aWindowIsNew [out] Whether the window being returned was just
@ -99,6 +103,7 @@ interface nsIWindowProvider : nsISupports
in AUTF8String aFeatures, in AUTF8String aFeatures,
in boolean aForceNoOpener, in boolean aForceNoOpener,
in boolean aForceNoReferrer, in boolean aForceNoReferrer,
in boolean aIsPopupRequested,
in nsDocShellLoadStatePtr aLoadState, in nsDocShellLoadStatePtr aLoadState,
out boolean aWindowIsNew); out boolean aWindowIsNew);
}; };

View file

@ -520,7 +520,11 @@ nsWindowWatcher::OpenWindowWithRemoteTab(nsIRemoteTab* aRemoteTab,
SizeSpec sizeSpec; SizeSpec sizeSpec;
CalcSizeSpec(features, false, sizeSpec); CalcSizeSpec(features, false, sizeSpec);
uint32_t chromeFlags = CalculateChromeFlagsForContent(features); // This is not initiated by window.open call in content context, and we
// don't need to propagate isPopupRequested out-parameter to the resulting
// browsing context.
bool unused = false;
uint32_t chromeFlags = CalculateChromeFlagsForContent(features, &unused);
if (isPrivateBrowsingWindow) { if (isPrivateBrowsingWindow) {
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW; chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
@ -697,6 +701,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
SizeSpec sizeSpec; SizeSpec sizeSpec;
CalcSizeSpec(features, hasChromeParent, sizeSpec); CalcSizeSpec(features, hasChromeParent, sizeSpec);
bool isPopupRequested = false;
// Make sure we calculate the chromeFlags *before* we push the // Make sure we calculate the chromeFlags *before* we push the
// callee context onto the context stack so that // callee context onto the context stack so that
// the calculation sees the actual caller when doing its // the calculation sees the actual caller when doing its
@ -707,7 +713,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
} else { } else {
MOZ_DIAGNOSTIC_ASSERT(parentBC && parentBC->IsContent(), MOZ_DIAGNOSTIC_ASSERT(parentBC && parentBC->IsContent(),
"content caller must provide content parent"); "content caller must provide content parent");
chromeFlags = CalculateChromeFlagsForContent(features); chromeFlags = CalculateChromeFlagsForContent(features, &isPopupRequested);
if (aDialog) { if (aDialog) {
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
@ -841,8 +847,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
if (provider) { if (provider) {
rv = provider->ProvideWindow( rv = provider->ProvideWindow(
openWindowInfo, chromeFlags, aCalledFromJS, uriToLoad, name, openWindowInfo, chromeFlags, aCalledFromJS, uriToLoad, name,
featuresStr, aForceNoOpener, aForceNoReferrer, aLoadState, featuresStr, aForceNoOpener, aForceNoReferrer, isPopupRequested,
&windowIsNew, getter_AddRefs(newBC)); aLoadState, &windowIsNew, getter_AddRefs(newBC));
if (NS_SUCCEEDED(rv) && newBC) { if (NS_SUCCEEDED(rv) && newBC) {
nsCOMPtr<nsIDocShell> newDocShell = newBC->GetDocShell(); nsCOMPtr<nsIDocShell> newDocShell = newBC->GetDocShell();
@ -1762,11 +1768,13 @@ bool nsWindowWatcher::ShouldOpenPopup(const WindowFeatures& aFeatures) {
* from a child process. The feature string can only control whether to open a * from a child process. The feature string can only control whether to open a
* new tab or a new popup. * new tab or a new popup.
* @param aFeatures a string containing a list of named features * @param aFeatures a string containing a list of named features
* @param aIsPopupRequested an out parameter that indicates whether a popup
* is requested by aFeatures
* @return the chrome bitmask * @return the chrome bitmask
*/ */
// static // static
uint32_t nsWindowWatcher::CalculateChromeFlagsForContent( uint32_t nsWindowWatcher::CalculateChromeFlagsForContent(
const WindowFeatures& aFeatures) { const WindowFeatures& aFeatures, bool* aIsPopupRequested) {
if (aFeatures.IsEmpty() || !ShouldOpenPopup(aFeatures)) { if (aFeatures.IsEmpty() || !ShouldOpenPopup(aFeatures)) {
// Open the current/new tab in the current/new window // Open the current/new tab in the current/new window
// (depends on browser.link.open_newwindow). // (depends on browser.link.open_newwindow).
@ -1774,6 +1782,7 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent(
} }
// Open a minimal popup. // Open a minimal popup.
*aIsPopupRequested = true;
return nsIWebBrowserChrome::CHROME_MINIMAL_POPUP; return nsIWebBrowserChrome::CHROME_MINIMAL_POPUP;
} }

View file

@ -90,7 +90,7 @@ class nsWindowWatcher : public nsIWindowWatcher,
static bool ShouldOpenPopup(const mozilla::dom::WindowFeatures& aFeatures); static bool ShouldOpenPopup(const mozilla::dom::WindowFeatures& aFeatures);
static uint32_t CalculateChromeFlagsForContent( static uint32_t CalculateChromeFlagsForContent(
const mozilla::dom::WindowFeatures& aFeatures); const mozilla::dom::WindowFeatures& aFeatures, bool* aIsPopupRequested);
static uint32_t CalculateChromeFlagsForSystem( static uint32_t CalculateChromeFlagsForSystem(
const mozilla::dom::WindowFeatures& aFeatures, bool aDialog, const mozilla::dom::WindowFeatures& aFeatures, bool aDialog,

View file

@ -519,14 +519,12 @@ NS_IMETHODIMP nsContentTreeOwner::SetTitle(const nsAString& aTitle) {
// nsContentTreeOwner: nsIWindowProvider // nsContentTreeOwner: nsIWindowProvider
//***************************************************************************** //*****************************************************************************
NS_IMETHODIMP NS_IMETHODIMP
nsContentTreeOwner::ProvideWindow(nsIOpenWindowInfo* aOpenWindowInfo, nsContentTreeOwner::ProvideWindow(
uint32_t aChromeFlags, bool aCalledFromJS, nsIOpenWindowInfo* aOpenWindowInfo, uint32_t aChromeFlags,
nsIURI* aURI, const nsAString& aName, bool aCalledFromJS, nsIURI* aURI, const nsAString& aName,
const nsACString& aFeatures, const nsACString& aFeatures, bool aForceNoOpener, bool aForceNoReferrer,
bool aForceNoOpener, bool aForceNoReferrer, bool aIsPopupRequested, nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
nsDocShellLoadState* aLoadState, dom::BrowsingContext** aReturn) {
bool* aWindowIsNew,
dom::BrowsingContext** aReturn) {
NS_ENSURE_ARG_POINTER(aOpenWindowInfo); NS_ENSURE_ARG_POINTER(aOpenWindowInfo);
RefPtr<dom::BrowsingContext> parent = aOpenWindowInfo->GetParent(); RefPtr<dom::BrowsingContext> parent = aOpenWindowInfo->GetParent();