fune/docshell/base/nsDocShellLoadState.cpp
2018-11-17 19:30:36 +00:00

558 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)
, mIsFromProcessingFrameAttributes(false)
{
}
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 {
#ifndef ANDROID
MOZ_ASSERT(false, "LoadURI: System principal required.");
#endif
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 (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
mDocShellInternalLoadFlags |=
nsIDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
}
if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) {
mDocShellInternalLoadFlags |= nsIDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD;
}
if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CLASSIFIER) {
mDocShellInternalLoadFlags |=
nsIDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
}
if (mLoadFlags & 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;
}
}