Bug 1736570 - Avoid DocumentChannel for nsParser-created initial about:blank replacement. r=nika,smaug

Differential Revision: https://phabricator.services.mozilla.com/D135106
This commit is contained in:
Henri Sivonen
2022-02-17 13:27:15 +00:00
parent 9fbf9d7b4c
commit 81ebfedbf3
13 changed files with 196 additions and 47 deletions

View File

@@ -232,6 +232,7 @@
#include "nsWidgetsCID.h"
#include "nsXULAppAPI.h"
#include "ThirdPartyUtil.h"
#include "BRNameMatchingPolicy.h"
#include "GeckoProfiler.h"
#include "mozilla/NullPrincipal.h"
@@ -391,7 +392,8 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mIsNavigating(false),
mSuspendMediaWhenInactive(false),
mForcedAutodetection(false),
mCheckingSessionHistory(false) {
mCheckingSessionHistory(false),
mNeedToReportActiveAfterLoadingBecomesActive(false) {
// If no outer window ID was provided, generate a new one.
if (aContentWindowID == 0) {
mContentWindowID = nsContentUtils::GenerateWindowId();
@@ -1339,7 +1341,8 @@ void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
mLoadGroup->AddRequest(channel, nullptr);
SetCurrentURI(doc->GetDocumentURI(), channel,
/* aFireOnLocationChange */ true,
/* aIsInitialAboutBlank */ false, /* aLocationFlags */ 0);
/* aIsInitialAboutBlank */ false,
/* aLocationFlags */ 0);
mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
mIsRestoringDocument = false;
}
@@ -1577,7 +1580,8 @@ nsDocShell::SetCurrentURI(nsIURI* aURI) {
// Note that securityUI will set STATE_IS_INSECURE, even if
// the scheme of |aURI| is "https".
SetCurrentURI(aURI, nullptr, /* aFireOnLocationChange */ true,
/* aIsInitialAboutBlank */ false, /* aLocationFlags */ 0);
/* aIsInitialAboutBlank */ false,
/* aLocationFlags */ 0);
return NS_OK;
}
@@ -6743,7 +6747,8 @@ nsresult nsDocShell::CreateAboutBlankContentViewer(
SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
/* aFireLocationChange */ true,
/* aIsInitialAboutBlank */ true, /* aLocationFlags */ 0);
/* aIsInitialAboutBlank */ true,
/* aLocationFlags */ 0);
rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
}
}
@@ -7561,7 +7566,8 @@ nsresult nsDocShell::RestoreFromHistory() {
// is still mLSHE or whether it's now mOSHE.
nsCOMPtr<nsIURI> uri = origLSHE->GetURI();
SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true,
/* aIsInitialAboutBlank */ false, /* aLocationFlags */ 0);
/* aIsInitialAboutBlank */ false,
/* aLocationFlags */ 0);
}
// This is the end of our CreateContentViewer() replacement.
@@ -8839,6 +8845,7 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
if (aLoadState->GetLoadingSessionHistoryInfo()) {
mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
*aLoadState->GetLoadingSessionHistoryInfo());
mNeedToReportActiveAfterLoadingBecomesActive = false;
}
// Set the doc's URI according to the new history entry's URI.
@@ -10116,6 +10123,14 @@ nsIPrincipal* nsDocShell::GetInheritedPrincipal(
return true;
}
bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank(
nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) {
return NS_IsAboutBlank(aURI) && aInheritPrincipal &&
(aPrincipalToInherit == GetInheritedPrincipal(false)) &&
(!mContentViewer || !mContentViewer->GetDocument() ||
mContentViewer->GetDocument()->IsInitialDocument());
}
nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
Maybe<uint32_t> aCacheKey,
nsIRequest** aRequest) {
@@ -10257,11 +10272,44 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
"DoURILoad thinks this is a document and InternalLoad does not");
}
// We want to inherit aLoadState->PrincipalToInherit() when:
// 1. ChannelShouldInheritPrincipal returns true.
// 2. aLoadState->URI() is not data: URI, or data: URI is not
// configured as unique opaque origin.
bool inheritPrincipal = false;
if (aLoadState->PrincipalToInherit()) {
bool isSrcdoc =
aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
aLoadState->PrincipalToInherit(), aLoadState->URI(),
true, // aInheritForAboutBlank
isSrcdoc);
inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI());
}
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
const bool isAboutBlankLoadOntoInitialAboutBlank =
IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal,
aLoadState->PrincipalToInherit());
// FIXME We still have a ton of codepaths that don't pass through
// DocumentLoadListener, so probably need to create session history info
// in more places.
if (aLoadState->GetLoadingSessionHistoryInfo()) {
SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
} else if (isAboutBlankLoadOntoInitialAboutBlank &&
mozilla::SessionHistoryInParent()) {
// Materialize LoadingSessionHistoryInfo here, because DocumentChannel
// loads have it, and later history behavior depends on it existing.
UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
aLoadState->URI(), aLoadState->TriggeringPrincipal(),
aLoadState->PrincipalToInherit(),
aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
mContentTypeHint);
mozilla::dom::LoadingSessionHistoryInfo info(*entry);
SetLoadingSessionHistoryInfo(info, true);
}
// open a channel for the url
@@ -10345,23 +10393,6 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
return NS_ERROR_FAILURE;
}
// We want to inherit aLoadState->PrincipalToInherit() when:
// 1. ChannelShouldInheritPrincipal returns true.
// 2. aLoadState->URI() is not data: URI, or data: URI is not
// configured as unique opaque origin.
bool inheritPrincipal = false;
if (aLoadState->PrincipalToInherit()) {
bool isSrcdoc =
aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
aLoadState->PrincipalToInherit(), aLoadState->URI(),
true, // aInheritForAboutBlank
isSrcdoc);
inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI());
}
uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
nsSecurityFlags securityFlags =
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
@@ -10394,6 +10425,30 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
sandboxFlags);
RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
if (isAboutBlankLoadOntoInitialAboutBlank) {
// Match the DocumentChannel case where the default for third-partiness
// differs from the default in LoadInfo construction here.
// toolkit/components/antitracking/test/browser/browser_aboutblank.js
// fails without this.
BrowsingContext* top = mBrowsingContext->Top();
if (top == mBrowsingContext) {
// If we're at the top, this must be a window.open()ed
// window, and we can't be third-party relative to ourselves.
loadInfo->SetIsThirdPartyContextToTopWindow(false);
} else {
if (Document* topDoc = top->GetDocument()) {
bool thirdParty = false;
mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal(
aLoadState->PrincipalToInherit(), &thirdParty);
loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
} else {
// If top is in a different process, we have to be third-party relative
// to it.
loadInfo->SetIsThirdPartyContextToTopWindow(true);
}
}
}
if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess() &&
context->HasValidTransientUserGestureActivation()) {
aLoadState->SetHasValidUserGestureActivation(true);
@@ -10461,7 +10516,8 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
currentUnstrippedURI);
nsCOMPtr<nsIChannel> channel;
if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI())) {
if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
!isAboutBlankLoadOntoInitialAboutBlank) {
channel = DocumentChannel::CreateForDocument(aLoadState, loadInfo,
loadFlags, this, cacheKey,
uriModified, isXFOError);
@@ -13541,13 +13597,16 @@ bool nsDocShell::GetIsAttemptingToNavigate() {
}
void nsDocShell::SetLoadingSessionHistoryInfo(
const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo) {
const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
bool aNeedToReportActiveAfterLoadingBecomesActive) {
// FIXME Would like to assert this, but can't yet.
// MOZ_ASSERT(!mLoadingEntry);
MOZ_LOG(gSHLog, LogLevel::Debug,
("Setting the loading entry on nsDocShell %p to %s", this,
aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get()));
mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
mNeedToReportActiveAfterLoadingBecomesActive =
aNeedToReportActiveAfterLoadingBecomesActive;
}
void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
@@ -13570,9 +13629,16 @@ void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
mLoadingEntry.swap(loadingEntry);
if (!mActiveEntryIsLoadingFromSessionHistory) {
if (mNeedToReportActiveAfterLoadingBecomesActive) {
// Needed to pass various history length WPTs.
mBrowsingContext->SetActiveSessionHistoryEntry(
mozilla::Nothing(), mActiveEntry.get(), mLoadType,
/* aUpdatedCacheKey = */ 0, false);
}
mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
}
}
mNeedToReportActiveAfterLoadingBecomesActive = false;
if (mActiveEntry) {
if (aCacheKey != 0) {
@@ -13582,12 +13648,14 @@ void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
uint32_t loadType =
mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
// We're passing in mCurrentURI, which could be null. SessionHistoryCommit
// does require a non-null uri if this is for a refresh load of the same
// URI, but in that case mCurrentURI won't be null here.
mBrowsingContext->SessionHistoryCommit(*loadingEntry, loadType, mCurrentURI,
hadActiveEntry, aPersist, false,
aExpired, aCacheKey);
if (loadingEntry->mLoadId != UINT64_MAX) {
// We're passing in mCurrentURI, which could be null. SessionHistoryCommit
// does require a non-null uri if this is for a refresh load of the same
// URI, but in that case mCurrentURI won't be null here.
mBrowsingContext->SessionHistoryCommit(
*loadingEntry, loadType, mCurrentURI, hadActiveEntry, aPersist, false,
aExpired, aCacheKey);
}
}
}