mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-10-31 16:28:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			1453 lines
		
	
	
	
		
			52 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1453 lines
		
	
	
	
		
			52 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 "nsDocShell.h"
 | |
| #include "nsILoadInfo.h"
 | |
| #include "nsIProtocolHandler.h"
 | |
| #include "nsISHEntry.h"
 | |
| #include "nsIURIFixup.h"
 | |
| #include "nsIWebNavigation.h"
 | |
| #include "nsIChannel.h"
 | |
| #include "nsIURLQueryStringStripper.h"
 | |
| #include "nsIXULRuntime.h"
 | |
| #include "nsNetUtil.h"
 | |
| #include "nsQueryObject.h"
 | |
| #include "ReferrerInfo.h"
 | |
| #include "mozilla/BasePrincipal.h"
 | |
| #include "mozilla/ClearOnShutdown.h"
 | |
| #include "mozilla/Components.h"
 | |
| #include "mozilla/dom/BrowsingContext.h"
 | |
| #include "mozilla/dom/ContentChild.h"
 | |
| #include "mozilla/dom/ContentParent.h"
 | |
| #include "mozilla/dom/FormData.h"
 | |
| #include "mozilla/dom/LoadURIOptionsBinding.h"
 | |
| #include "mozilla/dom/nsHTTPSOnlyUtils.h"
 | |
| #include "mozilla/StaticPrefs_browser.h"
 | |
| #include "mozilla/StaticPrefs_fission.h"
 | |
| #include "mozilla/glean/AntitrackingMetrics.h"
 | |
| 
 | |
| #include "mozilla/OriginAttributes.h"
 | |
| #include "mozilla/NullPrincipal.h"
 | |
| #include "mozilla/StaticPtr.h"
 | |
| 
 | |
| #include "mozilla/dom/PContent.h"
 | |
| 
 | |
| using namespace mozilla;
 | |
| using namespace mozilla::dom;
 | |
| 
 | |
| // Global reference to the URI fixup service.
 | |
| static mozilla::StaticRefPtr<nsIURIFixup> sURIFixup;
 | |
| 
 | |
| nsDocShellLoadState::nsDocShellLoadState(nsIURI* aURI)
 | |
|     : nsDocShellLoadState(aURI, nsContentUtils::GenerateLoadIdentifier()) {}
 | |
| 
 | |
| nsDocShellLoadState::nsDocShellLoadState(
 | |
|     const DocShellLoadStateInit& aLoadState, mozilla::ipc::IProtocol* aActor,
 | |
|     bool* aReadSuccess)
 | |
|     : mNotifiedBeforeUnloadListeners(false),
 | |
|       mLoadIdentifier(aLoadState.LoadIdentifier()) {
 | |
|   // If we return early, we failed to read in the data.
 | |
|   *aReadSuccess = false;
 | |
|   if (!aLoadState.URI()) {
 | |
|     MOZ_ASSERT_UNREACHABLE("Cannot create a LoadState with a null URI!");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   mResultPrincipalURI = aLoadState.ResultPrincipalURI();
 | |
|   mResultPrincipalURIIsSome = aLoadState.ResultPrincipalURIIsSome();
 | |
|   mKeepResultPrincipalURIIfSet = aLoadState.KeepResultPrincipalURIIfSet();
 | |
|   mLoadReplace = aLoadState.LoadReplace();
 | |
|   mInheritPrincipal = aLoadState.InheritPrincipal();
 | |
|   mPrincipalIsExplicit = aLoadState.PrincipalIsExplicit();
 | |
|   mForceAllowDataURI = aLoadState.ForceAllowDataURI();
 | |
|   mIsExemptFromHTTPSFirstMode = aLoadState.IsExemptFromHTTPSFirstMode();
 | |
|   mOriginalFrameSrc = aLoadState.OriginalFrameSrc();
 | |
|   mShouldCheckForRecursion = aLoadState.ShouldCheckForRecursion();
 | |
|   mIsFormSubmission = aLoadState.IsFormSubmission();
 | |
|   mLoadType = aLoadState.LoadType();
 | |
|   mTarget = aLoadState.Target();
 | |
|   mTargetBrowsingContext = aLoadState.TargetBrowsingContext();
 | |
|   mLoadFlags = aLoadState.LoadFlags();
 | |
|   mInternalLoadFlags = aLoadState.InternalLoadFlags();
 | |
|   mFirstParty = aLoadState.FirstParty();
 | |
|   mHasValidUserGestureActivation = aLoadState.HasValidUserGestureActivation();
 | |
|   mTextDirectiveUserActivation = aLoadState.TextDirectiveUserActivation();
 | |
|   mAllowFocusMove = aLoadState.AllowFocusMove();
 | |
|   mTypeHint = aLoadState.TypeHint();
 | |
|   mFileName = aLoadState.FileName();
 | |
|   mIsFromProcessingFrameAttributes =
 | |
|       aLoadState.IsFromProcessingFrameAttributes();
 | |
|   mReferrerInfo = aLoadState.ReferrerInfo();
 | |
|   mURI = aLoadState.URI();
 | |
|   mOriginalURI = aLoadState.OriginalURI();
 | |
|   mSourceBrowsingContext = aLoadState.SourceBrowsingContext();
 | |
|   mBaseURI = aLoadState.BaseURI();
 | |
|   mTriggeringPrincipal = aLoadState.TriggeringPrincipal();
 | |
|   mPrincipalToInherit = aLoadState.PrincipalToInherit();
 | |
|   mPartitionedPrincipalToInherit = aLoadState.PartitionedPrincipalToInherit();
 | |
|   mTriggeringSandboxFlags = aLoadState.TriggeringSandboxFlags();
 | |
|   mTriggeringWindowId = aLoadState.TriggeringWindowId();
 | |
|   mTriggeringStorageAccess = aLoadState.TriggeringStorageAccess();
 | |
|   mTriggeringClassificationFlags = aLoadState.TriggeringClassificationFlags();
 | |
|   mTriggeringRemoteType = aLoadState.TriggeringRemoteType();
 | |
|   mSchemelessInput = aLoadState.SchemelessInput();
 | |
|   mHttpsUpgradeTelemetry = aLoadState.HttpsUpgradeTelemetry();
 | |
|   mCsp = aLoadState.Csp();
 | |
|   mOriginalURIString = aLoadState.OriginalURIString();
 | |
|   mCancelContentJSEpoch = aLoadState.CancelContentJSEpoch();
 | |
|   mPostDataStream = aLoadState.PostDataStream();
 | |
|   mHeadersStream = aLoadState.HeadersStream();
 | |
|   mSrcdocData = aLoadState.SrcdocData();
 | |
|   mChannelInitialized = aLoadState.ChannelInitialized();
 | |
|   mIsMetaRefresh = aLoadState.IsMetaRefresh();
 | |
|   if (aLoadState.loadingSessionHistoryInfo().isSome()) {
 | |
|     mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(
 | |
|         aLoadState.loadingSessionHistoryInfo().ref());
 | |
|   }
 | |
|   mUnstrippedURI = aLoadState.UnstrippedURI();
 | |
|   mRemoteTypeOverride = aLoadState.RemoteTypeOverride();
 | |
| 
 | |
|   // We know this was created remotely, as we just received it over IPC.
 | |
|   mWasCreatedRemotely = true;
 | |
| 
 | |
|   // If we're in the parent process, potentially validate against a LoadState
 | |
|   // which we sent to the source content process.
 | |
|   if (XRE_IsParentProcess()) {
 | |
|     mozilla::ipc::IToplevelProtocol* top = aActor->ToplevelProtocol();
 | |
|     if (!top ||
 | |
|         top->GetProtocolId() != mozilla::ipc::ProtocolId::PContentMsgStart ||
 | |
|         top->GetSide() != mozilla::ipc::ParentSide) {
 | |
|       aActor->FatalError("nsDocShellLoadState must be received over PContent");
 | |
|       return;
 | |
|     }
 | |
|     ContentParent* cp = static_cast<ContentParent*>(top);
 | |
| 
 | |
|     // If this load was sent down to the content process as a navigation
 | |
|     // request, ensure it still matches the one we sent down.
 | |
|     if (RefPtr<nsDocShellLoadState> originalState =
 | |
|             cp->TakePendingLoadStateForId(mLoadIdentifier)) {
 | |
|       if (const char* mismatch = ValidateWithOriginalState(originalState)) {
 | |
|         aActor->FatalError(
 | |
|             nsPrintfCString(
 | |
|                 "nsDocShellLoadState %s changed while in content process",
 | |
|                 mismatch)
 | |
|                 .get());
 | |
|         return;
 | |
|       }
 | |
|     } else if (mTriggeringRemoteType != cp->GetRemoteType()) {
 | |
|       // If we don't have a previous load to compare to, the content process
 | |
|       // must be the triggering process.
 | |
|       aActor->FatalError(
 | |
|           "nsDocShellLoadState with invalid triggering remote type");
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // We successfully read in the data - return a success value.
 | |
|   *aReadSuccess = true;
 | |
| }
 | |
| 
 | |
| nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
 | |
|     : mReferrerInfo(aOther.mReferrerInfo),
 | |
|       mURI(aOther.mURI),
 | |
|       mOriginalURI(aOther.mOriginalURI),
 | |
|       mResultPrincipalURI(aOther.mResultPrincipalURI),
 | |
|       mResultPrincipalURIIsSome(aOther.mResultPrincipalURIIsSome),
 | |
|       mTriggeringPrincipal(aOther.mTriggeringPrincipal),
 | |
|       mTriggeringSandboxFlags(aOther.mTriggeringSandboxFlags),
 | |
|       mTriggeringWindowId(aOther.mTriggeringWindowId),
 | |
|       mTriggeringStorageAccess(aOther.mTriggeringStorageAccess),
 | |
|       mTriggeringClassificationFlags(aOther.mTriggeringClassificationFlags),
 | |
|       mCsp(aOther.mCsp),
 | |
|       mKeepResultPrincipalURIIfSet(aOther.mKeepResultPrincipalURIIfSet),
 | |
|       mLoadReplace(aOther.mLoadReplace),
 | |
|       mInheritPrincipal(aOther.mInheritPrincipal),
 | |
|       mPrincipalIsExplicit(aOther.mPrincipalIsExplicit),
 | |
|       mNotifiedBeforeUnloadListeners(aOther.mNotifiedBeforeUnloadListeners),
 | |
|       mPrincipalToInherit(aOther.mPrincipalToInherit),
 | |
|       mPartitionedPrincipalToInherit(aOther.mPartitionedPrincipalToInherit),
 | |
|       mForceAllowDataURI(aOther.mForceAllowDataURI),
 | |
|       mIsExemptFromHTTPSFirstMode(aOther.mIsExemptFromHTTPSFirstMode),
 | |
|       mHttpsFirstDowngradeData(aOther.GetHttpsFirstDowngradeData()),
 | |
|       mOriginalFrameSrc(aOther.mOriginalFrameSrc),
 | |
|       mShouldCheckForRecursion(aOther.mShouldCheckForRecursion),
 | |
|       mIsFormSubmission(aOther.mIsFormSubmission),
 | |
|       mLoadType(aOther.mLoadType),
 | |
|       mSHEntry(aOther.mSHEntry),
 | |
|       mTarget(aOther.mTarget),
 | |
|       mTargetBrowsingContext(aOther.mTargetBrowsingContext),
 | |
|       mPostDataStream(aOther.mPostDataStream),
 | |
|       mHeadersStream(aOther.mHeadersStream),
 | |
|       mSrcdocData(aOther.mSrcdocData),
 | |
|       mSourceBrowsingContext(aOther.mSourceBrowsingContext),
 | |
|       mBaseURI(aOther.mBaseURI),
 | |
|       mLoadFlags(aOther.mLoadFlags),
 | |
|       mInternalLoadFlags(aOther.mInternalLoadFlags),
 | |
|       mFirstParty(aOther.mFirstParty),
 | |
|       mHasValidUserGestureActivation(aOther.mHasValidUserGestureActivation),
 | |
|       mTextDirectiveUserActivation(aOther.mTextDirectiveUserActivation),
 | |
|       mAllowFocusMove(aOther.mAllowFocusMove),
 | |
|       mTypeHint(aOther.mTypeHint),
 | |
|       mFileName(aOther.mFileName),
 | |
|       mIsFromProcessingFrameAttributes(aOther.mIsFromProcessingFrameAttributes),
 | |
|       mPendingRedirectedChannel(aOther.mPendingRedirectedChannel),
 | |
|       mOriginalURIString(aOther.mOriginalURIString),
 | |
|       mCancelContentJSEpoch(aOther.mCancelContentJSEpoch),
 | |
|       mLoadIdentifier(aOther.mLoadIdentifier),
 | |
|       mChannelInitialized(aOther.mChannelInitialized),
 | |
|       mIsMetaRefresh(aOther.mIsMetaRefresh),
 | |
|       mWasCreatedRemotely(aOther.mWasCreatedRemotely),
 | |
|       mUnstrippedURI(aOther.mUnstrippedURI),
 | |
|       mRemoteTypeOverride(aOther.mRemoteTypeOverride),
 | |
|       mTriggeringRemoteType(aOther.mTriggeringRemoteType),
 | |
|       mSchemelessInput(aOther.mSchemelessInput),
 | |
|       mHttpsUpgradeTelemetry(aOther.mHttpsUpgradeTelemetry) {
 | |
|   MOZ_DIAGNOSTIC_ASSERT(
 | |
|       XRE_IsParentProcess(),
 | |
|       "Cloning a nsDocShellLoadState with the same load identifier is only "
 | |
|       "allowed in the parent process, as it could break triggering remote type "
 | |
|       "tracking in content.");
 | |
|   if (aOther.mLoadingSessionHistoryInfo) {
 | |
|     mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(
 | |
|         *aOther.mLoadingSessionHistoryInfo);
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsDocShellLoadState::nsDocShellLoadState(nsIURI* aURI, uint64_t aLoadIdentifier)
 | |
|     : mURI(aURI),
 | |
|       mResultPrincipalURIIsSome(false),
 | |
|       mTriggeringSandboxFlags(0),
 | |
|       mTriggeringWindowId(0),
 | |
|       mTriggeringStorageAccess(false),
 | |
|       mTriggeringClassificationFlags({0, 0}),
 | |
|       mKeepResultPrincipalURIIfSet(false),
 | |
|       mLoadReplace(false),
 | |
|       mInheritPrincipal(false),
 | |
|       mPrincipalIsExplicit(false),
 | |
|       mNotifiedBeforeUnloadListeners(false),
 | |
|       mForceAllowDataURI(false),
 | |
|       mIsExemptFromHTTPSFirstMode(false),
 | |
|       mOriginalFrameSrc(false),
 | |
|       mShouldCheckForRecursion(false),
 | |
|       mIsFormSubmission(false),
 | |
|       mLoadType(LOAD_NORMAL),
 | |
|       mSrcdocData(VoidString()),
 | |
|       mLoadFlags(0),
 | |
|       mInternalLoadFlags(0),
 | |
|       mFirstParty(false),
 | |
|       mHasValidUserGestureActivation(false),
 | |
|       mAllowFocusMove(false),
 | |
|       mTypeHint(VoidCString()),
 | |
|       mFileName(VoidString()),
 | |
|       mIsFromProcessingFrameAttributes(false),
 | |
|       mLoadIdentifier(aLoadIdentifier),
 | |
|       mChannelInitialized(false),
 | |
|       mIsMetaRefresh(false),
 | |
|       mWasCreatedRemotely(false),
 | |
|       mTriggeringRemoteType(XRE_IsContentProcess()
 | |
|                                 ? ContentChild::GetSingleton()->GetRemoteType()
 | |
|                                 : NOT_REMOTE_TYPE),
 | |
|       mSchemelessInput(nsILoadInfo::SchemelessInputTypeUnset) {
 | |
|   MOZ_ASSERT(aURI, "Cannot create a LoadState with a null URI!");
 | |
| 
 | |
|   // For https telemetry we set a flag indicating whether the load is https.
 | |
|   // There are some corner cases, e.g. view-source and also about: pages.
 | |
|   // about: pages, when hitting the network, always redirect to https.
 | |
|   // Since we record https telemetry only within nsHTTPSChannel, it's fine
 | |
|   // to set the flag here.
 | |
|   nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
 | |
|   if (innerURI->SchemeIs("https") || innerURI->SchemeIs("about")) {
 | |
|     mHttpsUpgradeTelemetry = nsILoadInfo::ALREADY_HTTPS;
 | |
|   } else {
 | |
|     mHttpsUpgradeTelemetry = nsILoadInfo::NO_UPGRADE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsDocShellLoadState::~nsDocShellLoadState() {
 | |
|   if (mWasCreatedRemotely && XRE_IsContentProcess() &&
 | |
|       ContentChild::GetSingleton()->CanSend()) {
 | |
|     ContentChild::GetSingleton()->SendCleanupPendingLoadState(mLoadIdentifier);
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsresult nsDocShellLoadState::CreateFromPendingChannel(
 | |
|     nsIChannel* aPendingChannel, uint64_t aLoadIdentifier,
 | |
|     uint64_t aRegistrarId, nsDocShellLoadState** aResult) {
 | |
|   // Create the nsDocShellLoadState object with default state pulled from the
 | |
|   // passed-in channel.
 | |
|   nsCOMPtr<nsIURI> uri;
 | |
|   nsresult rv = aPendingChannel->GetURI(getter_AddRefs(uri));
 | |
|   if (NS_WARN_IF(NS_FAILED(rv))) {
 | |
|     return rv;
 | |
|   }
 | |
| 
 | |
|   RefPtr<nsDocShellLoadState> loadState =
 | |
|       new nsDocShellLoadState(uri, aLoadIdentifier);
 | |
|   loadState->mPendingRedirectedChannel = aPendingChannel;
 | |
|   loadState->mChannelRegistrarId = aRegistrarId;
 | |
| 
 | |
|   // Pull relevant state from the channel, and store it on the
 | |
|   // nsDocShellLoadState.
 | |
|   nsCOMPtr<nsIURI> originalUri;
 | |
|   rv = aPendingChannel->GetOriginalURI(getter_AddRefs(originalUri));
 | |
|   if (NS_WARN_IF(NS_FAILED(rv))) {
 | |
|     return rv;
 | |
|   }
 | |
|   loadState->SetOriginalURI(originalUri);
 | |
| 
 | |
|   nsCOMPtr<nsILoadInfo> loadInfo = aPendingChannel->LoadInfo();
 | |
|   loadState->SetTriggeringPrincipal(loadInfo->TriggeringPrincipal());
 | |
| 
 | |
|   // Return the newly created loadState.
 | |
|   loadState.forget(aResult);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| static uint32_t WebNavigationFlagsToFixupFlags(nsIURI* aURI,
 | |
|                                                const nsACString& aURIString,
 | |
|                                                uint32_t aNavigationFlags) {
 | |
|   if (aURI) {
 | |
|     aNavigationFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
 | |
|   }
 | |
|   uint32_t fixupFlags = nsIURIFixup::FIXUP_FLAG_NONE;
 | |
|   if (aNavigationFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
 | |
|     fixupFlags |= nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
 | |
|   }
 | |
|   if (aNavigationFlags & nsIWebNavigation::LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
 | |
|     fixupFlags |= nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS;
 | |
|   }
 | |
|   return fixupFlags;
 | |
| };
 | |
| 
 | |
| nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
 | |
|     BrowsingContext* aBrowsingContext, const nsAString& aURI,
 | |
|     const LoadURIOptions& aLoadURIOptions, nsDocShellLoadState** aResult) {
 | |
|   uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
 | |
| 
 | |
|   NS_ASSERTION(
 | |
|       (loadFlags & nsDocShell::INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,
 | |
|       "Unexpected flags");
 | |
| 
 | |
|   nsCOMPtr<nsIURI> uri;
 | |
|   nsresult rv = NS_OK;
 | |
| 
 | |
|   NS_ConvertUTF16toUTF8 uriString(aURI);
 | |
|   // Cleanup the empty spaces that might be on each end.
 | |
|   uriString.Trim(" ");
 | |
|   // Eliminate embedded newlines, which single-line text fields now allow:
 | |
|   uriString.StripCRLF();
 | |
|   NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
 | |
| 
 | |
|   // Just create a URI and see what happens...
 | |
|   rv = NS_NewURI(getter_AddRefs(uri), uriString);
 | |
|   bool fixup = true;
 | |
|   if (NS_SUCCEEDED(rv) && uri &&
 | |
|       (uri->SchemeIs("about") || uri->SchemeIs("chrome"))) {
 | |
|     // Avoid third party fixup as a performance optimization.
 | |
|     loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
 | |
|     fixup = false;
 | |
|   } else if (!sURIFixup && !XRE_IsContentProcess()) {
 | |
|     nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
 | |
|     if (uriFixup) {
 | |
|       sURIFixup = uriFixup;
 | |
|       ClearOnShutdown(&sURIFixup);
 | |
|     } else {
 | |
|       fixup = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   nsAutoString searchProvider, keyword;
 | |
|   RefPtr<nsIInputStream> fixupStream;
 | |
|   if (fixup) {
 | |
|     uint32_t fixupFlags =
 | |
|         WebNavigationFlagsToFixupFlags(uri, uriString, loadFlags);
 | |
| 
 | |
|     // If we don't allow keyword lookups for this URL string, make sure to
 | |
|     // update loadFlags to indicate this as well.
 | |
|     if (!(fixupFlags & nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) {
 | |
|       loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
 | |
|     }
 | |
|     // Ensure URIFixup will use the right search engine in Private Browsing.
 | |
|     if (aBrowsingContext->UsePrivateBrowsing()) {
 | |
|       fixupFlags |= nsIURIFixup::FIXUP_FLAG_PRIVATE_CONTEXT;
 | |
|     }
 | |
| 
 | |
|     if (!XRE_IsContentProcess()) {
 | |
|       nsCOMPtr<nsIURIFixupInfo> fixupInfo;
 | |
|       sURIFixup->GetFixupURIInfo(uriString, fixupFlags,
 | |
|                                  getter_AddRefs(fixupInfo));
 | |
|       if (fixupInfo) {
 | |
|         // We could fix the uri, clear NS_ERROR_MALFORMED_URI.
 | |
|         rv = NS_OK;
 | |
|         fixupInfo->GetPreferredURI(getter_AddRefs(uri));
 | |
|         fixupInfo->SetConsumer(aBrowsingContext);
 | |
|         fixupInfo->GetKeywordProviderName(searchProvider);
 | |
|         fixupInfo->GetKeywordAsSent(keyword);
 | |
|         // GetFixupURIInfo only returns a post data stream if it succeeded
 | |
|         // and changed the URI, in which case we should override the
 | |
|         // passed-in post data by passing this as an override arg to
 | |
|         // our internal method.
 | |
|         fixupInfo->GetPostData(getter_AddRefs(fixupStream));
 | |
| 
 | |
|         if (fixupInfo &&
 | |
|             loadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
 | |
|           nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
 | |
|           if (serv) {
 | |
|             serv->NotifyObservers(fixupInfo, "keyword-uri-fixup",
 | |
|                                   PromiseFlatString(aURI).get());
 | |
|           }
 | |
|         }
 | |
|         nsDocShell::MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (rv == NS_ERROR_MALFORMED_URI) {
 | |
|     MOZ_ASSERT(!uri);
 | |
|     return rv;
 | |
|   }
 | |
| 
 | |
|   if (NS_FAILED(rv) || !uri) {
 | |
|     return NS_ERROR_FAILURE;
 | |
|   }
 | |
| 
 | |
|   RefPtr<nsDocShellLoadState> loadState;
 | |
|   rv = CreateFromLoadURIOptions(
 | |
|       aBrowsingContext, uri, aLoadURIOptions, loadFlags,
 | |
|       fixupStream ? fixupStream : aLoadURIOptions.mPostData,
 | |
|       getter_AddRefs(loadState));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
|   loadState->SetOriginalURIString(uriString);
 | |
|   loadState.forget(aResult);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
 | |
|     BrowsingContext* aBrowsingContext, nsIURI* aURI,
 | |
|     const LoadURIOptions& aLoadURIOptions, nsDocShellLoadState** aResult) {
 | |
|   return CreateFromLoadURIOptions(aBrowsingContext, aURI, aLoadURIOptions,
 | |
|                                   aLoadURIOptions.mLoadFlags,
 | |
|                                   aLoadURIOptions.mPostData, aResult);
 | |
| }
 | |
| 
 | |
| nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
 | |
|     BrowsingContext* aBrowsingContext, nsIURI* aURI,
 | |
|     const LoadURIOptions& aLoadURIOptions, uint32_t aLoadFlagsOverride,
 | |
|     nsIInputStream* aPostDataOverride, nsDocShellLoadState** aResult) {
 | |
|   nsresult rv = NS_OK;
 | |
|   uint32_t loadFlags = aLoadFlagsOverride;
 | |
|   RefPtr<nsIInputStream> postData = aPostDataOverride;
 | |
|   uint64_t available;
 | |
|   if (postData) {
 | |
|     rv = postData->Available(&available);
 | |
|     NS_ENSURE_SUCCESS(rv, rv);
 | |
|     if (available == 0) {
 | |
|       return NS_ERROR_INVALID_ARG;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (aLoadURIOptions.mHeaders) {
 | |
|     rv = aLoadURIOptions.mHeaders->Available(&available);
 | |
|     NS_ENSURE_SUCCESS(rv, rv);
 | |
|     if (available == 0) {
 | |
|       return NS_ERROR_INVALID_ARG;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   bool forceAllowDataURI =
 | |
|       loadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
 | |
| 
 | |
|   // Don't pass certain flags that aren't needed and end up confusing
 | |
|   // ConvertLoadTypeToDocShellInfoLoadType.  We do need to ensure that they are
 | |
|   // passed to LoadURI though, since it uses them.
 | |
|   uint32_t extraFlags = (loadFlags & EXTRA_LOAD_FLAGS);
 | |
|   loadFlags &= ~EXTRA_LOAD_FLAGS;
 | |
| 
 | |
|   RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
 | |
|   loadState->SetReferrerInfo(aLoadURIOptions.mReferrerInfo);
 | |
| 
 | |
|   loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags));
 | |
| 
 | |
|   loadState->SetLoadFlags(extraFlags);
 | |
|   loadState->SetFirstParty(true);
 | |
|   loadState->SetHasValidUserGestureActivation(
 | |
|       aLoadURIOptions.mHasValidUserGestureActivation);
 | |
|   loadState->SetTextDirectiveUserActivation(
 | |
|       aLoadURIOptions.mTextDirectiveUserActivation);
 | |
|   loadState->SetTriggeringSandboxFlags(aLoadURIOptions.mTriggeringSandboxFlags);
 | |
|   loadState->SetTriggeringWindowId(aLoadURIOptions.mTriggeringWindowId);
 | |
|   loadState->SetTriggeringStorageAccess(
 | |
|       aLoadURIOptions.mTriggeringStorageAccess);
 | |
|   // The load is assumed to be first-party, so the triggering classification
 | |
|   // should be both zero.
 | |
|   loadState->SetTriggeringClassificationFlags({0, 0});
 | |
|   loadState->SetPostDataStream(postData);
 | |
|   loadState->SetHeadersStream(aLoadURIOptions.mHeaders);
 | |
|   loadState->SetBaseURI(aLoadURIOptions.mBaseURI);
 | |
|   loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal);
 | |
|   loadState->SetCsp(aLoadURIOptions.mCsp);
 | |
|   loadState->SetForceAllowDataURI(forceAllowDataURI);
 | |
|   if (aLoadURIOptions.mCancelContentJSEpoch) {
 | |
|     loadState->SetCancelContentJSEpoch(aLoadURIOptions.mCancelContentJSEpoch);
 | |
|   }
 | |
| 
 | |
|   if (aLoadURIOptions.mTriggeringRemoteType.WasPassed()) {
 | |
|     if (XRE_IsParentProcess()) {
 | |
|       loadState->SetTriggeringRemoteType(
 | |
|           aLoadURIOptions.mTriggeringRemoteType.Value());
 | |
|     } else if (ContentChild::GetSingleton()->GetRemoteType() !=
 | |
|                aLoadURIOptions.mTriggeringRemoteType.Value()) {
 | |
|       NS_WARNING("Invalid TriggeringRemoteType from LoadURIOptions in content");
 | |
|       return NS_ERROR_INVALID_ARG;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (aLoadURIOptions.mRemoteTypeOverride.WasPassed()) {
 | |
|     loadState->SetRemoteTypeOverride(
 | |
|         aLoadURIOptions.mRemoteTypeOverride.Value());
 | |
|   }
 | |
| 
 | |
|   loadState->SetSchemelessInput(static_cast<nsILoadInfo::SchemelessInputType>(
 | |
|       aLoadURIOptions.mSchemelessInput));
 | |
| 
 | |
|   loadState.forget(aResult);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| nsIReferrerInfo* nsDocShellLoadState::GetReferrerInfo() const {
 | |
|   return mReferrerInfo;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
 | |
|   mReferrerInfo = aReferrerInfo;
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| nsIPrincipal* nsDocShellLoadState::PartitionedPrincipalToInherit() const {
 | |
|   return mPartitionedPrincipalToInherit;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetPartitionedPrincipalToInherit(
 | |
|     nsIPrincipal* aPartitionedPrincipalToInherit) {
 | |
|   mPartitionedPrincipalToInherit = aPartitionedPrincipalToInherit;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetCsp(nsIContentSecurityPolicy* aCsp) {
 | |
|   mCsp = aCsp;
 | |
| }
 | |
| 
 | |
| nsIContentSecurityPolicy* nsDocShellLoadState::Csp() const { return mCsp; }
 | |
| 
 | |
| void nsDocShellLoadState::SetTriggeringSandboxFlags(uint32_t flags) {
 | |
|   mTriggeringSandboxFlags = flags;
 | |
| }
 | |
| 
 | |
| uint32_t nsDocShellLoadState::TriggeringSandboxFlags() const {
 | |
|   return mTriggeringSandboxFlags;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetTriggeringWindowId(uint64_t aTriggeringWindowId) {
 | |
|   mTriggeringWindowId = aTriggeringWindowId;
 | |
| }
 | |
| 
 | |
| uint64_t nsDocShellLoadState::TriggeringWindowId() const {
 | |
|   return mTriggeringWindowId;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetTriggeringStorageAccess(
 | |
|     bool aTriggeringStorageAccess) {
 | |
|   mTriggeringStorageAccess = aTriggeringStorageAccess;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::TriggeringStorageAccess() const {
 | |
|   return mTriggeringStorageAccess;
 | |
| }
 | |
| 
 | |
| mozilla::net::ClassificationFlags
 | |
| nsDocShellLoadState::TriggeringClassificationFlags() const {
 | |
|   return mTriggeringClassificationFlags;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetTriggeringClassificationFlags(
 | |
|     mozilla::net::ClassificationFlags aFlags) {
 | |
|   mTriggeringClassificationFlags = aFlags;
 | |
| }
 | |
| 
 | |
| 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::NotifiedBeforeUnloadListeners() const {
 | |
|   return mNotifiedBeforeUnloadListeners;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetNotifiedBeforeUnloadListeners(
 | |
|     bool aNotifiedBeforeUnloadListeners) {
 | |
|   mNotifiedBeforeUnloadListeners = aNotifiedBeforeUnloadListeners;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::ForceAllowDataURI() const {
 | |
|   return mForceAllowDataURI;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetForceAllowDataURI(bool aForceAllowDataURI) {
 | |
|   mForceAllowDataURI = aForceAllowDataURI;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::IsExemptFromHTTPSFirstMode() const {
 | |
|   return mIsExemptFromHTTPSFirstMode;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetIsExemptFromHTTPSFirstMode(
 | |
|     bool aIsExemptFromHTTPSFirstMode) {
 | |
|   mIsExemptFromHTTPSFirstMode = aIsExemptFromHTTPSFirstMode;
 | |
| }
 | |
| 
 | |
| RefPtr<HTTPSFirstDowngradeData>
 | |
| nsDocShellLoadState::GetHttpsFirstDowngradeData() const {
 | |
|   return mHttpsFirstDowngradeData;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetHttpsFirstDowngradeData(
 | |
|     RefPtr<HTTPSFirstDowngradeData> const& aHttpsFirstTelemetryData) {
 | |
|   mHttpsFirstDowngradeData = aHttpsFirstTelemetryData;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::OriginalFrameSrc() const { return mOriginalFrameSrc; }
 | |
| 
 | |
| void nsDocShellLoadState::SetOriginalFrameSrc(bool aOriginalFrameSrc) {
 | |
|   mOriginalFrameSrc = aOriginalFrameSrc;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::ShouldCheckForRecursion() const {
 | |
|   return mShouldCheckForRecursion;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetShouldCheckForRecursion(
 | |
|     bool aShouldCheckForRecursion) {
 | |
|   mShouldCheckForRecursion = aShouldCheckForRecursion;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::IsFormSubmission() const { return mIsFormSubmission; }
 | |
| 
 | |
| void nsDocShellLoadState::SetIsFormSubmission(bool aIsFormSubmission) {
 | |
|   mIsFormSubmission = aIsFormSubmission;
 | |
| }
 | |
| 
 | |
| uint32_t nsDocShellLoadState::LoadType() const { return mLoadType; }
 | |
| 
 | |
| void nsDocShellLoadState::SetLoadType(uint32_t aLoadType) {
 | |
|   mLoadType = aLoadType;
 | |
| }
 | |
| 
 | |
| mozilla::dom::UserNavigationInvolvement
 | |
| nsDocShellLoadState::UserNavigationInvolvement() const {
 | |
|   return mUserNavigationInvolvement;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetUserNavigationInvolvement(
 | |
|     mozilla::dom::UserNavigationInvolvement aUserNavigationInvolvement) {
 | |
|   mUserNavigationInvolvement = aUserNavigationInvolvement;
 | |
| }
 | |
| 
 | |
| nsISHEntry* nsDocShellLoadState::SHEntry() const { return mSHEntry; }
 | |
| 
 | |
| void nsDocShellLoadState::SetSHEntry(nsISHEntry* aSHEntry) {
 | |
|   mSHEntry = aSHEntry;
 | |
|   nsCOMPtr<SessionHistoryEntry> she = do_QueryInterface(aSHEntry);
 | |
|   if (she) {
 | |
|     mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(she);
 | |
|   } else {
 | |
|     mLoadingSessionHistoryInfo = nullptr;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetLoadingSessionHistoryInfo(
 | |
|     const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo) {
 | |
|   SetLoadingSessionHistoryInfo(
 | |
|       MakeUnique<mozilla::dom::LoadingSessionHistoryInfo>(aLoadingInfo));
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetLoadingSessionHistoryInfo(
 | |
|     mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> aLoadingInfo) {
 | |
|   mLoadingSessionHistoryInfo = std::move(aLoadingInfo);
 | |
| }
 | |
| 
 | |
| const mozilla::dom::LoadingSessionHistoryInfo*
 | |
| nsDocShellLoadState::GetLoadingSessionHistoryInfo() const {
 | |
|   return mLoadingSessionHistoryInfo.get();
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetLoadIsFromSessionHistory(
 | |
|     int32_t aOffset, bool aLoadingCurrentEntry) {
 | |
|   if (mLoadingSessionHistoryInfo) {
 | |
|     mLoadingSessionHistoryInfo->mLoadIsFromSessionHistory = true;
 | |
|     mLoadingSessionHistoryInfo->mOffset = aOffset;
 | |
|     mLoadingSessionHistoryInfo->mLoadingCurrentEntry = aLoadingCurrentEntry;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::ClearLoadIsFromSessionHistory() {
 | |
|   if (mLoadingSessionHistoryInfo) {
 | |
|     mLoadingSessionHistoryInfo->mLoadIsFromSessionHistory = false;
 | |
|   }
 | |
|   mSHEntry = nullptr;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::LoadIsFromSessionHistory() const {
 | |
|   return mLoadingSessionHistoryInfo
 | |
|              ? mLoadingSessionHistoryInfo->mLoadIsFromSessionHistory
 | |
|              : !!mSHEntry;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::MaybeStripTrackerQueryStrings(
 | |
|     BrowsingContext* aContext) {
 | |
|   MOZ_ASSERT(aContext);
 | |
| 
 | |
|   // Return early if the triggering principal doesn't exist. This could happen
 | |
|   // when loading a URL by using a browsing context in the Browser Toolbox.
 | |
|   if (!TriggeringPrincipal()) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // We don't need to strip for sub frames because the query string has been
 | |
|   // stripped in the top-level content. Also, we don't apply stripping if it
 | |
|   // is triggered by addons.
 | |
|   //
 | |
|   // Note that we don't need to do the stripping if the channel has been
 | |
|   // initialized. This means that this has been loaded speculatively in the
 | |
|   // parent process before and the stripping was happening by then.
 | |
|   if (GetChannelInitialized() || !aContext->IsTopContent() ||
 | |
|       BasePrincipal::Cast(TriggeringPrincipal())->AddonPolicy()) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // We don't strip the URI if it's the same-site navigation. Note that we will
 | |
|   // consider the system principal triggered load as third-party in case the
 | |
|   // user copies and pastes a URL which has tracking query parameters or an
 | |
|   // loading from external applications, such as clicking a link in an email
 | |
|   // client.
 | |
|   bool isThirdPartyURI = false;
 | |
|   if (!TriggeringPrincipal()->IsSystemPrincipal() &&
 | |
|       (NS_FAILED(
 | |
|            TriggeringPrincipal()->IsThirdPartyURI(URI(), &isThirdPartyURI)) ||
 | |
|        !isThirdPartyURI)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   glean::contentblocking::query_stripping_count
 | |
|       .EnumGet(glean::contentblocking::QueryStrippingCountLabel::eNavigation)
 | |
|       .Add();
 | |
| 
 | |
|   nsCOMPtr<nsIURI> strippedURI;
 | |
| 
 | |
|   nsresult rv;
 | |
|   nsCOMPtr<nsIURLQueryStringStripper> queryStripper =
 | |
|       components::URLQueryStringStripper::Service(&rv);
 | |
|   NS_ENSURE_SUCCESS_VOID(rv);
 | |
| 
 | |
|   uint32_t numStripped;
 | |
| 
 | |
|   queryStripper->Strip(URI(), aContext->UsePrivateBrowsing(),
 | |
|                        getter_AddRefs(strippedURI), &numStripped);
 | |
|   if (numStripped) {
 | |
|     if (!mUnstrippedURI) {
 | |
|       mUnstrippedURI = URI();
 | |
|     }
 | |
|     SetURI(strippedURI);
 | |
| 
 | |
|     glean::contentblocking::query_stripping_count
 | |
|         .EnumGet(glean::contentblocking::QueryStrippingCountLabel::
 | |
|                      eStripfornavigation)
 | |
|         .Add();
 | |
|     glean::contentblocking::query_stripping_param_count.AccumulateSingleSample(
 | |
|         numStripped);
 | |
|   }
 | |
| 
 | |
| #ifdef DEBUG
 | |
|   // Make sure that unstripped URI is the same as URI() but only the query
 | |
|   // string could be different.
 | |
|   if (mUnstrippedURI) {
 | |
|     nsCOMPtr<nsIURI> uri;
 | |
|     Unused << queryStripper->Strip(mUnstrippedURI,
 | |
|                                    aContext->UsePrivateBrowsing(),
 | |
|                                    getter_AddRefs(uri), &numStripped);
 | |
|     bool equals = false;
 | |
|     Unused << URI()->Equals(uri, &equals);
 | |
|     MOZ_ASSERT(equals);
 | |
|   }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| const nsString& nsDocShellLoadState::SrcdocData() const { return mSrcdocData; }
 | |
| 
 | |
| void nsDocShellLoadState::SetSrcdocData(const nsAString& aSrcdocData) {
 | |
|   mSrcdocData = aSrcdocData;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetSourceBrowsingContext(
 | |
|     BrowsingContext* aSourceBrowsingContext) {
 | |
|   mSourceBrowsingContext = aSourceBrowsingContext;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetTargetBrowsingContext(
 | |
|     BrowsingContext* aTargetBrowsingContext) {
 | |
|   mTargetBrowsingContext = aTargetBrowsingContext;
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetLoadFlag(uint32_t aFlag) { mLoadFlags |= aFlag; }
 | |
| 
 | |
| void nsDocShellLoadState::UnsetLoadFlag(uint32_t aFlag) {
 | |
|   mLoadFlags &= ~aFlag;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::HasLoadFlags(uint32_t aFlags) {
 | |
|   return (mLoadFlags & aFlags) == aFlags;
 | |
| }
 | |
| 
 | |
| uint32_t nsDocShellLoadState::InternalLoadFlags() const {
 | |
|   return mInternalLoadFlags;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetInternalLoadFlags(uint32_t aLoadFlags) {
 | |
|   mInternalLoadFlags = aLoadFlags;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetInternalLoadFlag(uint32_t aFlag) {
 | |
|   mInternalLoadFlags |= aFlag;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::UnsetInternalLoadFlag(uint32_t aFlag) {
 | |
|   mInternalLoadFlags &= ~aFlag;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::HasInternalLoadFlags(uint32_t aFlags) {
 | |
|   return (mInternalLoadFlags & aFlags) == aFlags;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::FirstParty() const { return mFirstParty; }
 | |
| 
 | |
| void nsDocShellLoadState::SetFirstParty(bool aFirstParty) {
 | |
|   mFirstParty = aFirstParty;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::HasValidUserGestureActivation() const {
 | |
|   return mHasValidUserGestureActivation;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetHasValidUserGestureActivation(
 | |
|     bool aHasValidUserGestureActivation) {
 | |
|   mHasValidUserGestureActivation = aHasValidUserGestureActivation;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetTextDirectiveUserActivation(
 | |
|     bool aTextDirectiveUserActivation) {
 | |
|   mTextDirectiveUserActivation = aTextDirectiveUserActivation;
 | |
| }
 | |
| 
 | |
| bool nsDocShellLoadState::GetTextDirectiveUserActivation() {
 | |
|   return mTextDirectiveUserActivation;
 | |
| }
 | |
| 
 | |
| 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) {
 | |
|   MOZ_DIAGNOSTIC_ASSERT(aFileName.FindChar(char16_t(0)) == kNotFound,
 | |
|                         "The filename should never contain null characters");
 | |
|   mFileName = aFileName;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetRemoteTypeOverride(
 | |
|     const nsCString& aRemoteTypeOverride) {
 | |
|   MOZ_DIAGNOSTIC_ASSERT(
 | |
|       NS_IsAboutBlank(mURI),
 | |
|       "Should only have aRemoteTypeOverride for about:blank URIs");
 | |
|   mRemoteTypeOverride = mozilla::Some(aRemoteTypeOverride);
 | |
| }
 | |
| 
 | |
| const nsCString& nsDocShellLoadState::GetEffectiveTriggeringRemoteType() const {
 | |
|   // Consider non-errorpage loads from session history as being triggred by the
 | |
|   // parent process, as we'll validate them against the history entry.
 | |
|   //
 | |
|   // NOTE: Keep this check in-sync with the session-history validation check in
 | |
|   // `DocumentLoadListener::Open`!
 | |
|   if (LoadIsFromSessionHistory() && LoadType() != LOAD_ERROR_PAGE) {
 | |
|     return NOT_REMOTE_TYPE;
 | |
|   }
 | |
|   return mTriggeringRemoteType;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetTriggeringRemoteType(
 | |
|     const nsACString& aTriggeringRemoteType) {
 | |
|   MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "only settable in parent");
 | |
|   mTriggeringRemoteType = aTriggeringRemoteType;
 | |
| }
 | |
| 
 | |
| #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
 | |
| void nsDocShellLoadState::AssertProcessCouldTriggerLoadIfSystem() {
 | |
|   // Early check to see if we're trying to start a file URI load with a system
 | |
|   // principal within a web content process.
 | |
|   // If this assertion fails, the load will fail later during
 | |
|   // nsContentSecurityManager checks, however this assertion should happen
 | |
|   // closer to whichever caller is triggering the system-principal load.
 | |
|   if (mozilla::SessionHistoryInParent() &&
 | |
|       TriggeringPrincipal()->IsSystemPrincipal() &&
 | |
|       mozilla::dom::IsWebRemoteType(GetEffectiveTriggeringRemoteType())) {
 | |
|     bool localFile = false;
 | |
|     if (NS_SUCCEEDED(NS_URIChainHasFlags(
 | |
|             URI(), nsIProtocolHandler::URI_IS_LOCAL_FILE, &localFile)) &&
 | |
|         localFile) {
 | |
|       NS_WARNING(nsPrintfCString("Unexpected system load of file URI (%s) from "
 | |
|                                  "web content process",
 | |
|                                  URI()->GetSpecOrDefault().get())
 | |
|                      .get());
 | |
|       MOZ_CRASH("Unexpected system load of file URI from web content process");
 | |
|     }
 | |
|   }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| nsresult nsDocShellLoadState::SetupInheritingPrincipal(
 | |
|     BrowsingContext::Type aType,
 | |
|     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 && aType != BrowsingContext::Type::Chrome) {
 | |
|     if (mPrincipalToInherit->IsSystemPrincipal()) {
 | |
|       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::Create(aOriginAttributes);
 | |
|       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;
 | |
|     // Create a new null principal URI based on our precursor principal.
 | |
|     nsCOMPtr<nsIURI> nullPrincipalURI =
 | |
|         NullPrincipal::CreateURI(mPrincipalToInherit);
 | |
|     // If mFirstParty is true and the pref 'privacy.firstparty.isolate' is
 | |
|     // enabled, we will set firstPartyDomain on the origin attributes.
 | |
|     OriginAttributes attrs(aOriginAttributes);
 | |
|     if (mFirstParty) {
 | |
|       attrs.SetFirstPartyDomain(true, nullPrincipalURI);
 | |
|     }
 | |
|     mPrincipalToInherit = NullPrincipal::Create(attrs, nullPrincipalURI);
 | |
|   }
 | |
| 
 | |
|   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 (mReferrerInfo) {
 | |
|       nsCOMPtr<nsIURI> referrer = mReferrerInfo->GetOriginalReferrer();
 | |
|       mTriggeringPrincipal =
 | |
|           BasePrincipal::CreateContentPrincipal(referrer, aOriginAttributes);
 | |
| 
 | |
|       if (!mTriggeringPrincipal) {
 | |
|         return NS_ERROR_FAILURE;
 | |
|       }
 | |
|     } else {
 | |
|       mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
 | |
|     }
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::CalculateLoadURIFlags() {
 | |
|   if (mInheritPrincipal) {
 | |
|     MOZ_ASSERT(
 | |
|         !mPrincipalToInherit || !mPrincipalToInherit->IsSystemPrincipal(),
 | |
|         "Should not inherit SystemPrincipal");
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
 | |
|   }
 | |
| 
 | |
|   if (mReferrerInfo && !mReferrerInfo->GetSendReferrer()) {
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
 | |
|   }
 | |
|   if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
 | |
|     mInternalLoadFlags |=
 | |
|         nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
 | |
|   }
 | |
| 
 | |
|   if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) {
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD;
 | |
|   }
 | |
| 
 | |
|   if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CLASSIFIER) {
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
 | |
|   }
 | |
| 
 | |
|   if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
 | |
|   }
 | |
| 
 | |
|   if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE) {
 | |
|     mInternalLoadFlags |=
 | |
|         nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE;
 | |
|   }
 | |
| 
 | |
|   if (!mSrcdocData.IsVoid()) {
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
 | |
|   }
 | |
| 
 | |
|   if (mForceAllowDataURI) {
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
 | |
|   }
 | |
| 
 | |
|   if (mOriginalFrameSrc) {
 | |
|     mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC;
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsLoadFlags nsDocShellLoadState::CalculateChannelLoadFlags(
 | |
|     BrowsingContext* aBrowsingContext, bool aUriModified,
 | |
|     Maybe<bool> aIsEmbeddingBlockedError) {
 | |
|   MOZ_ASSERT(aBrowsingContext);
 | |
| 
 | |
|   nsLoadFlags loadFlags = aBrowsingContext->GetDefaultLoadFlags();
 | |
| 
 | |
|   if (FirstParty()) {
 | |
|     // tag first party URL loads
 | |
|     loadFlags |= nsIChannel::LOAD_INITIAL_DOCUMENT_URI;
 | |
|   }
 | |
| 
 | |
|   const uint32_t loadType = LoadType();
 | |
| 
 | |
|   // These values aren't available for loads initiated in the Parent process.
 | |
|   MOZ_ASSERT_IF(loadType == LOAD_ERROR_PAGE, aIsEmbeddingBlockedError.isSome());
 | |
| 
 | |
|   if (loadType == LOAD_ERROR_PAGE) {
 | |
|     // Error pages are LOAD_BACKGROUND, unless it's an
 | |
|     // XFO / frame-ancestors error for which we want an error page to load
 | |
|     // but additionally want the onload() event to fire.
 | |
|     if (!*aIsEmbeddingBlockedError) {
 | |
|       loadFlags |= nsIChannel::LOAD_BACKGROUND;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Mark the channel as being a document URI and allow content sniffing...
 | |
|   loadFlags |=
 | |
|       nsIChannel::LOAD_DOCUMENT_URI | nsIChannel::LOAD_CALL_CONTENT_SNIFFERS;
 | |
| 
 | |
|   if (nsDocShell::SandboxFlagsImplyCookies(
 | |
|           aBrowsingContext->GetSandboxFlags())) {
 | |
|     loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
 | |
|   }
 | |
| 
 | |
|   // Load attributes depend on load type...
 | |
|   switch (loadType) {
 | |
|     case LOAD_HISTORY: {
 | |
|       // Only send VALIDATE_NEVER if mLSHE's URI was never changed via
 | |
|       // push/replaceState (bug 669671).
 | |
|       if (!aUriModified) {
 | |
|         loadFlags |= nsIRequest::VALIDATE_NEVER;
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
 | |
|     case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
 | |
|       loadFlags |=
 | |
|           nsIRequest::LOAD_BYPASS_CACHE | nsIRequest::LOAD_FRESH_CONNECTION;
 | |
|       [[fallthrough]];
 | |
| 
 | |
|     case LOAD_REFRESH:
 | |
|       loadFlags |= nsIRequest::VALIDATE_ALWAYS;
 | |
|       break;
 | |
| 
 | |
|     case LOAD_NORMAL_BYPASS_CACHE:
 | |
|     case LOAD_NORMAL_BYPASS_PROXY:
 | |
|     case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
 | |
|     case LOAD_RELOAD_BYPASS_CACHE:
 | |
|     case LOAD_RELOAD_BYPASS_PROXY:
 | |
|     case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
 | |
|     case LOAD_REPLACE_BYPASS_CACHE:
 | |
|       loadFlags |=
 | |
|           nsIRequest::LOAD_BYPASS_CACHE | nsIRequest::LOAD_FRESH_CONNECTION;
 | |
|       break;
 | |
| 
 | |
|     case LOAD_RELOAD_NORMAL:
 | |
|       if (!StaticPrefs::
 | |
|               browser_soft_reload_only_force_validate_top_level_document()) {
 | |
|         loadFlags |= nsIRequest::VALIDATE_ALWAYS;
 | |
|         break;
 | |
|       }
 | |
|       [[fallthrough]];
 | |
|     case LOAD_NORMAL:
 | |
|     case LOAD_LINK:
 | |
|       // Set cache checking flags
 | |
|       switch (StaticPrefs::browser_cache_check_doc_frequency()) {
 | |
|         case 0:
 | |
|           loadFlags |= nsIRequest::VALIDATE_ONCE_PER_SESSION;
 | |
|           break;
 | |
|         case 1:
 | |
|           loadFlags |= nsIRequest::VALIDATE_ALWAYS;
 | |
|           break;
 | |
|         case 2:
 | |
|           loadFlags |= nsIRequest::VALIDATE_NEVER;
 | |
|           break;
 | |
|       }
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   if (HasInternalLoadFlags(nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER)) {
 | |
|     loadFlags |= nsIChannel::LOAD_BYPASS_URL_CLASSIFIER;
 | |
|   }
 | |
| 
 | |
|   // If the user pressed shift-reload, then do not allow ServiceWorker
 | |
|   // interception to occur. See step 12.1 of the SW HandleFetch algorithm.
 | |
|   if (IsForceReloadType(loadType)) {
 | |
|     loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
 | |
|   }
 | |
| 
 | |
|   return loadFlags;
 | |
| }
 | |
| 
 | |
| const char* nsDocShellLoadState::ValidateWithOriginalState(
 | |
|     nsDocShellLoadState* aOriginalState) {
 | |
|   MOZ_ASSERT(mLoadIdentifier == aOriginalState->mLoadIdentifier);
 | |
| 
 | |
|   // Check that `aOriginalState` is sufficiently similar to this state that
 | |
|   // they're performing the same load.
 | |
|   auto uriEq = [](nsIURI* a, nsIURI* b) -> bool {
 | |
|     bool eq = false;
 | |
|     return a == b || (a && b && NS_SUCCEEDED(a->Equals(b, &eq)) && eq);
 | |
|   };
 | |
|   if (!uriEq(mURI, aOriginalState->mURI)) {
 | |
|     return "URI";
 | |
|   }
 | |
|   if (!uriEq(mUnstrippedURI, aOriginalState->mUnstrippedURI)) {
 | |
|     return "UnstrippedURI";
 | |
|   }
 | |
|   if (!uriEq(mOriginalURI, aOriginalState->mOriginalURI)) {
 | |
|     return "OriginalURI";
 | |
|   }
 | |
|   if (!uriEq(mBaseURI, aOriginalState->mBaseURI)) {
 | |
|     return "BaseURI";
 | |
|   }
 | |
| 
 | |
|   if (!mTriggeringPrincipal->Equals(aOriginalState->mTriggeringPrincipal)) {
 | |
|     return "TriggeringPrincipal";
 | |
|   }
 | |
|   if (mTriggeringSandboxFlags != aOriginalState->mTriggeringSandboxFlags) {
 | |
|     return "TriggeringSandboxFlags";
 | |
|   }
 | |
|   if (mTriggeringRemoteType != aOriginalState->mTriggeringRemoteType) {
 | |
|     return "TriggeringRemoteType";
 | |
|   }
 | |
| 
 | |
|   if (mOriginalURIString != aOriginalState->mOriginalURIString) {
 | |
|     return "OriginalURIString";
 | |
|   }
 | |
| 
 | |
|   if (mRemoteTypeOverride != aOriginalState->mRemoteTypeOverride) {
 | |
|     return "RemoteTypeOverride";
 | |
|   }
 | |
| 
 | |
|   if (mSourceBrowsingContext.ContextId() !=
 | |
|       aOriginalState->mSourceBrowsingContext.ContextId()) {
 | |
|     return "SourceBrowsingContext";
 | |
|   }
 | |
| 
 | |
|   // FIXME: Consider calculating less information in the target process so that
 | |
|   // we can validate more properties more easily.
 | |
|   // FIXME: Identify what other flags will not change when sent through a
 | |
|   // content process.
 | |
| 
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| DocShellLoadStateInit nsDocShellLoadState::Serialize(
 | |
|     mozilla::ipc::IProtocol* aActor) {
 | |
|   MOZ_ASSERT(aActor);
 | |
|   DocShellLoadStateInit loadState;
 | |
|   loadState.ResultPrincipalURI() = mResultPrincipalURI;
 | |
|   loadState.ResultPrincipalURIIsSome() = mResultPrincipalURIIsSome;
 | |
|   loadState.KeepResultPrincipalURIIfSet() = mKeepResultPrincipalURIIfSet;
 | |
|   loadState.LoadReplace() = mLoadReplace;
 | |
|   loadState.InheritPrincipal() = mInheritPrincipal;
 | |
|   loadState.PrincipalIsExplicit() = mPrincipalIsExplicit;
 | |
|   loadState.ForceAllowDataURI() = mForceAllowDataURI;
 | |
|   loadState.IsExemptFromHTTPSFirstMode() = mIsExemptFromHTTPSFirstMode;
 | |
|   loadState.OriginalFrameSrc() = mOriginalFrameSrc;
 | |
|   loadState.ShouldCheckForRecursion() = mShouldCheckForRecursion;
 | |
|   loadState.IsFormSubmission() = mIsFormSubmission;
 | |
|   loadState.LoadType() = mLoadType;
 | |
|   loadState.userNavigationInvolvement() = mUserNavigationInvolvement;
 | |
|   loadState.Target() = mTarget;
 | |
|   loadState.TargetBrowsingContext() = mTargetBrowsingContext;
 | |
|   loadState.LoadFlags() = mLoadFlags;
 | |
|   loadState.InternalLoadFlags() = mInternalLoadFlags;
 | |
|   loadState.FirstParty() = mFirstParty;
 | |
|   loadState.HasValidUserGestureActivation() = mHasValidUserGestureActivation;
 | |
|   loadState.TextDirectiveUserActivation() = mTextDirectiveUserActivation;
 | |
|   loadState.AllowFocusMove() = mAllowFocusMove;
 | |
|   loadState.TypeHint() = mTypeHint;
 | |
|   loadState.FileName() = mFileName;
 | |
|   loadState.IsFromProcessingFrameAttributes() =
 | |
|       mIsFromProcessingFrameAttributes;
 | |
|   loadState.URI() = mURI;
 | |
|   loadState.OriginalURI() = mOriginalURI;
 | |
|   loadState.SourceBrowsingContext() = mSourceBrowsingContext;
 | |
|   loadState.BaseURI() = mBaseURI;
 | |
|   loadState.TriggeringPrincipal() = mTriggeringPrincipal;
 | |
|   loadState.PrincipalToInherit() = mPrincipalToInherit;
 | |
|   loadState.PartitionedPrincipalToInherit() = mPartitionedPrincipalToInherit;
 | |
|   loadState.TriggeringSandboxFlags() = mTriggeringSandboxFlags;
 | |
|   loadState.TriggeringWindowId() = mTriggeringWindowId;
 | |
|   loadState.TriggeringStorageAccess() = mTriggeringStorageAccess;
 | |
|   loadState.TriggeringClassificationFlags() = mTriggeringClassificationFlags;
 | |
|   loadState.TriggeringRemoteType() = mTriggeringRemoteType;
 | |
|   loadState.SchemelessInput() = mSchemelessInput;
 | |
|   loadState.HttpsUpgradeTelemetry() = mHttpsUpgradeTelemetry;
 | |
|   loadState.Csp() = mCsp;
 | |
|   loadState.OriginalURIString() = mOriginalURIString;
 | |
|   loadState.CancelContentJSEpoch() = mCancelContentJSEpoch;
 | |
|   loadState.ReferrerInfo() = mReferrerInfo;
 | |
|   loadState.PostDataStream() = mPostDataStream;
 | |
|   loadState.HeadersStream() = mHeadersStream;
 | |
|   loadState.SrcdocData() = mSrcdocData;
 | |
|   loadState.ResultPrincipalURI() = mResultPrincipalURI;
 | |
|   loadState.LoadIdentifier() = mLoadIdentifier;
 | |
|   loadState.ChannelInitialized() = mChannelInitialized;
 | |
|   loadState.IsMetaRefresh() = mIsMetaRefresh;
 | |
|   if (mLoadingSessionHistoryInfo) {
 | |
|     loadState.loadingSessionHistoryInfo().emplace(*mLoadingSessionHistoryInfo);
 | |
|   }
 | |
|   loadState.UnstrippedURI() = mUnstrippedURI;
 | |
|   loadState.RemoteTypeOverride() = mRemoteTypeOverride;
 | |
| 
 | |
|   if (XRE_IsParentProcess()) {
 | |
|     mozilla::ipc::IToplevelProtocol* top = aActor->ToplevelProtocol();
 | |
|     MOZ_RELEASE_ASSERT(top &&
 | |
|                            top->GetProtocolId() ==
 | |
|                                mozilla::ipc::ProtocolId::PContentMsgStart &&
 | |
|                            top->GetSide() == mozilla::ipc::ParentSide,
 | |
|                        "nsDocShellLoadState must be sent over PContent");
 | |
|     ContentParent* cp = static_cast<ContentParent*>(top);
 | |
|     cp->StorePendingLoadState(this);
 | |
|   }
 | |
| 
 | |
|   return loadState;
 | |
| }
 | |
| 
 | |
| nsIURI* nsDocShellLoadState::GetUnstrippedURI() const { return mUnstrippedURI; }
 | |
| 
 | |
| void nsDocShellLoadState::SetUnstrippedURI(nsIURI* aUnstrippedURI) {
 | |
|   mUnstrippedURI = aUnstrippedURI;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetSourceElement(mozilla::dom::Element* aElement) {
 | |
|   mSourceElement = do_GetWeakReference(aElement);
 | |
| }
 | |
| already_AddRefed<Element> nsDocShellLoadState::GetSourceElement() const {
 | |
|   nsCOMPtr<Element> element = do_QueryReferent(mSourceElement);
 | |
|   return element.forget();
 | |
| }
 | |
| 
 | |
| nsIStructuredCloneContainer* nsDocShellLoadState::GetNavigationAPIState()
 | |
|     const {
 | |
|   return mNavigationAPIState;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetNavigationAPIState(
 | |
|     nsIStructuredCloneContainer* aNavigationAPIState) {
 | |
|   mNavigationAPIState = aNavigationAPIState;
 | |
| }
 | |
| 
 | |
| NavigationType nsDocShellLoadState::GetNavigationType() const {
 | |
|   return LoadReplace() ? NavigationType::Replace : NavigationType::Push;
 | |
| }
 | |
| 
 | |
| mozilla::dom::FormData* nsDocShellLoadState::GetFormDataEntryList() {
 | |
|   return mFormDataEntryList;
 | |
| }
 | |
| 
 | |
| void nsDocShellLoadState::SetFormDataEntryList(
 | |
|     mozilla::dom::FormData* aFormDataEntryList) {
 | |
|   mFormDataEntryList = aFormDataEntryList;
 | |
| }
 | 
