forked from mirrors/gecko-dev
		
	 ca0550b32b
			
		
	
	
		ca0550b32b
		
	
	
	
	
		
			
			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 (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;
 | |
|   }
 | |
| }
 |