forked from mirrors/gecko-dev
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 --HG-- rename : docshell/base/nsDocShellLoadInfo.cpp => docshell/base/nsDocShellLoadState.cpp rename : docshell/base/nsDocShellLoadInfo.h => docshell/base/nsDocShellLoadState.h extra : moz-landing-system : lando
554 lines
13 KiB
C++
554 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsDocShellLoadState.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsIDocShellTreeItem.h"
|
|
#include "nsIScriptSecurityManager.h"
|
|
#include "nsIWebNavigation.h"
|
|
|
|
#include "mozilla/OriginAttributes.h"
|
|
#include "mozilla/NullPrincipal.h"
|
|
|
|
nsDocShellLoadState::nsDocShellLoadState()
|
|
: mResultPrincipalURIIsSome(false)
|
|
, mKeepResultPrincipalURIIfSet(false)
|
|
, mLoadReplace(false)
|
|
, mInheritPrincipal(false)
|
|
, mPrincipalIsExplicit(false)
|
|
, mForceAllowDataURI(false)
|
|
, mOriginalFrameSrc(false)
|
|
, mSendReferrer(true)
|
|
, mReferrerPolicy(mozilla::net::RP_Unset)
|
|
, mLoadType(LOAD_NORMAL)
|
|
, mIsSrcdocLoad(false)
|
|
, mLoadFlags(0)
|
|
, mFirstParty(false)
|
|
, mTypeHint(VoidCString())
|
|
, mFileName(VoidString())
|
|
, mDocShellInternalLoadFlags(0)
|
|
{
|
|
}
|
|
|
|
nsDocShellLoadState::~nsDocShellLoadState()
|
|
{
|
|
}
|
|
|
|
nsIURI*
|
|
nsDocShellLoadState::Referrer() const
|
|
{
|
|
return mReferrer;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetReferrer(nsIURI* aReferrer)
|
|
{
|
|
mReferrer = aReferrer;
|
|
}
|
|
|
|
nsIURI*
|
|
nsDocShellLoadState::URI() const
|
|
{
|
|
return mURI;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetURI(nsIURI* aURI)
|
|
{
|
|
mURI = aURI;
|
|
}
|
|
|
|
nsIURI*
|
|
nsDocShellLoadState::OriginalURI() const
|
|
{
|
|
return mOriginalURI;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetOriginalURI(nsIURI* aOriginalURI)
|
|
{
|
|
mOriginalURI = aOriginalURI;
|
|
}
|
|
|
|
nsIURI*
|
|
nsDocShellLoadState::ResultPrincipalURI() const
|
|
{
|
|
return mResultPrincipalURI;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetResultPrincipalURI(nsIURI* aResultPrincipalURI)
|
|
{
|
|
mResultPrincipalURI = aResultPrincipalURI;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::ResultPrincipalURIIsSome() const
|
|
{
|
|
return mResultPrincipalURIIsSome;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetResultPrincipalURIIsSome(bool aIsSome)
|
|
{
|
|
mResultPrincipalURIIsSome = aIsSome;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::KeepResultPrincipalURIIfSet() const
|
|
{
|
|
return mKeepResultPrincipalURIIfSet;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetKeepResultPrincipalURIIfSet(bool aKeep)
|
|
{
|
|
mKeepResultPrincipalURIIfSet = aKeep;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::LoadReplace() const
|
|
{
|
|
return mLoadReplace;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetLoadReplace(bool aLoadReplace)
|
|
{
|
|
mLoadReplace = aLoadReplace;
|
|
}
|
|
|
|
nsIPrincipal*
|
|
nsDocShellLoadState::TriggeringPrincipal() const
|
|
{
|
|
return mTriggeringPrincipal;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
|
|
{
|
|
mTriggeringPrincipal = aTriggeringPrincipal;
|
|
}
|
|
|
|
nsIPrincipal*
|
|
nsDocShellLoadState::PrincipalToInherit() const
|
|
{
|
|
return mPrincipalToInherit;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit)
|
|
{
|
|
mPrincipalToInherit = aPrincipalToInherit;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::InheritPrincipal() const
|
|
{
|
|
return mInheritPrincipal;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetInheritPrincipal(bool aInheritPrincipal)
|
|
{
|
|
mInheritPrincipal = aInheritPrincipal;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::PrincipalIsExplicit() const
|
|
{
|
|
return mPrincipalIsExplicit;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetPrincipalIsExplicit(bool aPrincipalIsExplicit)
|
|
{
|
|
mPrincipalIsExplicit = aPrincipalIsExplicit;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::ForceAllowDataURI() const
|
|
{
|
|
return mForceAllowDataURI;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetForceAllowDataURI(bool aForceAllowDataURI)
|
|
{
|
|
mForceAllowDataURI = aForceAllowDataURI;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::OriginalFrameSrc() const
|
|
{
|
|
return mOriginalFrameSrc;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetOriginalFrameSrc(bool aOriginalFrameSrc)
|
|
{
|
|
mOriginalFrameSrc = aOriginalFrameSrc;
|
|
}
|
|
|
|
uint32_t
|
|
nsDocShellLoadState::LoadType() const
|
|
{
|
|
return mLoadType;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetLoadType(uint32_t aLoadType)
|
|
{
|
|
mLoadType = aLoadType;
|
|
}
|
|
|
|
nsISHEntry*
|
|
nsDocShellLoadState::SHEntry() const
|
|
{
|
|
return mSHEntry;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetSHEntry(nsISHEntry* aSHEntry)
|
|
{
|
|
mSHEntry = aSHEntry;
|
|
}
|
|
|
|
const nsString&
|
|
nsDocShellLoadState::Target() const
|
|
{
|
|
return mTarget;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetTarget(const nsAString& aTarget)
|
|
{
|
|
mTarget = aTarget;
|
|
}
|
|
|
|
nsIInputStream*
|
|
nsDocShellLoadState::PostDataStream() const
|
|
{
|
|
return mPostDataStream;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetPostDataStream(nsIInputStream* aStream)
|
|
{
|
|
mPostDataStream = aStream;
|
|
}
|
|
|
|
nsIInputStream*
|
|
nsDocShellLoadState::HeadersStream() const
|
|
{
|
|
return mHeadersStream;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetHeadersStream(nsIInputStream* aHeadersStream)
|
|
{
|
|
mHeadersStream = aHeadersStream;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::SendReferrer() const
|
|
{
|
|
return mSendReferrer;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetSendReferrer(bool aSendReferrer)
|
|
{
|
|
mSendReferrer = aSendReferrer;
|
|
}
|
|
|
|
uint32_t
|
|
nsDocShellLoadState::ReferrerPolicy() const
|
|
{
|
|
return mReferrerPolicy;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetReferrerPolicy(mozilla::net::ReferrerPolicy aReferrerPolicy)
|
|
{
|
|
mReferrerPolicy = aReferrerPolicy;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::IsSrcdocLoad() const
|
|
{
|
|
return mIsSrcdocLoad;
|
|
}
|
|
|
|
const nsString&
|
|
nsDocShellLoadState::SrcdocData() const
|
|
{
|
|
return mSrcdocData;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetSrcdocData(const nsAString& aSrcdocData)
|
|
{
|
|
mSrcdocData = aSrcdocData;
|
|
mIsSrcdocLoad = true;
|
|
}
|
|
|
|
nsIDocShell*
|
|
nsDocShellLoadState::SourceDocShell() const
|
|
{
|
|
return mSourceDocShell;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetSourceDocShell(nsIDocShell* aSourceDocShell)
|
|
{
|
|
mSourceDocShell = aSourceDocShell;
|
|
}
|
|
|
|
nsIURI*
|
|
nsDocShellLoadState::BaseURI() const
|
|
{
|
|
return mBaseURI;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetBaseURI(nsIURI* aBaseURI)
|
|
{
|
|
mBaseURI = aBaseURI;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::GetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const
|
|
{
|
|
bool isSome = ResultPrincipalURIIsSome();
|
|
aRPURI.reset();
|
|
|
|
if (!isSome) {
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> uri = ResultPrincipalURI();
|
|
aRPURI.emplace(std::move(uri));
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI)
|
|
{
|
|
SetResultPrincipalURI(aRPURI.refOr(nullptr));
|
|
SetResultPrincipalURIIsSome(aRPURI.isSome());
|
|
}
|
|
|
|
uint32_t
|
|
nsDocShellLoadState::LoadFlags() const
|
|
{
|
|
return mLoadFlags;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetLoadFlags(uint32_t aLoadFlags)
|
|
{
|
|
mLoadFlags = aLoadFlags;
|
|
}
|
|
|
|
bool
|
|
nsDocShellLoadState::FirstParty() const
|
|
{
|
|
return mFirstParty;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetFirstParty(bool aFirstParty)
|
|
{
|
|
mFirstParty = aFirstParty;
|
|
}
|
|
|
|
const nsCString&
|
|
nsDocShellLoadState::TypeHint() const
|
|
{
|
|
return mTypeHint;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetTypeHint(const nsCString& aTypeHint)
|
|
{
|
|
mTypeHint = aTypeHint;
|
|
}
|
|
|
|
const nsString&
|
|
nsDocShellLoadState::FileName() const
|
|
{
|
|
return mFileName;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetFileName(const nsAString& aFileName)
|
|
{
|
|
mFileName = aFileName;
|
|
}
|
|
|
|
uint32_t
|
|
nsDocShellLoadState::DocShellInternalLoadFlags() const
|
|
{
|
|
return mDocShellInternalLoadFlags;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::SetDocShellInternalLoadFlags(uint32_t aFlags)
|
|
{
|
|
mDocShellInternalLoadFlags = aFlags;
|
|
}
|
|
|
|
|
|
nsresult
|
|
nsDocShellLoadState::SetupInheritingPrincipal(uint32_t aItemType,
|
|
const mozilla::OriginAttributes& aOriginAttributes)
|
|
{
|
|
// 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.
|
|
mPrincipalToInherit = mTriggeringPrincipal;
|
|
if (mPrincipalToInherit && aItemType != nsIDocShellTreeItem::typeChrome) {
|
|
if (nsContentUtils::IsSystemPrincipal(mPrincipalToInherit)) {
|
|
if (mPrincipalIsExplicit) {
|
|
return NS_ERROR_DOM_SECURITY_ERR;
|
|
}
|
|
mPrincipalToInherit = nullptr;
|
|
mInheritPrincipal = true;
|
|
} else if (nsContentUtils::IsExpandedPrincipal(mPrincipalToInherit)) {
|
|
if (mPrincipalIsExplicit) {
|
|
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.
|
|
mPrincipalToInherit =
|
|
NullPrincipal::CreateWithInheritedAttributes(aOriginAttributes,
|
|
false);
|
|
mInheritPrincipal = false;
|
|
}
|
|
}
|
|
|
|
if (!mPrincipalToInherit && !mInheritPrincipal && !mPrincipalIsExplicit) {
|
|
// See if there's system or chrome JS code running
|
|
mInheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
|
|
}
|
|
|
|
if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
|
|
mInheritPrincipal = false;
|
|
// If mFirstParty is true and the pref 'privacy.firstparty.isolate' is
|
|
// enabled, we will set firstPartyDomain on the origin attributes.
|
|
mPrincipalToInherit =
|
|
NullPrincipal::CreateWithInheritedAttributes(aOriginAttributes,
|
|
mFirstParty);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsDocShellLoadState::SetupTriggeringPrincipal(const mozilla::OriginAttributes& aOriginAttributes)
|
|
{
|
|
// If the triggeringPrincipal is not set, 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 (!mTriggeringPrincipal) {
|
|
if (mReferrer) {
|
|
mTriggeringPrincipal =
|
|
BasePrincipal::CreateCodebasePrincipal(mReferrer, aOriginAttributes);
|
|
|
|
if (!mTriggeringPrincipal) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
} else {
|
|
mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsDocShellLoadState::CalculateDocShellInternalLoadFlags()
|
|
{
|
|
MOZ_ASSERT(mDocShellInternalLoadFlags == 0,
|
|
"Shouldn't have any load flags set at this point.");
|
|
|
|
if (mInheritPrincipal) {
|
|
MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(mPrincipalToInherit),
|
|
"Should not inherit SystemPrincipal");
|
|
mDocShellInternalLoadFlags |=
|
|
nsIDocShell::INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
|
|
}
|
|
|
|
if (!mSendReferrer) {
|
|
mDocShellInternalLoadFlags |=
|
|
nsIDocShell::INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
|
|
}
|
|
|
|
if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
|
|
mDocShellInternalLoadFlags |=
|
|
nsIDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
|
}
|
|
|
|
if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) {
|
|
mDocShellInternalLoadFlags |= nsIDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD;
|
|
}
|
|
|
|
if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CLASSIFIER) {
|
|
mDocShellInternalLoadFlags |=
|
|
nsIDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
|
|
}
|
|
|
|
if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
|
|
mDocShellInternalLoadFlags |=
|
|
nsIDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
|
|
}
|
|
|
|
if (mIsSrcdocLoad) {
|
|
mDocShellInternalLoadFlags |= nsIDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
|
|
}
|
|
|
|
if (mForceAllowDataURI) {
|
|
mDocShellInternalLoadFlags |=
|
|
nsIDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
|
|
}
|
|
|
|
if (mOriginalFrameSrc) {
|
|
mDocShellInternalLoadFlags |=
|
|
nsIDocShell::INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC;
|
|
}
|
|
}
|