From 8c7b06dc230fdbdbbc9774663e65c69118a45f10 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Fri, 29 Jan 2021 22:15:44 +0000 Subject: [PATCH] Bug 1687805 - Part 2: Don't use OpenNoNavigate if noopener is force-enabled, r=kmag Differential Revision: https://phabricator.services.mozilla.com/D103360 --- docshell/base/nsDocShell.cpp | 26 ++++++++++++++++++++------ docshell/base/nsDocShell.h | 6 ++++++ dom/base/nsGlobalWindowOuter.cpp | 25 +++++++++++++++---------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 7aaf02c70ef1..42f73e10db9d 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -8437,6 +8437,19 @@ nsContentPolicyType nsDocShell::DetermineContentType() { : nsIContentPolicy::TYPE_INTERNAL_FRAME; } +bool nsDocShell::NoopenerForceEnabled() { + // If current's top-level browsing context's active document's + // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then + // if currentDoc's origin is not same origin with currentDoc's top-level + // origin, noopener is force enabled, and name is cleared to "_blank". + auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy(); + return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN || + topPolicy == + nsILoadInfo:: + OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) && + !mBrowsingContext->SameOriginWithTop(); +} + nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { MOZ_ASSERT(aLoadState, "need a load state!"); MOZ_ASSERT(!aLoadState->Target().IsEmpty(), "should have a target here!"); @@ -8550,17 +8563,18 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { // If we are a noopener load, we just hand the whole thing over to our // window. - if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER)) { + if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) || + NoopenerForceEnabled()) { // Various asserts that we know to hold because NO_OPENER loads can only // happen for links. MOZ_ASSERT(!aLoadState->LoadReplace()); MOZ_ASSERT(aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()); - MOZ_ASSERT(aLoadState->InternalLoadFlags() == - INTERNAL_LOAD_FLAGS_NO_OPENER || - aLoadState->InternalLoadFlags() == - (INTERNAL_LOAD_FLAGS_NO_OPENER | - INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)); + MOZ_ASSERT(!(aLoadState->InternalLoadFlags() & + ~(INTERNAL_LOAD_FLAGS_NO_OPENER | + INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)), + "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " + "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"); MOZ_ASSERT(!aLoadState->PostDataStream()); MOZ_ASSERT(!aLoadState->HeadersStream()); // If OnLinkClickSync was invoked inside the onload handler, the load diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 9e0d878a7ee5..686cd02f05ec 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -1059,6 +1059,12 @@ class nsDocShell final : public nsDocLoader, void ActivenessMaybeChanged(); + /** + * Returns true if `noopener` will be force-enabled by any attempt to create + * a popup window, even if rel="opener" is requested. + */ + bool NoopenerForceEnabled(); + private: // data members nsString mTitle; nsCString mOriginalUriString; diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index 6f592994dbe0..7e8199894142 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -6934,17 +6934,22 @@ nsresult nsGlobalWindowOuter::OpenInternal( nsAutoCString options; features.Stringify(options); - // If current's top-level browsing context's active document's - // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then - // if currentDoc's origin is not same origin with currentDoc's top-level - // origin, then set noopener to true and name to "_blank". + // If noopener is force-enabled for the current document, then set noopener to + // true, and clear the name to "_blank". nsAutoString windowName(aName); - auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy(); - if ((topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN || - topPolicy == - nsILoadInfo:: - OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) && - !mBrowsingContext->SameOriginWithTop()) { + if (nsDocShell::Cast(GetDocShell())->NoopenerForceEnabled()) { + // FIXME: Eventually bypass force-enabling noopener if `aPrintKind != + // PrintKind::None`, so that we can print pages with noopener force-enabled. + // This will require relaxing assertions elsewhere. + if (aPrintKind != PrintKind::None) { + NS_WARNING( + "printing frames with noopener force-enabled isn't supported yet"); + return NS_ERROR_FAILURE; + } + + MOZ_DIAGNOSTIC_ASSERT(aNavigate, + "cannot OpenNoNavigate if noopener is force-enabled"); + forceNoOpener = true; windowName = u"_blank"_ns; }