Backed out 5 changesets (bug 1694993) for bc failure on browser_cross_process_csp_inheritance.js

Backed out changeset 1d21d911b3e7 (bug 1694993)
Backed out changeset 3b412d5fbdcf (bug 1694993)
Backed out changeset c9585ce37fe5 (bug 1694993)
Backed out changeset 05d7cbbfe9e2 (bug 1694993)
Backed out changeset 3821545ab46b (bug 1694993)
This commit is contained in:
Narcis Beleuzu 2022-08-22 20:32:02 +03:00
Родитель bfde821b3b
Коммит 94d309143f
8 изменённых файлов: 185 добавлений и 304 удалений

Просмотреть файл

@ -215,4 +215,3 @@ skip-if = !sessionHistoryInParent
support-files =
file_ship_beforeunload_fired.html
skip-if = !sessionHistoryInParent
[test_open_javascript_noopener.html]

Просмотреть файл

@ -1,44 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script>
add_task(async function test_open_javascript_noopener() {
const topic = "test-javascript-was-run";
function jsuri(version) {
return `javascript:SpecialPowers.notifyObservers(null, "${topic}", "${version}");window.close()`;
}
let seen = [];
function observer(_subject, _topic, data) {
info(`got notification ${data}`);
seen.push(data);
}
SpecialPowers.addObserver(observer, topic);
isDeeply(seen, [], "seen no test notifications");
window.open(jsuri("1"));
// Bounce off the parent process to make sure the JS will have run.
await SpecialPowers.spawnChrome([], () => {});
isDeeply(seen, ["1"], "seen the opener notification");
window.open(jsuri("2"), "", "noopener");
// Bounce off the parent process to make sure the JS will have run.
await SpecialPowers.spawnChrome([], () => {});
isDeeply(seen, ["1"], "didn't get a notification from the noopener popup");
SpecialPowers.removeObserver(observer, topic);
});
</script>
</body>
</html>

Просмотреть файл

@ -1756,18 +1756,22 @@ bool nsGlobalWindowOuter::WouldReuseInnerWindow(Document* aNewDocument) {
return false;
}
void nsGlobalWindowOuter::SetInitialPrincipal(
nsIPrincipal* aNewWindowPrincipal, nsIContentSecurityPolicy* aCSP,
void nsGlobalWindowOuter::SetInitialPrincipalToSubject(
nsIContentSecurityPolicy* aCSP,
const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP) {
// First, grab the subject principal.
nsCOMPtr<nsIPrincipal> newWindowPrincipal =
nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
// We should never create windows with an expanded principal.
// If we have a system principal, make sure we're not using it for a content
// docshell.
// NOTE: Please keep this logic in sync with
// nsAppShellService::JustCreateTopWindow
if (nsContentUtils::IsExpandedPrincipal(aNewWindowPrincipal) ||
(aNewWindowPrincipal->IsSystemPrincipal() &&
if (nsContentUtils::IsExpandedPrincipal(newWindowPrincipal) ||
(newWindowPrincipal->IsSystemPrincipal() &&
GetBrowsingContext()->IsContent())) {
aNewWindowPrincipal = nullptr;
newWindowPrincipal = nullptr;
}
// If there's an existing document, bail if it either:
@ -1775,7 +1779,7 @@ void nsGlobalWindowOuter::SetInitialPrincipal(
// (a) is not an initial about:blank document, or
if (!mDoc->IsInitialDocument()) return;
// (b) already has the correct principal.
if (mDoc->NodePrincipal() == aNewWindowPrincipal) return;
if (mDoc->NodePrincipal() == newWindowPrincipal) return;
#ifdef DEBUG
// If we have a document loaded at this point, it had better be about:blank.
@ -1791,7 +1795,7 @@ void nsGlobalWindowOuter::SetInitialPrincipal(
// Use the subject (or system) principal as the storage principal too until
// the new window finishes navigating and gets a real storage principal.
nsDocShell::Cast(GetDocShell())
->CreateAboutBlankContentViewer(aNewWindowPrincipal, aNewWindowPrincipal,
->CreateAboutBlankContentViewer(newWindowPrincipal, newWindowPrincipal,
aCSP, nullptr,
/* aIsInitialDocument */ true, aCOEP);

Просмотреть файл

@ -305,8 +305,8 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
mozilla::dom::EventTarget* aChromeEventHandler) override;
// Outer windows only.
virtual void SetInitialPrincipal(
nsIPrincipal* aNewWindowPrincipal, nsIContentSecurityPolicy* aCSP,
virtual void SetInitialPrincipalToSubject(
nsIContentSecurityPolicy* aCSP,
const mozilla::Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCoep)
override;

Просмотреть файл

@ -880,10 +880,10 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
return mDoc;
}
// Set the window up with an about:blank document with the given principal and
// potentially a CSP and a COEP.
virtual void SetInitialPrincipal(
nsIPrincipal* aNewWindowPrincipal, nsIContentSecurityPolicy* aCSP,
// Set the window up with an about:blank document with the current subject
// principal and potentially a CSP and a COEP.
virtual void SetInitialPrincipalToSubject(
nsIContentSecurityPolicy* aCSP,
const mozilla::Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCoep) = 0;
// Returns an object containing the window's state. This also suspends

Просмотреть файл

@ -1,26 +0,0 @@
test(function() {
var popup = window.open("", "sessionStorageTestWindow");
sessionStorage.setItem("FOO", "BAR");
var reopened = window.open("", "sessionStorageTestWindow");
assert_equals(
popup,
reopened,
"window.open with the same name should re-open the same window"
);
assert_equals(
sessionStorage.getItem("FOO"),
"BAR",
"local sessionStorage is correct"
);
assert_equals(
popup.sessionStorage.getItem("FOO"),
null,
"popup sessionStorage is correct"
);
popup.close();
}, "ensure that re-opening a named window doesn't copy sessionStorage");

Просмотреть файл

@ -629,10 +629,10 @@ nsresult nsWindowWatcher::OpenWindowInternal(
nsAutoString name; // string version of aName
nsCOMPtr<nsIURI> uriToLoad; // from aUrl, if any
nsCOMPtr<nsIDocShellTreeOwner>
parentTreeOwner; // from the parent window, if any
RefPtr<BrowsingContext> targetBC; // from the new window
parentTreeOwner; // from the parent window, if any
RefPtr<BrowsingContext> newBC; // from the new window
nsCOMPtr<nsPIDOMWindowOuter> parentOuterWin =
nsCOMPtr<nsPIDOMWindowOuter> parentWindow =
aParent ? nsPIDOMWindowOuter::From(aParent) : nullptr;
NS_ENSURE_ARG_POINTER(aResult);
@ -643,8 +643,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
return NS_ERROR_FAILURE;
}
if (parentOuterWin) {
parentTreeOwner = parentOuterWin->GetTreeOwner();
if (parentWindow) {
parentTreeOwner = parentWindow->GetTreeOwner();
}
// We expect BrowserParent to have provided us the absolute URI of the window
@ -676,13 +676,9 @@ nsresult nsWindowWatcher::OpenWindowInternal(
}
RefPtr<BrowsingContext> parentBC(
parentOuterWin ? parentOuterWin->GetBrowsingContext() : nullptr);
parentWindow ? parentWindow->GetBrowsingContext() : nullptr);
nsCOMPtr<nsIDocShell> parentDocShell(parentBC ? parentBC->GetDocShell()
: nullptr);
RefPtr<Document> parentDoc(parentOuterWin ? parentOuterWin->GetDoc()
: nullptr);
nsCOMPtr<nsPIDOMWindowInner> parentInnerWin(
parentOuterWin ? parentOuterWin->GetCurrentInnerWindow() : nullptr);
// Return null for any attempt to trigger a load from a discarded browsing
// context. The spec is non-normative, and doesn't specify what should happen
@ -698,18 +694,18 @@ nsresult nsWindowWatcher::OpenWindowInternal(
}
// try to find an extant browsing context with the given name
targetBC = GetBrowsingContextByName(name, aForceNoOpener, parentBC);
newBC = GetBrowsingContextByName(name, aForceNoOpener, parentBC);
// Do sandbox checks here, instead of waiting until nsIDocShell::LoadURI.
// The state of the window can change before this call and if we are blocked
// because of sandboxing, we wouldn't want that to happen.
if (parentBC && parentBC->IsSandboxedFrom(targetBC)) {
if (parentBC && parentBC->IsSandboxedFrom(newBC)) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
// If our target BrowsingContext is still pending initialization, ignore the
// navigation request targeting it.
if (targetBC && NS_WARN_IF(targetBC->GetPendingInitialization())) {
if (newBC && NS_WARN_IF(newBC->GetPendingInitialization())) {
return NS_ERROR_ABORT;
}
@ -719,7 +715,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
bool hasChromeParent = !XRE_IsContentProcess();
if (aParent) {
// Check if the parent document has chrome privileges.
hasChromeParent = parentDoc && nsContentUtils::IsChromeDoc(parentDoc);
Document* doc = parentWindow->GetDoc();
hasChromeParent = doc && nsContentUtils::IsChromeDoc(doc);
}
bool isCallerChrome = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
@ -811,56 +808,10 @@ nsresult nsWindowWatcher::OpenWindowInternal(
}
}
// Now that the jsapiChromeGuard has been set, fetch the system principal
// potentially configured by it. We want to make sure to respect any principal
// changes imposed by that guard throughout this function.
//
// Note: The check for the current JSContext isn't necessarily sensical.
// It's just designed to preserve old semantics during a mass-conversion
// patch.
// Bug 1498605 verify usages of systemPrincipal here
JSContext* cx = nsContentUtils::GetCurrentJSContext();
nsCOMPtr<nsIPrincipal> subjectPrincipal =
cx ? nsContentUtils::SubjectPrincipal()
: nsContentUtils::GetSystemPrincipal();
MOZ_ASSERT(subjectPrincipal);
nsCOMPtr<nsIPrincipal> newWindowPrincipal;
if (!targetBC) {
if (windowTypeIsChrome) {
// If we are creating a chrome window, we must be called with a system
// principal, and should inherit that for the new chrome window.
MOZ_RELEASE_ASSERT(subjectPrincipal->IsSystemPrincipal(),
"Only system principals can create chrome windows");
newWindowPrincipal = subjectPrincipal;
} else if (nsContentUtils::IsSystemOrExpandedPrincipal(subjectPrincipal)) {
// Don't allow initial about:blank documents to inherit a system or
// expanded principal, instead replace it with a null principal. We can't
// inherit origin attributes from the system principal, so use the parent
// BC if it's available.
if (parentBC) {
newWindowPrincipal = NullPrincipal::CreateWithInheritedAttributes(
parentBC->OriginAttributesRef());
} else {
newWindowPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
}
} else if (aForceNoOpener) {
// If we're opening a new window with noopener, create a new opaque
// principal for the new window, rather than re-using the existing
// principal.
newWindowPrincipal =
NullPrincipal::CreateWithInheritedAttributes(subjectPrincipal);
} else {
// Finally, if there's an opener relationship and it's not a special
// principal, we should inherit that principal for the new window.
newWindowPrincipal = subjectPrincipal;
}
}
// Information used when opening new content windows. This object will be
// passed through to the inner nsFrameLoader.
RefPtr<nsOpenWindowInfo> openWindowInfo;
if (!targetBC && !windowTypeIsChrome) {
if (!newBC && !windowTypeIsChrome) {
openWindowInfo = new nsOpenWindowInfo();
openWindowInfo->mForceNoOpener = aForceNoOpener;
openWindowInfo->mParent = parentBC;
@ -871,12 +822,17 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// want it to match the current remoteness.
openWindowInfo->mIsRemote = XRE_IsContentProcess();
// Inherit our OriginAttributes from the computed new window principal.
MOZ_ASSERT(
newWindowPrincipal &&
!nsContentUtils::IsSystemOrExpandedPrincipal(newWindowPrincipal));
openWindowInfo->mOriginAttributes =
newWindowPrincipal->OriginAttributesRef();
// If we have a non-system non-expanded subject principal, we can inherit
// our OriginAttributes from it.
nsCOMPtr<nsIPrincipal> subjectPrincipal =
nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
if (subjectPrincipal &&
!nsContentUtils::IsSystemOrExpandedPrincipal(subjectPrincipal)) {
openWindowInfo->mOriginAttributes =
subjectPrincipal->OriginAttributesRef();
} else if (parentBC) {
openWindowInfo->mOriginAttributes = parentBC->OriginAttributesRef();
}
MOZ_DIAGNOSTIC_ASSERT(
!parentBC || openWindowInfo->mOriginAttributes.EqualsIgnoringFPD(
@ -887,7 +843,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
uint32_t activeDocsSandboxFlags = 0;
nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
Maybe<nsILoadInfo::CrossOriginEmbedderPolicy> coepToInheritForAboutBlank;
if (!targetBC) {
if (!newBC) {
// We're going to either open up a new window ourselves or ask a
// nsIWindowProvider for one. In either case, we'll want to set the right
// name on it.
@ -895,20 +851,22 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// If the parent trying to open a new window is sandboxed
// without 'allow-popups', this is not allowed and we fail here.
if (parentDoc) {
// Save sandbox flags for copying to new browsing context (docShell).
activeDocsSandboxFlags = parentDoc->GetSandboxFlags();
if (aParent) {
if (Document* doc = parentWindow->GetDoc()) {
// Save sandbox flags for copying to new browsing context (docShell).
activeDocsSandboxFlags = doc->GetSandboxFlags();
if (!aForceNoOpener) {
cspToInheritForAboutBlank = parentDoc->GetCsp();
coepToInheritForAboutBlank = parentDoc->GetEmbedderPolicy();
}
if (!aForceNoOpener) {
cspToInheritForAboutBlank = doc->GetCsp();
coepToInheritForAboutBlank = doc->GetEmbedderPolicy();
}
// Check to see if this frame is allowed to navigate, but don't check if
// we're printing, as that's not a real navigation.
if (aPrintKind == PRINT_NONE &&
(activeDocsSandboxFlags & SANDBOXED_AUXILIARY_NAVIGATION)) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
// Check to see if this frame is allowed to navigate, but don't check if
// we're printing, as that's not a real navigation.
if (aPrintKind == PRINT_NONE &&
(activeDocsSandboxFlags & SANDBOXED_AUXILIARY_NAVIGATION)) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
}
}
@ -926,17 +884,17 @@ nsresult nsWindowWatcher::OpenWindowInternal(
rv = provider->ProvideWindow(
openWindowInfo, chromeFlags, aCalledFromJS, uriToLoad, name,
featuresStr, aForceNoOpener, aForceNoReferrer, isPopupRequested,
aLoadState, &windowIsNew, getter_AddRefs(targetBC));
aLoadState, &windowIsNew, getter_AddRefs(newBC));
if (NS_SUCCEEDED(rv) && targetBC) {
nsCOMPtr<nsIDocShell> newDocShell = targetBC->GetDocShell();
if (NS_SUCCEEDED(rv) && newBC) {
nsCOMPtr<nsIDocShell> newDocShell = newBC->GetDocShell();
// If this is a new window, but it's incompatible with the current
// userContextId, we ignore it and we pretend that nothing has been
// returned by ProvideWindow.
if (!windowIsNew && newDocShell) {
if (!CheckUserContextCompatibility(newDocShell)) {
targetBC = nullptr;
newBC = nullptr;
windowIsNew = false;
}
}
@ -955,7 +913,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
bool newWindowShouldBeModal = false;
bool parentIsModal = false;
if (!targetBC) {
if (!newBC) {
if (XRE_IsContentProcess()) {
// If our window provider failed to provide a window in the content
// process, we cannot recover. Reject the window open request and bail.
@ -1009,9 +967,9 @@ nsresult nsWindowWatcher::OpenWindowInternal(
nsCOMPtr<nsIWebBrowserChrome> newChrome;
nsCOMPtr<nsPIDOMWindowInner> parentTopInnerWindow;
if (parentOuterWin) {
if (parentWindow) {
nsCOMPtr<nsPIDOMWindowOuter> parentTopWindow =
parentOuterWin->GetInProcessTop();
parentWindow->GetInProcessTop();
if (parentTopWindow) {
parentTopInnerWindow = parentTopWindow->GetCurrentInnerWindow();
}
@ -1048,53 +1006,53 @@ nsresult nsWindowWatcher::OpenWindowInternal(
if (!newDocShellItem) {
rv = NS_ERROR_FAILURE;
}
targetBC = newDocShellItem->GetBrowsingContext();
newBC = newDocShellItem->GetBrowsingContext();
}
}
}
// better have a window to use by this point
if (!targetBC) {
if (!newBC) {
return rv;
}
// If our parent is sandboxed, set it as the one permitted sandboxed navigator
// on the new window we're opening.
if (activeDocsSandboxFlags && parentBC) {
MOZ_ALWAYS_SUCCEEDS(targetBC->SetOnePermittedSandboxedNavigator(parentBC));
MOZ_ALWAYS_SUCCEEDS(newBC->SetOnePermittedSandboxedNavigator(parentBC));
}
if (!aForceNoOpener && parentBC) {
// If we've created a new content window, its opener should have been set
// when its BrowsingContext was created, in order to ensure that the context
// is loaded within the correct BrowsingContextGroup.
if (windowIsNew && targetBC->IsContent()) {
if (windowIsNew && newBC->IsContent()) {
if (parentBC->IsDiscarded()) {
// If the parent BC was discarded in a nested event loop before we got
// to this point, we can't set it as the opener. Ideally we would still
// set `HadOriginalOpener()` in that case, but that's somewhat
// nontrivial, and not worth the effort given the nature of the corner
// case (see comment in `nsFrameLoader::CreateBrowsingContext`.
MOZ_RELEASE_ASSERT(targetBC->GetOpenerId() == parentBC->Id() ||
targetBC->GetOpenerId() == 0);
MOZ_RELEASE_ASSERT(newBC->GetOpenerId() == parentBC->Id() ||
newBC->GetOpenerId() == 0);
} else {
MOZ_RELEASE_ASSERT(targetBC->GetOpenerId() == parentBC->Id());
MOZ_RELEASE_ASSERT(targetBC->HadOriginalOpener());
MOZ_RELEASE_ASSERT(newBC->GetOpenerId() == parentBC->Id());
MOZ_RELEASE_ASSERT(newBC->HadOriginalOpener());
}
} else {
// Update the opener for an existing or chrome BC.
targetBC->SetOpener(parentBC);
newBC->SetOpener(parentBC);
}
}
RefPtr<nsDocShell> targetDocShell(nsDocShell::Cast(targetBC->GetDocShell()));
RefPtr<nsDocShell> newDocShell(nsDocShell::Cast(newBC->GetDocShell()));
// As required by spec, new windows always start out same-process, even if the
// URL being loaded will eventually load in a new process.
MOZ_DIAGNOSTIC_ASSERT(!windowIsNew || targetDocShell);
MOZ_DIAGNOSTIC_ASSERT(!windowIsNew || newDocShell);
// New top-level windows are only opened in the parent process and are, by
// definition, always in-process.
MOZ_DIAGNOSTIC_ASSERT(!isNewToplevelWindow || targetDocShell);
MOZ_DIAGNOSTIC_ASSERT(!isNewToplevelWindow || newDocShell);
// Copy sandbox flags to the new window if activeDocsSandboxFlags says to do
// so. Note that it's only nonzero if the window is new, so clobbering
@ -1102,46 +1060,45 @@ nsresult nsWindowWatcher::OpenWindowInternal(
if (activeDocsSandboxFlags &
SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS) {
MOZ_ASSERT(windowIsNew, "Should only get here for new windows");
MOZ_ALWAYS_SUCCEEDS(targetBC->SetSandboxFlags(activeDocsSandboxFlags));
MOZ_ALWAYS_SUCCEEDS(newBC->SetSandboxFlags(activeDocsSandboxFlags));
MOZ_ALWAYS_SUCCEEDS(
targetBC->SetInitialSandboxFlags(targetBC->GetSandboxFlags()));
newBC->SetInitialSandboxFlags(newBC->GetSandboxFlags()));
}
RefPtr<nsGlobalWindowOuter> targetOuterWin(
nsGlobalWindowOuter::Cast(targetBC->GetDOMWindow()));
RefPtr<nsGlobalWindowOuter> win(
nsGlobalWindowOuter::Cast(newBC->GetDOMWindow()));
#ifdef DEBUG
if (targetOuterWin && windowIsNew) {
if (win && windowIsNew) {
// Assert that we're not loading things right now. If we are, when
// that load completes it will clobber whatever principals we set up
// on this new window!
nsCOMPtr<nsIChannel> chan;
targetDocShell->GetDocumentChannel(getter_AddRefs(chan));
newDocShell->GetDocumentChannel(getter_AddRefs(chan));
MOZ_ASSERT(!chan, "Why is there a document channel?");
if (RefPtr<Document> doc = targetOuterWin->GetExtantDoc()) {
if (RefPtr<Document> doc = win->GetExtantDoc()) {
MOZ_ASSERT(doc->IsInitialDocument(),
"New window's document should be an initial document");
}
}
#endif
MOZ_ASSERT(targetOuterWin || !windowIsNew,
"New windows are always created in-process");
MOZ_ASSERT(win || !windowIsNew, "New windows are always created in-process");
*aResult = do_AddRef(targetBC).take();
*aResult = do_AddRef(newBC).take();
if (isNewToplevelWindow) {
nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
targetDocShell->GetTreeOwner(getter_AddRefs(newTreeOwner));
newDocShell->GetTreeOwner(getter_AddRefs(newTreeOwner));
MaybeDisablePersistence(sizeSpec, newTreeOwner);
}
if (aDialog && aArgv) {
MOZ_ASSERT(targetOuterWin);
NS_ENSURE_TRUE(targetOuterWin, NS_ERROR_UNEXPECTED);
MOZ_ASSERT(win);
NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED);
// Set the args on the new window.
MOZ_TRY(targetOuterWin->SetArguments(aArgv));
MOZ_TRY(win->SetArguments(aArgv));
}
/* allow a window that we found by name to keep its name (important for cases
@ -1149,40 +1106,52 @@ nsresult nsWindowWatcher::OpenWindowInternal(
is not a window name. */
if (windowNeedsName) {
if (nameSpecified && !name.LowerCaseEqualsLiteral("_blank")) {
MOZ_ALWAYS_SUCCEEDS(targetBC->SetName(name));
MOZ_ALWAYS_SUCCEEDS(newBC->SetName(name));
} else {
MOZ_ALWAYS_SUCCEEDS(targetBC->SetName(u""_ns));
MOZ_ALWAYS_SUCCEEDS(newBC->SetName(u""_ns));
}
}
// Now we have to set the right opener principal on the new window. Note
// that we have to do this _before_ starting any URI loads, thanks to the
// sync nature of javascript: loads.
//
// Note: The check for the current JSContext isn't necessarily sensical.
// It's just designed to preserve old semantics during a mass-conversion
// patch.
// Bug 1498605 verify usages of systemPrincipal here
JSContext* cx = nsContentUtils::GetCurrentJSContext();
nsCOMPtr<nsIPrincipal> subjectPrincipal =
cx ? nsContentUtils::SubjectPrincipal()
: nsContentUtils::GetSystemPrincipal();
if (windowIsNew) {
MOZ_DIAGNOSTIC_ASSERT(
!targetBC->IsContent() ||
newWindowPrincipal->OriginAttributesRef().EqualsIgnoringFPD(
targetBC->OriginAttributesRef()));
if (subjectPrincipal &&
!nsContentUtils::IsSystemOrExpandedPrincipal(subjectPrincipal) &&
newBC->IsContent()) {
MOZ_DIAGNOSTIC_ASSERT(
subjectPrincipal->OriginAttributesRef().EqualsIgnoringFPD(
newBC->OriginAttributesRef()));
}
bool autoPrivateBrowsing =
Preferences::GetBool("browser.privatebrowsing.autostart");
if (!autoPrivateBrowsing &&
(chromeFlags & nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW)) {
if (targetBC->IsChrome()) {
targetBC->SetUsePrivateBrowsing(false);
if (newBC->IsChrome()) {
newBC->SetUsePrivateBrowsing(false);
}
MOZ_DIAGNOSTIC_ASSERT(
!targetBC->UsePrivateBrowsing(),
!newBC->UsePrivateBrowsing(),
"CHROME_NON_PRIVATE_WINDOW passed, but got private window");
} else if (autoPrivateBrowsing ||
(chromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW)) {
if (targetBC->IsChrome()) {
targetBC->SetUsePrivateBrowsing(true);
if (newBC->IsChrome()) {
newBC->SetUsePrivateBrowsing(true);
}
MOZ_DIAGNOSTIC_ASSERT(
targetBC->UsePrivateBrowsing(),
newBC->UsePrivateBrowsing(),
"CHROME_PRIVATE_WINDOW passed, but got non-private window");
}
@ -1191,47 +1160,26 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// the JS stack, just use the principal of our parent window. In those
// cases we do _not_ set the parent window principal as the owner of the
// load--since we really don't know who the owner is, just leave it null.
NS_ASSERTION(targetOuterWin == targetDocShell->GetWindow(),
"Different windows??");
NS_ASSERTION(win == newDocShell->GetWindow(), "Different windows??");
// Initialize the principal of the initial about:blank document. For
// toplevel windows, this call may have already happened when the window was
// created, but SetInitialPrincipal is safe to call multiple times.
if (targetOuterWin) {
// The principal of the initial about:blank document gets set up in
// nsWindowWatcher::AddWindow. Make sure to call it. In the common case
// this call already happened when the window was created, but
// SetInitialPrincipalToSubject is safe to call multiple times.
if (win) {
MOZ_ASSERT(windowIsNew);
MOZ_ASSERT(!targetOuterWin->GetSameProcessOpener() ||
targetOuterWin->GetSameProcessOpener() == aParent);
targetOuterWin->SetInitialPrincipal(newWindowPrincipal,
cspToInheritForAboutBlank,
coepToInheritForAboutBlank);
MOZ_ASSERT(!win->GetSameProcessOpener() ||
win->GetSameProcessOpener() == aParent);
win->SetInitialPrincipalToSubject(cspToInheritForAboutBlank,
coepToInheritForAboutBlank);
if (aIsPopupSpam) {
MOZ_ASSERT(!targetBC->GetIsPopupSpam(),
MOZ_ASSERT(!newBC->GetIsPopupSpam(),
"Who marked it as popup spam already???");
// Make sure we don't mess up our counter even if the above assert
// fails.
if (!targetBC->GetIsPopupSpam()) {
MOZ_ALWAYS_SUCCEEDS(targetBC->SetIsPopupSpam(true));
}
}
}
// Copy the current session storage for the current domain. Don't perform
// the copy if we're forcing noopener, however.
if (!aForceNoOpener && subjectPrincipal && parentDocShell &&
targetDocShell) {
const RefPtr<SessionStorageManager> parentStorageManager =
parentDocShell->GetBrowsingContext()->GetSessionStorageManager();
const RefPtr<SessionStorageManager> newStorageManager =
targetDocShell->GetBrowsingContext()->GetSessionStorageManager();
if (parentStorageManager && newStorageManager) {
RefPtr<Storage> storage;
parentStorageManager->GetStorage(
parentInnerWin, subjectPrincipal, subjectPrincipal,
targetBC->UsePrivateBrowsing(), getter_AddRefs(storage));
if (storage) {
newStorageManager->CloneStorage(storage);
if (!newBC->GetIsPopupSpam()) {
MOZ_ALWAYS_SUCCEEDS(newBC->SetIsPopupSpam(true));
}
}
}
@ -1240,12 +1188,15 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// We rely on CalculateChromeFlags to decide whether remote (out-of-process)
// tabs should be used.
MOZ_DIAGNOSTIC_ASSERT(
targetBC->UseRemoteTabs() ==
newBC->UseRemoteTabs() ==
!!(chromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW));
MOZ_DIAGNOSTIC_ASSERT(
targetBC->UseRemoteSubframes() ==
newBC->UseRemoteSubframes() ==
!!(chromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW));
nsCOMPtr<nsPIDOMWindowInner> pInnerWin =
parentWindow ? parentWindow->GetCurrentInnerWindow() : nullptr;
;
RefPtr<nsDocShellLoadState> loadState = aLoadState;
if (uriToLoad && loadState) {
// If a URI was passed to this function, open that, not what was passed in
@ -1253,7 +1204,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
loadState->SetURI(uriToLoad);
} else if (uriToLoad && aNavigate && !loadState) {
RefPtr<WindowContext> context =
parentInnerWin ? parentInnerWin->GetWindowContext() : nullptr;
pInnerWin ? pInnerWin->GetWindowContext() : nullptr;
loadState = new nsDocShellLoadState(uriToLoad);
loadState->SetSourceBrowsingContext(parentBC);
@ -1280,8 +1231,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
screw up focus in the hidden window; see bug 36016.
*/
RefPtr<Document> doc = GetEntryDocument();
if (!doc) {
doc = parentDoc;
if (!doc && parentWindow) {
doc = parentWindow->GetExtantDoc();
}
if (doc) {
auto referrerInfo = MakeRefPtr<ReferrerInfo>(*doc);
@ -1304,14 +1255,14 @@ nsresult nsWindowWatcher::OpenWindowInternal(
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
if (obsSvc) {
obsSvc->NotifyObservers(ToSupports(targetOuterWin),
"toplevel-window-ready", nullptr);
obsSvc->NotifyObservers(ToSupports(win), "toplevel-window-ready",
nullptr);
}
}
// Before loading the URI we want to be 100% sure that we use the correct
// userContextId.
MOZ_ASSERT_IF(targetDocShell, CheckUserContextCompatibility(targetDocShell));
MOZ_ASSERT_IF(newDocShell, CheckUserContextCompatibility(newDocShell));
// If this tab or window has been opened by a window.open call, we have to
// provide all the data needed to send a
@ -1331,7 +1282,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
props->SetPropertyAsInterface(u"sourceTabDocShell"_ns, parentDocShell);
props->SetPropertyAsInterface(u"createdTabDocShell"_ns,
ToSupports(targetDocShell));
ToSupports(newDocShell));
obsSvc->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
"webNavigation-createdNavigationTarget-from-js",
@ -1340,38 +1291,49 @@ nsresult nsWindowWatcher::OpenWindowInternal(
}
if (uriToLoad && aNavigate) {
uint32_t loadFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
if (windowIsNew) {
loadFlags |= nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD;
// Per spec, the explicit navigation to about:blank after the initial
// about:blank document in a new window does not occur, so there is no
// opportunity for it to inherit the source document's principal. This
// doesn't perfectly model this, as a noopener creation of `about:blank`
// will replace the global due to a principal mismatch, but it should be
// unobservable (bug 1694993).
if (aForceNoOpener) {
loadFlags |= nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
}
}
loadState->SetLoadFlags(loadFlags);
// XXXBFCache Per spec this should effectively use
// LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL when noopener is passed to
// window.open(). Bug 1694993.
loadState->SetLoadFlags(
windowIsNew
? static_cast<uint32_t>(nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD)
: static_cast<uint32_t>(nsIWebNavigation::LOAD_FLAGS_NONE));
loadState->SetFirstParty(true);
// Should this pay attention to errors returned by LoadURI?
targetBC->LoadURI(loadState);
newBC->LoadURI(loadState);
}
// Copy the current session storage for the current domain. Don't perform the
// copy if we're forcing noopener, however.
if (!aForceNoOpener && subjectPrincipal && parentDocShell && newDocShell) {
const RefPtr<SessionStorageManager> parentStorageManager =
parentDocShell->GetBrowsingContext()->GetSessionStorageManager();
const RefPtr<SessionStorageManager> newStorageManager =
newDocShell->GetBrowsingContext()->GetSessionStorageManager();
if (parentStorageManager && newStorageManager) {
RefPtr<Storage> storage;
parentStorageManager->GetStorage(
pInnerWin, subjectPrincipal, subjectPrincipal,
newBC->UsePrivateBrowsing(), getter_AddRefs(storage));
if (storage) {
newStorageManager->CloneStorage(storage);
}
}
}
if (isNewToplevelWindow) {
nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
targetDocShell->GetTreeOwner(getter_AddRefs(newTreeOwner));
newDocShell->GetTreeOwner(getter_AddRefs(newTreeOwner));
SizeOpenedWindow(newTreeOwner, aParent, isCallerChrome, sizeSpec);
}
if (windowIsModal) {
NS_ENSURE_TRUE(targetDocShell, NS_ERROR_NOT_IMPLEMENTED);
NS_ENSURE_TRUE(newDocShell, NS_ERROR_NOT_IMPLEMENTED);
nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
targetDocShell->GetTreeOwner(getter_AddRefs(newTreeOwner));
newDocShell->GetTreeOwner(getter_AddRefs(newTreeOwner));
nsCOMPtr<nsIWebBrowserChrome> newChrome(do_GetInterface(newTreeOwner));
// Throw an exception here if no web browser chrome is available,
@ -1385,7 +1347,7 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// Make sure we maintain the state on an outer window, because
// that's where it lives; inner windows assert if you try to
// maintain the state on them.
nsAutoWindowStateHelper windowStateHelper(parentOuterWin);
nsAutoWindowStateHelper windowStateHelper(parentWindow);
if (!windowStateHelper.DefaultEnabled()) {
// Default to cancel not opening the modal window.
@ -1417,8 +1379,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
}
// If a website opens a popup exit DOM fullscreen
if (StaticPrefs::full_screen_api_exit_on_windowOpen() && aCalledFromJS &&
!hasChromeParent && !isCallerChrome && parentOuterWin) {
Document::AsyncExitFullscreen(parentOuterWin->GetDoc());
!hasChromeParent && !isCallerChrome && parentWindow) {
Document::AsyncExitFullscreen(parentWindow->GetDoc());
}
if (aForceNoOpener && windowIsNew) {

Просмотреть файл

@ -746,27 +746,24 @@ nsresult nsAppShellService::JustCreateTopWindow(
nsIWebBrowserChrome::CHROME_FISSION_WINDOW);
// Eagerly create an about:blank content viewer with the right principal
// here, rather than letting it happen in the upcoming call to
// SetInitialPrincipal. This avoids creating the about:blank document and
// then blowing it away with a second one, which can cause problems for the
// top-level chrome window case. See bug 789773.
// Toplevel chrome windows always have a system principal, so ensure the
// initial window is created with that principal.
// We need to do this even when creating a chrome window to load a content
// window, see bug 799348 comment 13 for details about what previously
// happened here due to it using the subject principal.
// here, rather than letting it happening in the upcoming call to
// SetInitialPrincipalToSubject. This avoids creating the about:blank
// document and then blowing it away with a second one, which can cause
// problems for the top-level chrome window case. See bug 789773. Note that
// we don't accept expanded principals here, similar to
// SetInitialPrincipalToSubject.
if (nsContentUtils::IsInitialized()) { // Sometimes this happens really
// early. See bug 793370.
MOZ_DIAGNOSTIC_ASSERT(
nsContentUtils::LegacyIsCallerChromeOrNativeCode(),
"Previously, this method would use the subject principal rather than "
"hardcoding the system principal");
// Use the system principal as the storage principal too until the new
// window finishes navigating and gets a real storage principal.
nsCOMPtr<nsIPrincipal> principal =
nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
if (nsContentUtils::IsExpandedPrincipal(principal)) {
principal = nullptr;
}
// Use the subject (or system) principal as the storage principal too
// until the new window finishes navigating and gets a real storage
// principal.
rv = docShell->CreateAboutBlankContentViewer(
nsContentUtils::GetSystemPrincipal(),
nsContentUtils::GetSystemPrincipal(),
/* aCsp = */ nullptr, /* aBaseURI = */ nullptr,
principal, principal, /* aCsp = */ nullptr, /* aBaseURI = */ nullptr,
/* aIsInitialDocument = */ true);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<Document> doc = docShell->GetDocument();
@ -850,18 +847,7 @@ nsAppShellService::RegisterTopLevelWindow(nsIAppWindow* aWindow) {
nsCOMPtr<nsPIDOMWindowOuter> domWindow(docShell->GetWindow());
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
// Toplevel chrome windows always have a system principal, so ensure the
// initial window is created with that principal.
// We need to do this even when creating a chrome window to load a content
// window, see bug 799348 comment 13 for details about what previously
// happened here due to it using the subject principal.
MOZ_DIAGNOSTIC_ASSERT(
nsContentUtils::LegacyIsCallerChromeOrNativeCode(),
"Previously, this method would use the subject principal rather than "
"hardcoding the system principal");
domWindow->SetInitialPrincipal(nsContentUtils::GetSystemPrincipal(), nullptr,
Nothing());
domWindow->SetInitialPrincipalToSubject(nullptr, Nothing());
// tell the window mediator about the new window
nsCOMPtr<nsIWindowMediator> mediator(