Bug 1492648 - Move from nsDocShellLoadInfo to nsDocShellLoadState r=bzbarsky,nika
Creates the nsDocShellLoadState object, which is basically nsDocShellLoadInfo plus a few extra fields to make it usable as a single argument to nsDocShell::LoadURI (and eventually nsDocShell::InternalLoad). Subframe history handling is a huge logic block in nsDocShell::LoadURI, which is only used on history loads. This patch also extracts the logic out into its own function to make the body of LoadURI clearer. Differential Revision: https://phabricator.services.mozilla.com/D6944
This commit is contained in:
@@ -169,7 +169,7 @@
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsDocShellEditorData.h"
|
||||
#include "nsDocShellEnumerator.h"
|
||||
#include "nsDocShellLoadInfo.h"
|
||||
#include "nsDocShellLoadState.h"
|
||||
#include "nsDocShellLoadTypes.h"
|
||||
#include "nsDOMCID.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
@@ -643,14 +643,12 @@ nsDocShell::GetInterface(const nsIID& aIID, void** aSink)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::LoadURI(nsIURI* aURI,
|
||||
nsDocShellLoadInfo* aLoadInfo,
|
||||
uint32_t aLoadFlags,
|
||||
bool aFirstParty)
|
||||
nsDocShell::LoadURI(nsDocShellLoadState* aLoadState)
|
||||
{
|
||||
MOZ_ASSERT(aLoadInfo || (aLoadFlags & EXTRA_LOAD_FLAGS) == 0,
|
||||
"Unexpected flags");
|
||||
MOZ_ASSERT((aLoadFlags & 0xf) == 0, "Should not have these flags set");
|
||||
MOZ_ASSERT(aLoadState, "Must have a valid load state!");
|
||||
MOZ_ASSERT((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,
|
||||
"Should not have these flags set");
|
||||
MOZ_ASSERT(aLoadState->URI(), "Should have a valid URI to load");
|
||||
|
||||
// Note: we allow loads to get through here even if mFiredUnloadEvent is
|
||||
// true; that case will get handled in LoadInternal or LoadHistoryEntry,
|
||||
@@ -662,86 +660,121 @@ nsDocShell::LoadURI(nsIURI* aURI,
|
||||
return NS_OK; // JS may not handle returning of an error code
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
|
||||
bool keepResultPrincipalURIIfSet = false;
|
||||
bool loadReplace = false;
|
||||
nsCOMPtr<nsIInputStream> postStream;
|
||||
nsCOMPtr<nsIInputStream> headersStream;
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
|
||||
bool inheritPrincipal = false;
|
||||
bool principalIsExplicit = false;
|
||||
bool sendReferrer = true;
|
||||
uint32_t referrerPolicy = RP_Unset;
|
||||
bool isSrcdoc = false;
|
||||
nsCOMPtr<nsISHEntry> shEntry;
|
||||
nsString target;
|
||||
nsAutoString srcdoc;
|
||||
bool forceAllowDataURI = false;
|
||||
bool originalFrameSrc = false;
|
||||
nsCOMPtr<nsIDocShell> sourceDocShell;
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
|
||||
uint32_t loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
|
||||
|
||||
NS_ENSURE_ARG(aURI);
|
||||
|
||||
if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
|
||||
mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
|
||||
mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
|
||||
StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
|
||||
}
|
||||
|
||||
// Extract the info from the DocShellLoadInfo struct...
|
||||
if (aLoadInfo) {
|
||||
referrer = aLoadInfo->Referrer();
|
||||
originalURI = aLoadInfo->OriginalURI();
|
||||
aLoadInfo->GetMaybeResultPrincipalURI(resultPrincipalURI);
|
||||
keepResultPrincipalURIIfSet = aLoadInfo->KeepResultPrincipalURIIfSet();
|
||||
loadReplace = aLoadInfo->LoadReplace();
|
||||
// Get the appropriate loadType from nsIDocShellLoadInfo type
|
||||
loadType = aLoadInfo->LoadType();
|
||||
|
||||
triggeringPrincipal = aLoadInfo->TriggeringPrincipal();
|
||||
inheritPrincipal = aLoadInfo->InheritPrincipal();
|
||||
principalIsExplicit = aLoadInfo->PrincipalIsExplicit();
|
||||
shEntry = aLoadInfo->SHEntry();
|
||||
aLoadInfo->GetTarget(target);
|
||||
postStream = aLoadInfo->PostDataStream();
|
||||
headersStream = aLoadInfo->HeadersStream();
|
||||
sendReferrer = aLoadInfo->SendReferrer();
|
||||
referrerPolicy = aLoadInfo->ReferrerPolicy();
|
||||
isSrcdoc = aLoadInfo->IsSrcdocLoad();
|
||||
aLoadInfo->GetSrcdocData(srcdoc);
|
||||
sourceDocShell = aLoadInfo->SourceDocShell();
|
||||
baseURI = aLoadInfo->BaseURI();
|
||||
forceAllowDataURI = aLoadInfo->ForceAllowDataURI();
|
||||
originalFrameSrc = aLoadInfo->OriginalFrameSrc();
|
||||
}
|
||||
|
||||
MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,
|
||||
("nsDocShell[%p]: loading %s with flags 0x%08x",
|
||||
this, aURI->GetSpecOrDefault().get(), aLoadFlags));
|
||||
this, aLoadState->URI()->GetSpecOrDefault().get(),
|
||||
aLoadState->LoadFlags()));
|
||||
|
||||
if (!shEntry &&
|
||||
!LOAD_TYPE_HAS_FLAGS(loadType, LOAD_FLAGS_REPLACE_HISTORY)) {
|
||||
// First verify if this is a subframe.
|
||||
if (!aLoadState->SHEntry() &&
|
||||
!LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),
|
||||
LOAD_FLAGS_REPLACE_HISTORY)) {
|
||||
// This is possibly a subframe, so handle it accordingly.
|
||||
//
|
||||
// If history exists, it will be loaded into the aLoadState object, and the
|
||||
// LoadType will be changed.
|
||||
MaybeHandleSubframeHistory(aLoadState);
|
||||
}
|
||||
|
||||
if (aLoadState->SHEntry()) {
|
||||
#ifdef DEBUG
|
||||
MOZ_LOG(gDocShellLog, LogLevel::Debug,
|
||||
("nsDocShell[%p]: loading from session history", this));
|
||||
#endif
|
||||
|
||||
return LoadHistoryEntry(aLoadState->SHEntry(), aLoadState->LoadType());
|
||||
}
|
||||
|
||||
// On history navigation via Back/Forward buttons, don't execute
|
||||
// automatic JavaScript redirection such as |location.href = ...| or
|
||||
// |window.open()|
|
||||
//
|
||||
// LOAD_NORMAL: window.open(...) etc.
|
||||
// LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
|
||||
if ((aLoadState->LoadType() == LOAD_NORMAL ||
|
||||
aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
|
||||
ShouldBlockLoadingForBackButton()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Set up the inheriting principal in LoadState.
|
||||
nsresult rv = aLoadState->SetupInheritingPrincipal(mItemType, mOriginAttributes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aLoadState->SetupTriggeringPrincipal(mOriginAttributes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aLoadState->CalculateDocShellInternalLoadFlags();
|
||||
|
||||
mozilla::Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
|
||||
aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
|
||||
|
||||
MOZ_ASSERT(aLoadState->TypeHint().IsVoid(),
|
||||
"Typehint should be null when calling InternalLoad from LoadURI");
|
||||
MOZ_ASSERT(aLoadState->FileName().IsVoid(),
|
||||
"FileName should be null when calling InternalLoad from LoadURI");
|
||||
MOZ_ASSERT(aLoadState->SHEntry() == nullptr,
|
||||
"SHEntry should be null when calling InternalLoad from LoadURI");
|
||||
|
||||
return InternalLoad(aLoadState->URI(),
|
||||
aLoadState->OriginalURI(),
|
||||
resultPrincipalURI,
|
||||
aLoadState->KeepResultPrincipalURIIfSet(),
|
||||
aLoadState->LoadReplace(),
|
||||
aLoadState->Referrer(),
|
||||
aLoadState->ReferrerPolicy(),
|
||||
aLoadState->TriggeringPrincipal(),
|
||||
aLoadState->PrincipalToInherit(),
|
||||
aLoadState->DocShellInternalLoadFlags(),
|
||||
aLoadState->Target(),
|
||||
aLoadState->TypeHint(),
|
||||
aLoadState->FileName(),
|
||||
aLoadState->PostDataStream(),
|
||||
aLoadState->HeadersStream(),
|
||||
aLoadState->LoadType(),
|
||||
aLoadState->SHEntry(),
|
||||
aLoadState->FirstParty(),
|
||||
aLoadState->SrcdocData(),
|
||||
aLoadState->SourceDocShell(),
|
||||
aLoadState->BaseURI(),
|
||||
nullptr, // no nsIDocShell
|
||||
nullptr); // no nsIRequest
|
||||
}
|
||||
|
||||
void
|
||||
nsDocShell::MaybeHandleSubframeHistory(nsDocShellLoadState* aLoadState)
|
||||
{
|
||||
// First, verify if this is a subframe.
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
|
||||
GetSameTypeParent(getter_AddRefs(parentAsItem));
|
||||
nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
|
||||
uint32_t parentLoadType;
|
||||
|
||||
if (parentDS && parentDS != static_cast<nsIDocShell*>(this)) {
|
||||
/* OK. It is a subframe. Checkout the
|
||||
* parent's loadtype. If the parent was loaded thro' a history
|
||||
* mechanism, then get the SH entry for the child from the parent.
|
||||
* This is done to restore frameset navigation while going back/forward.
|
||||
* If the parent was loaded through any other loadType, set the
|
||||
* child's loadType too accordingly, so that session history does not
|
||||
* get confused.
|
||||
if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
|
||||
// This is the root docshell. If we got here while
|
||||
// executing an onLoad Handler,this load will not go
|
||||
// into session history.
|
||||
bool inOnLoadHandler = false;
|
||||
GetIsExecutingOnLoadHandler(&inOnLoadHandler);
|
||||
if (inOnLoadHandler) {
|
||||
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
|
||||
* loaded through a history mechanism, then get the SH entry for the child from
|
||||
* the parent. This is done to restore frameset navigation while going
|
||||
* back/forward. If the parent was loaded through any other loadType, set the
|
||||
* child's loadType too accordingly, so that session history does not get
|
||||
* confused.
|
||||
*/
|
||||
|
||||
// Get the parent's load type
|
||||
uint32_t parentLoadType;
|
||||
parentDS->GetLoadType(&parentLoadType);
|
||||
|
||||
// Get the ShEntry for the child from the parent
|
||||
@@ -749,13 +782,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
|
||||
bool oshe = false;
|
||||
parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
|
||||
bool dynamicallyAddedChild = mDynamicallyCreated;
|
||||
|
||||
if (!dynamicallyAddedChild && !oshe && currentSH) {
|
||||
currentSH->HasDynamicallyAddedChild(&dynamicallyAddedChild);
|
||||
}
|
||||
|
||||
if (!dynamicallyAddedChild) {
|
||||
// Only use the old SHEntry, if we're sure enough that
|
||||
// it wasn't originally for some other frame.
|
||||
nsCOMPtr<nsISHEntry> shEntry;
|
||||
parentDS->GetChildSHEntry(mChildOffset, getter_AddRefs(shEntry));
|
||||
aLoadState->SetSHEntry(shEntry);
|
||||
}
|
||||
|
||||
// Make some decisions on the child frame's loadType based on the
|
||||
@@ -768,58 +805,13 @@ nsDocShell::LoadURI(nsIURI* aURI,
|
||||
// currentSHEntry is null.
|
||||
nsCOMPtr<nsISHEntry> currentChildEntry;
|
||||
GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
|
||||
if (!mCurrentURI || (NS_IsAboutBlank(mCurrentURI) && !currentChildEntry)) {
|
||||
// This is a newly created frame. Check for exception cases first.
|
||||
// By default the subframe will inherit the parent's loadType.
|
||||
if (shEntry && (parentLoadType == LOAD_NORMAL ||
|
||||
parentLoadType == LOAD_LINK ||
|
||||
parentLoadType == LOAD_NORMAL_EXTERNAL)) {
|
||||
// The parent was loaded normally. In this case, this *brand new*
|
||||
// child really shouldn't have a SHEntry. If it does, it could be
|
||||
// because the parent is replacing an existing frame with a new frame,
|
||||
// in the onLoadHandler. We don't want this url to get into session
|
||||
// history. Clear off shEntry, and set load type to
|
||||
// LOAD_BYPASS_HISTORY.
|
||||
bool inOnLoadHandler = false;
|
||||
parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
|
||||
if (inOnLoadHandler) {
|
||||
loadType = LOAD_NORMAL_REPLACE;
|
||||
shEntry = nullptr;
|
||||
}
|
||||
} else if (parentLoadType == LOAD_REFRESH) {
|
||||
// Clear shEntry. For refresh loads, we have to load
|
||||
// what comes thro' the pipe, not what's in history.
|
||||
shEntry = nullptr;
|
||||
} else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
|
||||
(shEntry &&
|
||||
((parentLoadType & LOAD_CMD_HISTORY) ||
|
||||
(parentLoadType == LOAD_RELOAD_NORMAL) ||
|
||||
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
|
||||
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
|
||||
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
|
||||
// If the parent url, bypassed history or was loaded from
|
||||
// history, pass on the parent's loadType to the new child
|
||||
// frame too, so that the child frame will also
|
||||
// avoid getting into history.
|
||||
loadType = parentLoadType;
|
||||
} else if (parentLoadType == LOAD_ERROR_PAGE) {
|
||||
// If the parent document is an error page, we don't
|
||||
// want to update global/session history. However,
|
||||
// this child frame is not an error page.
|
||||
loadType = LOAD_BYPASS_HISTORY;
|
||||
} else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
|
||||
(parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
|
||||
(parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
|
||||
// the new frame should inherit the parent's load type so that it also
|
||||
// bypasses the cache and/or proxy
|
||||
loadType = parentLoadType;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry)) {
|
||||
// This is a pre-existing subframe. If
|
||||
// 1. The load of this frame was not originally initiated by session
|
||||
// history directly (i.e. (!shEntry) condition succeeded, but it can
|
||||
// still be a history load on parent which causes this frame being
|
||||
// loaded), and
|
||||
// loaded), which we checked with the above assert, and
|
||||
// 2. mCurrentURI is not null, nor the initial about:blank,
|
||||
// it is possible that a parent's onLoadHandler or even self's
|
||||
// onLoadHandler is loading a new page in this child. Check parent's and
|
||||
@@ -831,187 +823,57 @@ nsDocShell::LoadURI(nsIURI* aURI,
|
||||
GetBusyFlags(&selfBusy);
|
||||
if (parentBusy & BUSY_FLAGS_BUSY ||
|
||||
selfBusy & BUSY_FLAGS_BUSY) {
|
||||
loadType = LOAD_NORMAL_REPLACE;
|
||||
shEntry = nullptr;
|
||||
}
|
||||
}
|
||||
} // parentDS
|
||||
else {
|
||||
// This is the root docshell. If we got here while
|
||||
// executing an onLoad Handler,this load will not go
|
||||
// into session history.
|
||||
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
|
||||
aLoadState->SetSHEntry(nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a newly created frame. Check for exception cases first.
|
||||
// By default the subframe will inherit the parent's loadType.
|
||||
if (aLoadState->SHEntry() && (parentLoadType == LOAD_NORMAL ||
|
||||
parentLoadType == LOAD_LINK ||
|
||||
parentLoadType == LOAD_NORMAL_EXTERNAL)) {
|
||||
// The parent was loaded normally. In this case, this *brand new*
|
||||
// child really shouldn't have a SHEntry. If it does, it could be
|
||||
// because the parent is replacing an existing frame with a new frame,
|
||||
// in the onLoadHandler. We don't want this url to get into session
|
||||
// history. Clear off shEntry, and set load type to
|
||||
// LOAD_BYPASS_HISTORY.
|
||||
bool inOnLoadHandler = false;
|
||||
GetIsExecutingOnLoadHandler(&inOnLoadHandler);
|
||||
parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
|
||||
if (inOnLoadHandler) {
|
||||
loadType = LOAD_NORMAL_REPLACE;
|
||||
}
|
||||
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
|
||||
aLoadState->SetSHEntry(nullptr);
|
||||
}
|
||||
} // !shEntry
|
||||
|
||||
if (shEntry) {
|
||||
#ifdef DEBUG
|
||||
MOZ_LOG(gDocShellLog, LogLevel::Debug,
|
||||
("nsDocShell[%p]: loading from session history", this));
|
||||
#endif
|
||||
|
||||
return LoadHistoryEntry(shEntry, loadType);
|
||||
} else if (parentLoadType == LOAD_REFRESH) {
|
||||
// Clear shEntry. For refresh loads, we have to load
|
||||
// what comes through the pipe, not what's in history.
|
||||
aLoadState->SetSHEntry(nullptr);
|
||||
} else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
|
||||
(aLoadState->SHEntry() &&
|
||||
((parentLoadType & LOAD_CMD_HISTORY) ||
|
||||
(parentLoadType == LOAD_RELOAD_NORMAL) ||
|
||||
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
|
||||
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
|
||||
(parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
|
||||
// If the parent url, bypassed history or was loaded from
|
||||
// history, pass on the parent's loadType to the new child
|
||||
// frame too, so that the child frame will also
|
||||
// avoid getting into history.
|
||||
aLoadState->SetLoadType(parentLoadType);
|
||||
} else if (parentLoadType == LOAD_ERROR_PAGE) {
|
||||
// If the parent document is an error page, we don't
|
||||
// want to update global/session history. However,
|
||||
// this child frame is not an error page.
|
||||
aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
|
||||
} else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
|
||||
(parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
|
||||
(parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
|
||||
// the new frame should inherit the parent's load type so that it also
|
||||
// bypasses the cache and/or proxy
|
||||
aLoadState->SetLoadType(parentLoadType);
|
||||
}
|
||||
|
||||
// On history navigation via Back/Forward buttons, don't execute
|
||||
// automatic JavaScript redirection such as |location.href = ...| or
|
||||
// |window.open()|
|
||||
//
|
||||
// LOAD_NORMAL: window.open(...) etc.
|
||||
// LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
|
||||
if ((loadType == LOAD_NORMAL || loadType == LOAD_STOP_CONTENT) &&
|
||||
ShouldBlockLoadingForBackButton()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Perform the load...
|
||||
|
||||
// We need a principalToInherit.
|
||||
//
|
||||
// If principalIsExplicit is not set there are 4 possibilities:
|
||||
// (1) If the system principal or an expanded principal was passed
|
||||
// in and we're a typeContent docshell, inherit the principal
|
||||
// from the current document instead.
|
||||
// (2) In all other cases when the principal passed in is not null,
|
||||
// use that principal.
|
||||
// (3) If the caller has allowed inheriting from the current document,
|
||||
// or if we're being called from system code (eg chrome JS or pure
|
||||
// C++) then inheritPrincipal should be true and InternalLoad will get
|
||||
// a principal from the current document. If none of these things are
|
||||
// true, then
|
||||
// (4) we don't pass a principal into the channel, and a principal will be
|
||||
// created later from the channel's internal data.
|
||||
//
|
||||
// If principalIsExplicit *is* set, there are 4 possibilities
|
||||
// (1) If the system principal or an expanded principal was passed in
|
||||
// and we're a typeContent docshell, return an error.
|
||||
// (2) In all other cases when the principal passed in is not null,
|
||||
// use that principal.
|
||||
// (3) If the caller has allowed inheriting from the current document,
|
||||
// then inheritPrincipal should be true and InternalLoad will get
|
||||
// a principal from the current document. If none of these things are
|
||||
// true, then
|
||||
// (4) we dont' pass a principal into the channel, and a principal will be
|
||||
// created later from the channel's internal data.
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = triggeringPrincipal;
|
||||
if (principalToInherit && mItemType != typeChrome) {
|
||||
if (nsContentUtils::IsSystemPrincipal(principalToInherit)) {
|
||||
if (principalIsExplicit) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
principalToInherit = nullptr;
|
||||
inheritPrincipal = true;
|
||||
} else if (nsContentUtils::IsExpandedPrincipal(principalToInherit)) {
|
||||
if (principalIsExplicit) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
// Don't inherit from the current page. Just do the safe thing
|
||||
// and pretend that we were loaded by a nullprincipal.
|
||||
//
|
||||
// We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
|
||||
// have origin attributes.
|
||||
principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this);
|
||||
inheritPrincipal = false;
|
||||
}
|
||||
}
|
||||
if (!principalToInherit && !inheritPrincipal && !principalIsExplicit) {
|
||||
// See if there's system or chrome JS code running
|
||||
inheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
|
||||
}
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
|
||||
inheritPrincipal = false;
|
||||
// If aFirstParty is true and the pref 'privacy.firstparty.isolate' is
|
||||
// enabled, we will set firstPartyDomain on the origin attributes.
|
||||
principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this, aFirstParty);
|
||||
}
|
||||
|
||||
// If the triggeringPrincipal is not passed explicitly, we first try to create
|
||||
// a principal from the referrer, since the referrer URI reflects the web origin
|
||||
// that triggered the load. If there is no referrer URI, we fall back to using
|
||||
// the SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
|
||||
// and no referrer simulate a load that was triggered by the system.
|
||||
// It's important to note that this block of code needs to appear *after* the block
|
||||
// where we munge the principalToInherit, because otherwise we would never enter
|
||||
// code blocks checking if the principalToInherit is null and we will end up with
|
||||
// a wrong inheritPrincipal flag.
|
||||
if (!triggeringPrincipal) {
|
||||
if (referrer) {
|
||||
nsresult rv = CreatePrincipalFromReferrer(referrer,
|
||||
getter_AddRefs(triggeringPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (inheritPrincipal) {
|
||||
MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(principalToInherit), "Should not inherit SystemPrincipal");
|
||||
flags |= INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
|
||||
}
|
||||
|
||||
if (!sendReferrer) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
|
||||
}
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
}
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
|
||||
}
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
|
||||
}
|
||||
|
||||
if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
|
||||
}
|
||||
|
||||
if (isSrcdoc) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
|
||||
}
|
||||
|
||||
if (forceAllowDataURI) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
|
||||
}
|
||||
|
||||
if (originalFrameSrc) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC;
|
||||
}
|
||||
|
||||
return InternalLoad(aURI,
|
||||
originalURI,
|
||||
resultPrincipalURI,
|
||||
keepResultPrincipalURIIfSet,
|
||||
loadReplace,
|
||||
referrer,
|
||||
referrerPolicy,
|
||||
triggeringPrincipal,
|
||||
principalToInherit,
|
||||
flags,
|
||||
target,
|
||||
nullptr, // No type hint
|
||||
VoidString(), // No forced download
|
||||
postStream,
|
||||
headersStream,
|
||||
loadType,
|
||||
nullptr, // No SHEntry
|
||||
aFirstParty,
|
||||
srcdoc,
|
||||
sourceDocShell,
|
||||
baseURI,
|
||||
nullptr, // No nsIDocShell
|
||||
nullptr); // No nsIRequest
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4226,7 +4088,7 @@ nsDocShell::LoadURIWithOptions(const nsAString& aURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aTriggeringPrincipal)
|
||||
{
|
||||
NS_ASSERTION((aLoadFlags & 0xf) == 0, "Unexpected flags");
|
||||
NS_ASSERTION((aLoadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0, "Unexpected flags");
|
||||
|
||||
if (!IsNavigationAllowed()) {
|
||||
return NS_OK; // JS may not handle returning of an error code
|
||||
@@ -4321,27 +4183,28 @@ nsDocShell::LoadURIWithOptions(const nsAString& aURI,
|
||||
uint32_t extraFlags = (aLoadFlags & EXTRA_LOAD_FLAGS);
|
||||
aLoadFlags &= ~EXTRA_LOAD_FLAGS;
|
||||
|
||||
RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
|
||||
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
|
||||
|
||||
/*
|
||||
* If the user "Disables Protection on This Page", we have to make sure to
|
||||
* remember the users decision when opening links in child tabs [Bug 906190]
|
||||
*/
|
||||
uint32_t loadType;
|
||||
if (aLoadFlags & LOAD_FLAGS_ALLOW_MIXED_CONTENT) {
|
||||
loadType = MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, aLoadFlags);
|
||||
loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, aLoadFlags));
|
||||
} else {
|
||||
loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
|
||||
loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags));
|
||||
}
|
||||
|
||||
loadInfo->SetLoadType(loadType);
|
||||
loadInfo->SetPostDataStream(postStream);
|
||||
loadInfo->SetReferrer(aReferringURI);
|
||||
loadInfo->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
|
||||
loadInfo->SetHeadersStream(aHeaderStream);
|
||||
loadInfo->SetBaseURI(aBaseURI);
|
||||
loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
|
||||
loadInfo->SetForceAllowDataURI(forceAllowDataURI);
|
||||
loadState->SetURI(uri);
|
||||
loadState->SetLoadFlags(extraFlags);
|
||||
loadState->SetFirstParty(true);
|
||||
loadState->SetPostDataStream(postStream);
|
||||
loadState->SetReferrer(aReferringURI);
|
||||
loadState->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
|
||||
loadState->SetHeadersStream(aHeaderStream);
|
||||
loadState->SetBaseURI(aBaseURI);
|
||||
loadState->SetTriggeringPrincipal(aTriggeringPrincipal);
|
||||
loadState->SetForceAllowDataURI(forceAllowDataURI);
|
||||
|
||||
if (fixupInfo) {
|
||||
nsAutoString searchProvider, keyword;
|
||||
@@ -4350,7 +4213,7 @@ nsDocShell::LoadURIWithOptions(const nsAString& aURI,
|
||||
MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
|
||||
}
|
||||
|
||||
rv = LoadURI(uri, loadInfo, extraFlags, true);
|
||||
rv = LoadURI(loadState);
|
||||
|
||||
// Save URI string in case it's needed later when
|
||||
// sending to search engine service in EndPageLoad()
|
||||
@@ -4922,7 +4785,7 @@ nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, nsIChannel* aFa
|
||||
return InternalLoad(aErrorURI, nullptr, Nothing(), false, false, nullptr, RP_Unset,
|
||||
nsContentUtils::GetSystemPrincipal(), nullptr,
|
||||
INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
|
||||
nullptr, VoidString(), nullptr, nullptr,
|
||||
VoidCString(), VoidString(), nullptr, nullptr,
|
||||
LOAD_ERROR_PAGE, nullptr, true, VoidString(), this,
|
||||
nullptr, nullptr, nullptr);
|
||||
}
|
||||
@@ -4934,7 +4797,7 @@ nsDocShell::Reload(uint32_t aReloadFlags)
|
||||
return NS_OK; // JS may not handle returning of an error code
|
||||
}
|
||||
nsresult rv;
|
||||
NS_ASSERTION(((aReloadFlags & 0xf) == 0),
|
||||
NS_ASSERTION(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0),
|
||||
"Reload command not updated to use load flags!");
|
||||
NS_ASSERTION((aReloadFlags & EXTRA_LOAD_FLAGS) == 0,
|
||||
"Don't pass these flags to Reload");
|
||||
@@ -5022,7 +4885,7 @@ nsDocShell::Reload(uint32_t aReloadFlags)
|
||||
triggeringPrincipal,
|
||||
flags,
|
||||
EmptyString(), // No window target
|
||||
NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
|
||||
NS_LossyConvertUTF16toASCII(contentTypeHint),
|
||||
VoidString(), // No forced download
|
||||
nullptr, // No post data
|
||||
nullptr, // No headers data
|
||||
@@ -6274,22 +6137,22 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel
|
||||
{
|
||||
NS_ENSURE_ARG(aURI);
|
||||
|
||||
RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
|
||||
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
|
||||
|
||||
/* We do need to pass in a referrer, but we don't want it to
|
||||
* be sent to the server.
|
||||
*/
|
||||
loadInfo->SetSendReferrer(false);
|
||||
loadState->SetSendReferrer(false);
|
||||
|
||||
/* for most refreshes the current URI is an appropriate
|
||||
* internal referrer
|
||||
*/
|
||||
loadInfo->SetReferrer(mCurrentURI);
|
||||
loadState->SetReferrer(mCurrentURI);
|
||||
|
||||
loadInfo->SetOriginalURI(mCurrentURI);
|
||||
loadInfo->SetResultPrincipalURI(aURI);
|
||||
loadInfo->SetResultPrincipalURIIsSome(true);
|
||||
loadInfo->SetKeepResultPrincipalURIIfSet(true);
|
||||
loadState->SetOriginalURI(mCurrentURI);
|
||||
loadState->SetResultPrincipalURI(aURI);
|
||||
loadState->SetResultPrincipalURIIsSome(true);
|
||||
loadState->SetKeepResultPrincipalURIIfSet(true);
|
||||
|
||||
// Set the triggering pricipal to aPrincipal if available, or current
|
||||
// document's principal otherwise.
|
||||
@@ -6301,8 +6164,8 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel
|
||||
}
|
||||
principal = doc->NodePrincipal();
|
||||
}
|
||||
loadInfo->SetTriggeringPrincipal(principal);
|
||||
loadInfo->SetPrincipalIsExplicit(true);
|
||||
loadState->SetTriggeringPrincipal(principal);
|
||||
loadState->SetPrincipalIsExplicit(true);
|
||||
|
||||
/* Check if this META refresh causes a redirection
|
||||
* to another site.
|
||||
@@ -6315,7 +6178,7 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel
|
||||
* we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
|
||||
* Pass a REPLACE flag to LoadURI().
|
||||
*/
|
||||
loadInfo->SetLoadType(LOAD_NORMAL_REPLACE);
|
||||
loadState->SetLoadType(LOAD_NORMAL_REPLACE);
|
||||
|
||||
/* for redirects we mimic HTTP, which passes the
|
||||
* original referrer
|
||||
@@ -6323,17 +6186,21 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel
|
||||
nsCOMPtr<nsIURI> internalReferrer;
|
||||
GetReferringURI(getter_AddRefs(internalReferrer));
|
||||
if (internalReferrer) {
|
||||
loadInfo->SetReferrer(internalReferrer);
|
||||
loadState->SetReferrer(internalReferrer);
|
||||
}
|
||||
} else {
|
||||
loadInfo->SetLoadType(LOAD_REFRESH);
|
||||
loadState->SetLoadType(LOAD_REFRESH);
|
||||
}
|
||||
|
||||
loadState->SetURI(aURI);
|
||||
loadState->SetLoadFlags(nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
|
||||
loadState->SetFirstParty(true);
|
||||
|
||||
/*
|
||||
* LoadURI(...) will cancel all refresh timers... This causes the
|
||||
* Timer and its refreshData instance to be released...
|
||||
*/
|
||||
LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, true);
|
||||
LoadURI(loadState);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -9100,7 +8967,7 @@ public:
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
nsIPrincipal* aPrincipalToInherit,
|
||||
uint32_t aFlags,
|
||||
const char* aTypeHint,
|
||||
const nsACString& aTypeHint,
|
||||
nsIInputStream* aPostData,
|
||||
nsIInputStream* aHeadersData,
|
||||
uint32_t aLoadType,
|
||||
@@ -9110,6 +8977,7 @@ public:
|
||||
nsIDocShell* aSourceDocShell,
|
||||
nsIURI* aBaseURI)
|
||||
: mozilla::Runnable("InternalLoadEvent")
|
||||
, mTypeHint(aTypeHint)
|
||||
, mSrcdoc(aSrcdoc)
|
||||
, mDocShell(aDocShell)
|
||||
, mURI(aURI)
|
||||
@@ -9130,12 +8998,6 @@ public:
|
||||
, mSourceDocShell(aSourceDocShell)
|
||||
, mBaseURI(aBaseURI)
|
||||
{
|
||||
// Make sure to keep null things null as needed
|
||||
if (aTypeHint) {
|
||||
mTypeHint = aTypeHint;
|
||||
} else {
|
||||
mTypeHint.SetIsVoid(true);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
@@ -9148,8 +9010,7 @@ public:
|
||||
mReferrerPolicy,
|
||||
mTriggeringPrincipal, mPrincipalToInherit,
|
||||
mFlags, EmptyString(),
|
||||
mTypeHint.IsVoid() ? nullptr
|
||||
: mTypeHint.get(),
|
||||
mTypeHint,
|
||||
VoidString(), mPostData,
|
||||
mHeadersData, mLoadType, mSHEntry,
|
||||
mFirstParty, mSrcdoc, mSourceDocShell,
|
||||
@@ -9220,7 +9081,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipalToInherit,
|
||||
uint32_t aFlags,
|
||||
const nsAString& aWindowTarget,
|
||||
const char* aTypeHint,
|
||||
const nsACString& aTypeHint,
|
||||
const nsAString& aFileName,
|
||||
nsIInputStream* aPostData,
|
||||
nsIInputStream* aHeadersData,
|
||||
@@ -9501,31 +9362,31 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
MOZ_ASSERT(!aSHEntry);
|
||||
MOZ_ASSERT(aFirstParty); // Windowwatcher will assume this.
|
||||
|
||||
RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
|
||||
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
|
||||
|
||||
// Set up our loadinfo so it will do the load as much like we would have
|
||||
// as possible.
|
||||
loadInfo->SetReferrer(aReferrer);
|
||||
loadInfo->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
|
||||
loadInfo->SetSendReferrer(!(aFlags &
|
||||
loadState->SetReferrer(aReferrer);
|
||||
loadState->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
|
||||
loadState->SetSendReferrer(!(aFlags &
|
||||
INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
|
||||
loadInfo->SetOriginalURI(aOriginalURI);
|
||||
loadInfo->SetMaybeResultPrincipalURI(aResultPrincipalURI);
|
||||
loadInfo->SetKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet);
|
||||
loadInfo->SetLoadReplace(aLoadReplace);
|
||||
loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
|
||||
loadInfo->SetInheritPrincipal(
|
||||
loadState->SetOriginalURI(aOriginalURI);
|
||||
loadState->SetMaybeResultPrincipalURI(aResultPrincipalURI);
|
||||
loadState->SetKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet);
|
||||
loadState->SetLoadReplace(aLoadReplace);
|
||||
loadState->SetTriggeringPrincipal(aTriggeringPrincipal);
|
||||
loadState->SetInheritPrincipal(
|
||||
aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
|
||||
// Explicit principal because we do not want any guesses as to what the
|
||||
// principal to inherit is: it should be aTriggeringPrincipal.
|
||||
loadInfo->SetPrincipalIsExplicit(true);
|
||||
loadInfo->SetLoadType(LOAD_LINK);
|
||||
loadInfo->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
|
||||
loadState->SetPrincipalIsExplicit(true);
|
||||
loadState->SetLoadType(LOAD_LINK);
|
||||
loadState->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
|
||||
|
||||
rv = win->Open(NS_ConvertUTF8toUTF16(spec),
|
||||
aWindowTarget, // window name
|
||||
EmptyString(), // Features
|
||||
loadInfo,
|
||||
loadState,
|
||||
true, // aForceNoOpener
|
||||
getter_AddRefs(newWin));
|
||||
MOZ_ASSERT(!newWin);
|
||||
@@ -10336,7 +10197,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
uint32_t aReferrerPolicy,
|
||||
nsIPrincipal* aTriggeringPrincipal,
|
||||
nsIPrincipal* aPrincipalToInherit,
|
||||
const char* aTypeHint,
|
||||
const nsACString& aTypeHint,
|
||||
const nsAString& aFileName,
|
||||
nsIInputStream* aPostData,
|
||||
nsIInputStream* aHeadersData,
|
||||
@@ -10685,8 +10546,8 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
loadInfo->SetResultPrincipalURI(aResultPrincipalURI.ref());
|
||||
}
|
||||
|
||||
if (aTypeHint && *aTypeHint) {
|
||||
channel->SetContentType(nsDependentCString(aTypeHint));
|
||||
if (!aTypeHint.IsVoid()) {
|
||||
channel->SetContentType(aTypeHint);
|
||||
mContentTypeHint = aTypeHint;
|
||||
} else {
|
||||
mContentTypeHint.Truncate();
|
||||
@@ -12240,7 +12101,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
|
||||
principalToInherit,
|
||||
flags,
|
||||
EmptyString(), // No window target
|
||||
contentType.get(), // Type hint
|
||||
contentType, // Type hint
|
||||
VoidString(), // No forced file download
|
||||
postData, // Post data stream
|
||||
nullptr, // No headers stream
|
||||
@@ -13428,7 +13289,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
||||
aContent->NodePrincipal(),
|
||||
flags,
|
||||
target, // Window target
|
||||
NS_LossyConvertUTF16toASCII(typeHint).get(),
|
||||
NS_LossyConvertUTF16toASCII(typeHint),
|
||||
aFileName, // Download as file
|
||||
aPostDataStream, // Post data stream
|
||||
aHeadersDataStream, // Headers stream
|
||||
|
||||
Reference in New Issue
Block a user