Bug 1807268 - Fix verifyOpenAllInNewTabsOptionTest UI test r=ohorvath
[gecko.git] / docshell / base / nsDocShellLoadState.cpp
blobb3812eedd328504e6d5df68a499f08500ba1e168
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsDocShellLoadState.h"
8 #include "nsIDocShell.h"
9 #include "nsDocShell.h"
10 #include "nsIProtocolHandler.h"
11 #include "nsISHEntry.h"
12 #include "nsIURIFixup.h"
13 #include "nsIWebNavigation.h"
14 #include "nsIChannel.h"
15 #include "nsIURLQueryStringStripper.h"
16 #include "nsIXULRuntime.h"
17 #include "nsNetUtil.h"
18 #include "nsQueryObject.h"
19 #include "ReferrerInfo.h"
20 #include "mozilla/BasePrincipal.h"
21 #include "mozilla/ClearOnShutdown.h"
22 #include "mozilla/Components.h"
23 #include "mozilla/dom/BrowsingContext.h"
24 #include "mozilla/dom/ContentChild.h"
25 #include "mozilla/dom/ContentParent.h"
26 #include "mozilla/dom/LoadURIOptionsBinding.h"
27 #include "mozilla/StaticPrefs_browser.h"
28 #include "mozilla/StaticPrefs_fission.h"
29 #include "mozilla/Telemetry.h"
31 #include "mozilla/OriginAttributes.h"
32 #include "mozilla/NullPrincipal.h"
33 #include "mozilla/StaticPtr.h"
35 #include "mozilla/dom/PContent.h"
37 using namespace mozilla;
38 using namespace mozilla::dom;
40 // Global reference to the URI fixup service.
41 static mozilla::StaticRefPtr<nsIURIFixup> sURIFixup;
43 nsDocShellLoadState::nsDocShellLoadState(nsIURI* aURI)
44 : nsDocShellLoadState(aURI, nsContentUtils::GenerateLoadIdentifier()) {}
46 nsDocShellLoadState::nsDocShellLoadState(
47 const DocShellLoadStateInit& aLoadState, mozilla::ipc::IProtocol* aActor,
48 bool* aReadSuccess)
49 : mNotifiedBeforeUnloadListeners(false),
50 mLoadIdentifier(aLoadState.LoadIdentifier()) {
51 // If we return early, we failed to read in the data.
52 *aReadSuccess = false;
53 if (!aLoadState.URI()) {
54 MOZ_ASSERT_UNREACHABLE("Cannot create a LoadState with a null URI!");
55 return;
58 mResultPrincipalURI = aLoadState.ResultPrincipalURI();
59 mResultPrincipalURIIsSome = aLoadState.ResultPrincipalURIIsSome();
60 mKeepResultPrincipalURIIfSet = aLoadState.KeepResultPrincipalURIIfSet();
61 mLoadReplace = aLoadState.LoadReplace();
62 mInheritPrincipal = aLoadState.InheritPrincipal();
63 mPrincipalIsExplicit = aLoadState.PrincipalIsExplicit();
64 mForceAllowDataURI = aLoadState.ForceAllowDataURI();
65 mIsExemptFromHTTPSFirstMode = aLoadState.IsExemptFromHTTPSFirstMode();
66 mOriginalFrameSrc = aLoadState.OriginalFrameSrc();
67 mIsFormSubmission = aLoadState.IsFormSubmission();
68 mLoadType = aLoadState.LoadType();
69 mTarget = aLoadState.Target();
70 mTargetBrowsingContext = aLoadState.TargetBrowsingContext();
71 mLoadFlags = aLoadState.LoadFlags();
72 mInternalLoadFlags = aLoadState.InternalLoadFlags();
73 mFirstParty = aLoadState.FirstParty();
74 mHasValidUserGestureActivation = aLoadState.HasValidUserGestureActivation();
75 mAllowFocusMove = aLoadState.AllowFocusMove();
76 mTypeHint = aLoadState.TypeHint();
77 mFileName = aLoadState.FileName();
78 mIsFromProcessingFrameAttributes =
79 aLoadState.IsFromProcessingFrameAttributes();
80 mReferrerInfo = aLoadState.ReferrerInfo();
81 mURI = aLoadState.URI();
82 mOriginalURI = aLoadState.OriginalURI();
83 mSourceBrowsingContext = aLoadState.SourceBrowsingContext();
84 mBaseURI = aLoadState.BaseURI();
85 mTriggeringPrincipal = aLoadState.TriggeringPrincipal();
86 mPrincipalToInherit = aLoadState.PrincipalToInherit();
87 mPartitionedPrincipalToInherit = aLoadState.PartitionedPrincipalToInherit();
88 mTriggeringSandboxFlags = aLoadState.TriggeringSandboxFlags();
89 mTriggeringWindowId = aLoadState.TriggeringWindowId();
90 mTriggeringStorageAccess = aLoadState.TriggeringStorageAccess();
91 mTriggeringRemoteType = aLoadState.TriggeringRemoteType();
92 mWasSchemelessInput = aLoadState.WasSchemelessInput();
93 mCsp = aLoadState.Csp();
94 mOriginalURIString = aLoadState.OriginalURIString();
95 mCancelContentJSEpoch = aLoadState.CancelContentJSEpoch();
96 mPostDataStream = aLoadState.PostDataStream();
97 mHeadersStream = aLoadState.HeadersStream();
98 mSrcdocData = aLoadState.SrcdocData();
99 mChannelInitialized = aLoadState.ChannelInitialized();
100 mIsMetaRefresh = aLoadState.IsMetaRefresh();
101 if (aLoadState.loadingSessionHistoryInfo().isSome()) {
102 mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(
103 aLoadState.loadingSessionHistoryInfo().ref());
105 mUnstrippedURI = aLoadState.UnstrippedURI();
106 mRemoteTypeOverride = aLoadState.RemoteTypeOverride();
108 // We know this was created remotely, as we just received it over IPC.
109 mWasCreatedRemotely = true;
111 // If we're in the parent process, potentially validate against a LoadState
112 // which we sent to the source content process.
113 if (XRE_IsParentProcess()) {
114 mozilla::ipc::IToplevelProtocol* top = aActor->ToplevelProtocol();
115 if (!top ||
116 top->GetProtocolId() != mozilla::ipc::ProtocolId::PContentMsgStart ||
117 top->GetSide() != mozilla::ipc::ParentSide) {
118 aActor->FatalError("nsDocShellLoadState must be received over PContent");
119 return;
121 ContentParent* cp = static_cast<ContentParent*>(top);
123 // If this load was sent down to the content process as a navigation
124 // request, ensure it still matches the one we sent down.
125 if (RefPtr<nsDocShellLoadState> originalState =
126 cp->TakePendingLoadStateForId(mLoadIdentifier)) {
127 if (const char* mismatch = ValidateWithOriginalState(originalState)) {
128 aActor->FatalError(
129 nsPrintfCString(
130 "nsDocShellLoadState %s changed while in content process",
131 mismatch)
132 .get());
133 return;
135 } else if (mTriggeringRemoteType != cp->GetRemoteType()) {
136 // If we don't have a previous load to compare to, the content process
137 // must be the triggering process.
138 aActor->FatalError(
139 "nsDocShellLoadState with invalid triggering remote type");
140 return;
144 // We successfully read in the data - return a success value.
145 *aReadSuccess = true;
148 nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
149 : mReferrerInfo(aOther.mReferrerInfo),
150 mURI(aOther.mURI),
151 mOriginalURI(aOther.mOriginalURI),
152 mResultPrincipalURI(aOther.mResultPrincipalURI),
153 mResultPrincipalURIIsSome(aOther.mResultPrincipalURIIsSome),
154 mTriggeringPrincipal(aOther.mTriggeringPrincipal),
155 mTriggeringSandboxFlags(aOther.mTriggeringSandboxFlags),
156 mTriggeringWindowId(aOther.mTriggeringWindowId),
157 mTriggeringStorageAccess(aOther.mTriggeringStorageAccess),
158 mCsp(aOther.mCsp),
159 mKeepResultPrincipalURIIfSet(aOther.mKeepResultPrincipalURIIfSet),
160 mLoadReplace(aOther.mLoadReplace),
161 mInheritPrincipal(aOther.mInheritPrincipal),
162 mPrincipalIsExplicit(aOther.mPrincipalIsExplicit),
163 mNotifiedBeforeUnloadListeners(aOther.mNotifiedBeforeUnloadListeners),
164 mPrincipalToInherit(aOther.mPrincipalToInherit),
165 mPartitionedPrincipalToInherit(aOther.mPartitionedPrincipalToInherit),
166 mForceAllowDataURI(aOther.mForceAllowDataURI),
167 mIsExemptFromHTTPSFirstMode(aOther.mIsExemptFromHTTPSFirstMode),
168 mOriginalFrameSrc(aOther.mOriginalFrameSrc),
169 mIsFormSubmission(aOther.mIsFormSubmission),
170 mLoadType(aOther.mLoadType),
171 mSHEntry(aOther.mSHEntry),
172 mTarget(aOther.mTarget),
173 mTargetBrowsingContext(aOther.mTargetBrowsingContext),
174 mPostDataStream(aOther.mPostDataStream),
175 mHeadersStream(aOther.mHeadersStream),
176 mSrcdocData(aOther.mSrcdocData),
177 mSourceBrowsingContext(aOther.mSourceBrowsingContext),
178 mBaseURI(aOther.mBaseURI),
179 mLoadFlags(aOther.mLoadFlags),
180 mInternalLoadFlags(aOther.mInternalLoadFlags),
181 mFirstParty(aOther.mFirstParty),
182 mHasValidUserGestureActivation(aOther.mHasValidUserGestureActivation),
183 mAllowFocusMove(aOther.mAllowFocusMove),
184 mTypeHint(aOther.mTypeHint),
185 mFileName(aOther.mFileName),
186 mIsFromProcessingFrameAttributes(aOther.mIsFromProcessingFrameAttributes),
187 mPendingRedirectedChannel(aOther.mPendingRedirectedChannel),
188 mOriginalURIString(aOther.mOriginalURIString),
189 mCancelContentJSEpoch(aOther.mCancelContentJSEpoch),
190 mLoadIdentifier(aOther.mLoadIdentifier),
191 mChannelInitialized(aOther.mChannelInitialized),
192 mIsMetaRefresh(aOther.mIsMetaRefresh),
193 mWasCreatedRemotely(aOther.mWasCreatedRemotely),
194 mUnstrippedURI(aOther.mUnstrippedURI),
195 mRemoteTypeOverride(aOther.mRemoteTypeOverride),
196 mTriggeringRemoteType(aOther.mTriggeringRemoteType),
197 mWasSchemelessInput(aOther.mWasSchemelessInput) {
198 MOZ_DIAGNOSTIC_ASSERT(
199 XRE_IsParentProcess(),
200 "Cloning a nsDocShellLoadState with the same load identifier is only "
201 "allowed in the parent process, as it could break triggering remote type "
202 "tracking in content.");
203 if (aOther.mLoadingSessionHistoryInfo) {
204 mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(
205 *aOther.mLoadingSessionHistoryInfo);
209 nsDocShellLoadState::nsDocShellLoadState(nsIURI* aURI, uint64_t aLoadIdentifier)
210 : mURI(aURI),
211 mResultPrincipalURIIsSome(false),
212 mTriggeringSandboxFlags(0),
213 mTriggeringWindowId(0),
214 mTriggeringStorageAccess(false),
215 mKeepResultPrincipalURIIfSet(false),
216 mLoadReplace(false),
217 mInheritPrincipal(false),
218 mPrincipalIsExplicit(false),
219 mNotifiedBeforeUnloadListeners(false),
220 mForceAllowDataURI(false),
221 mIsExemptFromHTTPSFirstMode(false),
222 mOriginalFrameSrc(false),
223 mIsFormSubmission(false),
224 mLoadType(LOAD_NORMAL),
225 mSrcdocData(VoidString()),
226 mLoadFlags(0),
227 mInternalLoadFlags(0),
228 mFirstParty(false),
229 mHasValidUserGestureActivation(false),
230 mAllowFocusMove(false),
231 mTypeHint(VoidCString()),
232 mFileName(VoidString()),
233 mIsFromProcessingFrameAttributes(false),
234 mLoadIdentifier(aLoadIdentifier),
235 mChannelInitialized(false),
236 mIsMetaRefresh(false),
237 mWasCreatedRemotely(false),
238 mTriggeringRemoteType(XRE_IsContentProcess()
239 ? ContentChild::GetSingleton()->GetRemoteType()
240 : NOT_REMOTE_TYPE),
241 mWasSchemelessInput(false) {
242 MOZ_ASSERT(aURI, "Cannot create a LoadState with a null URI!");
245 nsDocShellLoadState::~nsDocShellLoadState() {
246 if (mWasCreatedRemotely && XRE_IsContentProcess()) {
247 ContentChild::GetSingleton()->SendCleanupPendingLoadState(mLoadIdentifier);
251 nsresult nsDocShellLoadState::CreateFromPendingChannel(
252 nsIChannel* aPendingChannel, uint64_t aLoadIdentifier,
253 uint64_t aRegistrarId, nsDocShellLoadState** aResult) {
254 // Create the nsDocShellLoadState object with default state pulled from the
255 // passed-in channel.
256 nsCOMPtr<nsIURI> uri;
257 nsresult rv = aPendingChannel->GetURI(getter_AddRefs(uri));
258 if (NS_WARN_IF(NS_FAILED(rv))) {
259 return rv;
262 RefPtr<nsDocShellLoadState> loadState =
263 new nsDocShellLoadState(uri, aLoadIdentifier);
264 loadState->mPendingRedirectedChannel = aPendingChannel;
265 loadState->mChannelRegistrarId = aRegistrarId;
267 // Pull relevant state from the channel, and store it on the
268 // nsDocShellLoadState.
269 nsCOMPtr<nsIURI> originalUri;
270 rv = aPendingChannel->GetOriginalURI(getter_AddRefs(originalUri));
271 if (NS_WARN_IF(NS_FAILED(rv))) {
272 return rv;
274 loadState->SetOriginalURI(originalUri);
276 nsCOMPtr<nsILoadInfo> loadInfo = aPendingChannel->LoadInfo();
277 loadState->SetTriggeringPrincipal(loadInfo->TriggeringPrincipal());
279 // Return the newly created loadState.
280 loadState.forget(aResult);
281 return NS_OK;
284 static uint32_t WebNavigationFlagsToFixupFlags(nsIURI* aURI,
285 const nsACString& aURIString,
286 uint32_t aNavigationFlags) {
287 if (aURI) {
288 aNavigationFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
290 uint32_t fixupFlags = nsIURIFixup::FIXUP_FLAG_NONE;
291 if (aNavigationFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
292 fixupFlags |= nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
294 if (aNavigationFlags & nsIWebNavigation::LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
295 fixupFlags |= nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS;
297 return fixupFlags;
300 nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
301 BrowsingContext* aBrowsingContext, const nsAString& aURI,
302 const LoadURIOptions& aLoadURIOptions, nsDocShellLoadState** aResult) {
303 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
305 NS_ASSERTION(
306 (loadFlags & nsDocShell::INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,
307 "Unexpected flags");
309 nsCOMPtr<nsIURI> uri;
310 nsresult rv = NS_OK;
312 NS_ConvertUTF16toUTF8 uriString(aURI);
313 // Cleanup the empty spaces that might be on each end.
314 uriString.Trim(" ");
315 // Eliminate embedded newlines, which single-line text fields now allow:
316 uriString.StripCRLF();
317 NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
319 // Just create a URI and see what happens...
320 rv = NS_NewURI(getter_AddRefs(uri), uriString);
321 bool fixup = true;
322 if (NS_SUCCEEDED(rv) && uri &&
323 (uri->SchemeIs("about") || uri->SchemeIs("chrome"))) {
324 // Avoid third party fixup as a performance optimization.
325 loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
326 fixup = false;
327 } else if (!sURIFixup && !XRE_IsContentProcess()) {
328 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
329 if (uriFixup) {
330 sURIFixup = uriFixup;
331 ClearOnShutdown(&sURIFixup);
332 } else {
333 fixup = false;
337 nsAutoString searchProvider, keyword;
338 RefPtr<nsIInputStream> fixupStream;
339 if (fixup) {
340 uint32_t fixupFlags =
341 WebNavigationFlagsToFixupFlags(uri, uriString, loadFlags);
343 // If we don't allow keyword lookups for this URL string, make sure to
344 // update loadFlags to indicate this as well.
345 if (!(fixupFlags & nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) {
346 loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
348 // Ensure URIFixup will use the right search engine in Private Browsing.
349 if (aBrowsingContext->UsePrivateBrowsing()) {
350 fixupFlags |= nsIURIFixup::FIXUP_FLAG_PRIVATE_CONTEXT;
353 if (!XRE_IsContentProcess()) {
354 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
355 sURIFixup->GetFixupURIInfo(uriString, fixupFlags,
356 getter_AddRefs(fixupInfo));
357 if (fixupInfo) {
358 // We could fix the uri, clear NS_ERROR_MALFORMED_URI.
359 rv = NS_OK;
360 fixupInfo->GetPreferredURI(getter_AddRefs(uri));
361 fixupInfo->SetConsumer(aBrowsingContext);
362 fixupInfo->GetKeywordProviderName(searchProvider);
363 fixupInfo->GetKeywordAsSent(keyword);
364 // GetFixupURIInfo only returns a post data stream if it succeeded
365 // and changed the URI, in which case we should override the
366 // passed-in post data by passing this as an override arg to
367 // our internal method.
368 fixupInfo->GetPostData(getter_AddRefs(fixupStream));
370 if (fixupInfo &&
371 loadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
372 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
373 if (serv) {
374 serv->NotifyObservers(fixupInfo, "keyword-uri-fixup",
375 PromiseFlatString(aURI).get());
378 nsDocShell::MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
383 if (rv == NS_ERROR_MALFORMED_URI) {
384 MOZ_ASSERT(!uri);
385 return rv;
388 if (NS_FAILED(rv) || !uri) {
389 return NS_ERROR_FAILURE;
392 RefPtr<nsDocShellLoadState> loadState;
393 rv = CreateFromLoadURIOptions(
394 aBrowsingContext, uri, aLoadURIOptions, loadFlags,
395 fixupStream ? fixupStream : aLoadURIOptions.mPostData,
396 getter_AddRefs(loadState));
397 NS_ENSURE_SUCCESS(rv, rv);
398 loadState->SetOriginalURIString(uriString);
399 loadState.forget(aResult);
400 return NS_OK;
403 nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
404 BrowsingContext* aBrowsingContext, nsIURI* aURI,
405 const LoadURIOptions& aLoadURIOptions, nsDocShellLoadState** aResult) {
406 return CreateFromLoadURIOptions(aBrowsingContext, aURI, aLoadURIOptions,
407 aLoadURIOptions.mLoadFlags,
408 aLoadURIOptions.mPostData, aResult);
411 nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
412 BrowsingContext* aBrowsingContext, nsIURI* aURI,
413 const LoadURIOptions& aLoadURIOptions, uint32_t aLoadFlagsOverride,
414 nsIInputStream* aPostDataOverride, nsDocShellLoadState** aResult) {
415 nsresult rv = NS_OK;
416 uint32_t loadFlags = aLoadFlagsOverride;
417 RefPtr<nsIInputStream> postData = aPostDataOverride;
418 uint64_t available;
419 if (postData) {
420 rv = postData->Available(&available);
421 NS_ENSURE_SUCCESS(rv, rv);
422 if (available == 0) {
423 return NS_ERROR_INVALID_ARG;
427 if (aLoadURIOptions.mHeaders) {
428 rv = aLoadURIOptions.mHeaders->Available(&available);
429 NS_ENSURE_SUCCESS(rv, rv);
430 if (available == 0) {
431 return NS_ERROR_INVALID_ARG;
435 bool forceAllowDataURI =
436 loadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
438 // Don't pass certain flags that aren't needed and end up confusing
439 // ConvertLoadTypeToDocShellInfoLoadType. We do need to ensure that they are
440 // passed to LoadURI though, since it uses them.
441 uint32_t extraFlags = (loadFlags & EXTRA_LOAD_FLAGS);
442 loadFlags &= ~EXTRA_LOAD_FLAGS;
444 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
445 loadState->SetReferrerInfo(aLoadURIOptions.mReferrerInfo);
447 loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags));
449 loadState->SetLoadFlags(extraFlags);
450 loadState->SetFirstParty(true);
451 loadState->SetHasValidUserGestureActivation(
452 aLoadURIOptions.mHasValidUserGestureActivation);
453 loadState->SetTriggeringSandboxFlags(aLoadURIOptions.mTriggeringSandboxFlags);
454 loadState->SetTriggeringWindowId(aLoadURIOptions.mTriggeringWindowId);
455 loadState->SetTriggeringStorageAccess(
456 aLoadURIOptions.mTriggeringStorageAccess);
457 loadState->SetPostDataStream(postData);
458 loadState->SetHeadersStream(aLoadURIOptions.mHeaders);
459 loadState->SetBaseURI(aLoadURIOptions.mBaseURI);
460 loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal);
461 loadState->SetCsp(aLoadURIOptions.mCsp);
462 loadState->SetForceAllowDataURI(forceAllowDataURI);
463 if (aLoadURIOptions.mCancelContentJSEpoch) {
464 loadState->SetCancelContentJSEpoch(aLoadURIOptions.mCancelContentJSEpoch);
467 if (aLoadURIOptions.mTriggeringRemoteType.WasPassed()) {
468 if (XRE_IsParentProcess()) {
469 loadState->SetTriggeringRemoteType(
470 aLoadURIOptions.mTriggeringRemoteType.Value());
471 } else if (ContentChild::GetSingleton()->GetRemoteType() !=
472 aLoadURIOptions.mTriggeringRemoteType.Value()) {
473 NS_WARNING("Invalid TriggeringRemoteType from LoadURIOptions in content");
474 return NS_ERROR_INVALID_ARG;
478 if (aLoadURIOptions.mRemoteTypeOverride.WasPassed()) {
479 loadState->SetRemoteTypeOverride(
480 aLoadURIOptions.mRemoteTypeOverride.Value());
483 loadState->SetWasSchemelessInput(aLoadURIOptions.mWasSchemelessInput);
485 loadState.forget(aResult);
486 return NS_OK;
489 nsIReferrerInfo* nsDocShellLoadState::GetReferrerInfo() const {
490 return mReferrerInfo;
493 void nsDocShellLoadState::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
494 mReferrerInfo = aReferrerInfo;
497 nsIURI* nsDocShellLoadState::URI() const { return mURI; }
499 void nsDocShellLoadState::SetURI(nsIURI* aURI) { mURI = aURI; }
501 nsIURI* nsDocShellLoadState::OriginalURI() const { return mOriginalURI; }
503 void nsDocShellLoadState::SetOriginalURI(nsIURI* aOriginalURI) {
504 mOriginalURI = aOriginalURI;
507 nsIURI* nsDocShellLoadState::ResultPrincipalURI() const {
508 return mResultPrincipalURI;
511 void nsDocShellLoadState::SetResultPrincipalURI(nsIURI* aResultPrincipalURI) {
512 mResultPrincipalURI = aResultPrincipalURI;
515 bool nsDocShellLoadState::ResultPrincipalURIIsSome() const {
516 return mResultPrincipalURIIsSome;
519 void nsDocShellLoadState::SetResultPrincipalURIIsSome(bool aIsSome) {
520 mResultPrincipalURIIsSome = aIsSome;
523 bool nsDocShellLoadState::KeepResultPrincipalURIIfSet() const {
524 return mKeepResultPrincipalURIIfSet;
527 void nsDocShellLoadState::SetKeepResultPrincipalURIIfSet(bool aKeep) {
528 mKeepResultPrincipalURIIfSet = aKeep;
531 bool nsDocShellLoadState::LoadReplace() const { return mLoadReplace; }
533 void nsDocShellLoadState::SetLoadReplace(bool aLoadReplace) {
534 mLoadReplace = aLoadReplace;
537 nsIPrincipal* nsDocShellLoadState::TriggeringPrincipal() const {
538 return mTriggeringPrincipal;
541 void nsDocShellLoadState::SetTriggeringPrincipal(
542 nsIPrincipal* aTriggeringPrincipal) {
543 mTriggeringPrincipal = aTriggeringPrincipal;
546 nsIPrincipal* nsDocShellLoadState::PrincipalToInherit() const {
547 return mPrincipalToInherit;
550 void nsDocShellLoadState::SetPrincipalToInherit(
551 nsIPrincipal* aPrincipalToInherit) {
552 mPrincipalToInherit = aPrincipalToInherit;
555 nsIPrincipal* nsDocShellLoadState::PartitionedPrincipalToInherit() const {
556 return mPartitionedPrincipalToInherit;
559 void nsDocShellLoadState::SetPartitionedPrincipalToInherit(
560 nsIPrincipal* aPartitionedPrincipalToInherit) {
561 mPartitionedPrincipalToInherit = aPartitionedPrincipalToInherit;
564 void nsDocShellLoadState::SetCsp(nsIContentSecurityPolicy* aCsp) {
565 mCsp = aCsp;
568 nsIContentSecurityPolicy* nsDocShellLoadState::Csp() const { return mCsp; }
570 void nsDocShellLoadState::SetTriggeringSandboxFlags(uint32_t flags) {
571 mTriggeringSandboxFlags = flags;
574 uint32_t nsDocShellLoadState::TriggeringSandboxFlags() const {
575 return mTriggeringSandboxFlags;
578 void nsDocShellLoadState::SetTriggeringWindowId(uint64_t aTriggeringWindowId) {
579 mTriggeringWindowId = aTriggeringWindowId;
582 uint64_t nsDocShellLoadState::TriggeringWindowId() const {
583 return mTriggeringWindowId;
586 void nsDocShellLoadState::SetTriggeringStorageAccess(
587 bool aTriggeringStorageAccess) {
588 mTriggeringStorageAccess = aTriggeringStorageAccess;
591 bool nsDocShellLoadState::TriggeringStorageAccess() const {
592 return mTriggeringStorageAccess;
595 bool nsDocShellLoadState::InheritPrincipal() const { return mInheritPrincipal; }
597 void nsDocShellLoadState::SetInheritPrincipal(bool aInheritPrincipal) {
598 mInheritPrincipal = aInheritPrincipal;
601 bool nsDocShellLoadState::PrincipalIsExplicit() const {
602 return mPrincipalIsExplicit;
605 void nsDocShellLoadState::SetPrincipalIsExplicit(bool aPrincipalIsExplicit) {
606 mPrincipalIsExplicit = aPrincipalIsExplicit;
609 bool nsDocShellLoadState::NotifiedBeforeUnloadListeners() const {
610 return mNotifiedBeforeUnloadListeners;
613 void nsDocShellLoadState::SetNotifiedBeforeUnloadListeners(
614 bool aNotifiedBeforeUnloadListeners) {
615 mNotifiedBeforeUnloadListeners = aNotifiedBeforeUnloadListeners;
618 bool nsDocShellLoadState::ForceAllowDataURI() const {
619 return mForceAllowDataURI;
622 void nsDocShellLoadState::SetForceAllowDataURI(bool aForceAllowDataURI) {
623 mForceAllowDataURI = aForceAllowDataURI;
626 bool nsDocShellLoadState::IsExemptFromHTTPSFirstMode() const {
627 return mIsExemptFromHTTPSFirstMode;
630 void nsDocShellLoadState::SetIsExemptFromHTTPSFirstMode(
631 bool aIsExemptFromHTTPSFirstMode) {
632 mIsExemptFromHTTPSFirstMode = aIsExemptFromHTTPSFirstMode;
635 bool nsDocShellLoadState::OriginalFrameSrc() const { return mOriginalFrameSrc; }
637 void nsDocShellLoadState::SetOriginalFrameSrc(bool aOriginalFrameSrc) {
638 mOriginalFrameSrc = aOriginalFrameSrc;
641 bool nsDocShellLoadState::IsFormSubmission() const { return mIsFormSubmission; }
643 void nsDocShellLoadState::SetIsFormSubmission(bool aIsFormSubmission) {
644 mIsFormSubmission = aIsFormSubmission;
647 uint32_t nsDocShellLoadState::LoadType() const { return mLoadType; }
649 void nsDocShellLoadState::SetLoadType(uint32_t aLoadType) {
650 mLoadType = aLoadType;
653 nsISHEntry* nsDocShellLoadState::SHEntry() const { return mSHEntry; }
655 void nsDocShellLoadState::SetSHEntry(nsISHEntry* aSHEntry) {
656 mSHEntry = aSHEntry;
657 nsCOMPtr<SessionHistoryEntry> she = do_QueryInterface(aSHEntry);
658 if (she) {
659 mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(she);
660 } else {
661 mLoadingSessionHistoryInfo = nullptr;
665 void nsDocShellLoadState::SetLoadingSessionHistoryInfo(
666 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo) {
667 SetLoadingSessionHistoryInfo(
668 MakeUnique<mozilla::dom::LoadingSessionHistoryInfo>(aLoadingInfo));
671 void nsDocShellLoadState::SetLoadingSessionHistoryInfo(
672 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> aLoadingInfo) {
673 mLoadingSessionHistoryInfo = std::move(aLoadingInfo);
676 const mozilla::dom::LoadingSessionHistoryInfo*
677 nsDocShellLoadState::GetLoadingSessionHistoryInfo() const {
678 return mLoadingSessionHistoryInfo.get();
681 void nsDocShellLoadState::SetLoadIsFromSessionHistory(
682 int32_t aOffset, bool aLoadingCurrentEntry) {
683 if (mLoadingSessionHistoryInfo) {
684 mLoadingSessionHistoryInfo->mLoadIsFromSessionHistory = true;
685 mLoadingSessionHistoryInfo->mOffset = aOffset;
686 mLoadingSessionHistoryInfo->mLoadingCurrentEntry = aLoadingCurrentEntry;
690 void nsDocShellLoadState::ClearLoadIsFromSessionHistory() {
691 if (mLoadingSessionHistoryInfo) {
692 mLoadingSessionHistoryInfo->mLoadIsFromSessionHistory = false;
694 mSHEntry = nullptr;
697 bool nsDocShellLoadState::LoadIsFromSessionHistory() const {
698 return mLoadingSessionHistoryInfo
699 ? mLoadingSessionHistoryInfo->mLoadIsFromSessionHistory
700 : !!mSHEntry;
703 void nsDocShellLoadState::MaybeStripTrackerQueryStrings(
704 BrowsingContext* aContext) {
705 MOZ_ASSERT(aContext);
707 // Return early if the triggering principal doesn't exist. This could happen
708 // when loading a URL by using a browsing context in the Browser Toolbox.
709 if (!TriggeringPrincipal()) {
710 return;
713 // We don't need to strip for sub frames because the query string has been
714 // stripped in the top-level content. Also, we don't apply stripping if it
715 // is triggered by addons.
717 // Note that we don't need to do the stripping if the channel has been
718 // initialized. This means that this has been loaded speculatively in the
719 // parent process before and the stripping was happening by then.
720 if (GetChannelInitialized() || !aContext->IsTopContent() ||
721 BasePrincipal::Cast(TriggeringPrincipal())->AddonPolicy()) {
722 return;
725 // We don't strip the URI if it's the same-site navigation. Note that we will
726 // consider the system principal triggered load as third-party in case the
727 // user copies and pastes a URL which has tracking query parameters or an
728 // loading from external applications, such as clicking a link in an email
729 // client.
730 bool isThirdPartyURI = false;
731 if (!TriggeringPrincipal()->IsSystemPrincipal() &&
732 (NS_FAILED(
733 TriggeringPrincipal()->IsThirdPartyURI(URI(), &isThirdPartyURI)) ||
734 !isThirdPartyURI)) {
735 return;
738 Telemetry::AccumulateCategorical(
739 Telemetry::LABELS_QUERY_STRIPPING_COUNT::Navigation);
741 nsCOMPtr<nsIURI> strippedURI;
743 nsresult rv;
744 nsCOMPtr<nsIURLQueryStringStripper> queryStripper =
745 components::URLQueryStringStripper::Service(&rv);
746 NS_ENSURE_SUCCESS_VOID(rv);
748 uint32_t numStripped;
750 queryStripper->Strip(URI(), aContext->UsePrivateBrowsing(),
751 getter_AddRefs(strippedURI), &numStripped);
752 if (numStripped) {
753 if (!mUnstrippedURI) {
754 mUnstrippedURI = URI();
756 SetURI(strippedURI);
758 Telemetry::AccumulateCategorical(
759 Telemetry::LABELS_QUERY_STRIPPING_COUNT::StripForNavigation);
760 Telemetry::Accumulate(Telemetry::QUERY_STRIPPING_PARAM_COUNT, numStripped);
763 #ifdef DEBUG
764 // Make sure that unstripped URI is the same as URI() but only the query
765 // string could be different.
766 if (mUnstrippedURI) {
767 nsCOMPtr<nsIURI> uri;
768 Unused << queryStripper->Strip(mUnstrippedURI,
769 aContext->UsePrivateBrowsing(),
770 getter_AddRefs(uri), &numStripped);
771 bool equals = false;
772 Unused << URI()->Equals(uri, &equals);
773 MOZ_ASSERT(equals);
775 #endif
778 const nsString& nsDocShellLoadState::Target() const { return mTarget; }
780 void nsDocShellLoadState::SetTarget(const nsAString& aTarget) {
781 mTarget = aTarget;
784 nsIInputStream* nsDocShellLoadState::PostDataStream() const {
785 return mPostDataStream;
788 void nsDocShellLoadState::SetPostDataStream(nsIInputStream* aStream) {
789 mPostDataStream = aStream;
792 nsIInputStream* nsDocShellLoadState::HeadersStream() const {
793 return mHeadersStream;
796 void nsDocShellLoadState::SetHeadersStream(nsIInputStream* aHeadersStream) {
797 mHeadersStream = aHeadersStream;
800 const nsString& nsDocShellLoadState::SrcdocData() const { return mSrcdocData; }
802 void nsDocShellLoadState::SetSrcdocData(const nsAString& aSrcdocData) {
803 mSrcdocData = aSrcdocData;
806 void nsDocShellLoadState::SetSourceBrowsingContext(
807 BrowsingContext* aSourceBrowsingContext) {
808 mSourceBrowsingContext = aSourceBrowsingContext;
811 void nsDocShellLoadState::SetTargetBrowsingContext(
812 BrowsingContext* aTargetBrowsingContext) {
813 mTargetBrowsingContext = aTargetBrowsingContext;
816 nsIURI* nsDocShellLoadState::BaseURI() const { return mBaseURI; }
818 void nsDocShellLoadState::SetBaseURI(nsIURI* aBaseURI) { mBaseURI = aBaseURI; }
820 void nsDocShellLoadState::GetMaybeResultPrincipalURI(
821 mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const {
822 bool isSome = ResultPrincipalURIIsSome();
823 aRPURI.reset();
825 if (!isSome) {
826 return;
829 nsCOMPtr<nsIURI> uri = ResultPrincipalURI();
830 aRPURI.emplace(std::move(uri));
833 void nsDocShellLoadState::SetMaybeResultPrincipalURI(
834 mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI) {
835 SetResultPrincipalURI(aRPURI.refOr(nullptr));
836 SetResultPrincipalURIIsSome(aRPURI.isSome());
839 uint32_t nsDocShellLoadState::LoadFlags() const { return mLoadFlags; }
841 void nsDocShellLoadState::SetLoadFlags(uint32_t aLoadFlags) {
842 mLoadFlags = aLoadFlags;
845 void nsDocShellLoadState::SetLoadFlag(uint32_t aFlag) { mLoadFlags |= aFlag; }
847 void nsDocShellLoadState::UnsetLoadFlag(uint32_t aFlag) {
848 mLoadFlags &= ~aFlag;
851 bool nsDocShellLoadState::HasLoadFlags(uint32_t aFlags) {
852 return (mLoadFlags & aFlags) == aFlags;
855 uint32_t nsDocShellLoadState::InternalLoadFlags() const {
856 return mInternalLoadFlags;
859 void nsDocShellLoadState::SetInternalLoadFlags(uint32_t aLoadFlags) {
860 mInternalLoadFlags = aLoadFlags;
863 void nsDocShellLoadState::SetInternalLoadFlag(uint32_t aFlag) {
864 mInternalLoadFlags |= aFlag;
867 void nsDocShellLoadState::UnsetInternalLoadFlag(uint32_t aFlag) {
868 mInternalLoadFlags &= ~aFlag;
871 bool nsDocShellLoadState::HasInternalLoadFlags(uint32_t aFlags) {
872 return (mInternalLoadFlags & aFlags) == aFlags;
875 bool nsDocShellLoadState::FirstParty() const { return mFirstParty; }
877 void nsDocShellLoadState::SetFirstParty(bool aFirstParty) {
878 mFirstParty = aFirstParty;
881 bool nsDocShellLoadState::HasValidUserGestureActivation() const {
882 return mHasValidUserGestureActivation;
885 void nsDocShellLoadState::SetHasValidUserGestureActivation(
886 bool aHasValidUserGestureActivation) {
887 mHasValidUserGestureActivation = aHasValidUserGestureActivation;
890 const nsCString& nsDocShellLoadState::TypeHint() const { return mTypeHint; }
892 void nsDocShellLoadState::SetTypeHint(const nsCString& aTypeHint) {
893 mTypeHint = aTypeHint;
896 const nsString& nsDocShellLoadState::FileName() const { return mFileName; }
898 void nsDocShellLoadState::SetFileName(const nsAString& aFileName) {
899 MOZ_DIAGNOSTIC_ASSERT(aFileName.FindChar(char16_t(0)) == kNotFound,
900 "The filename should never contain null characters");
901 mFileName = aFileName;
904 void nsDocShellLoadState::SetRemoteTypeOverride(
905 const nsCString& aRemoteTypeOverride) {
906 MOZ_DIAGNOSTIC_ASSERT(
907 NS_IsAboutBlank(mURI),
908 "Should only have aRemoteTypeOverride for about:blank URIs");
909 mRemoteTypeOverride = mozilla::Some(aRemoteTypeOverride);
912 const nsCString& nsDocShellLoadState::GetEffectiveTriggeringRemoteType() const {
913 // Consider non-errorpage loads from session history as being triggred by the
914 // parent process, as we'll validate them against the history entry.
916 // NOTE: Keep this check in-sync with the session-history validation check in
917 // `DocumentLoadListener::Open`!
918 if (LoadIsFromSessionHistory() && LoadType() != LOAD_ERROR_PAGE) {
919 return NOT_REMOTE_TYPE;
921 return mTriggeringRemoteType;
924 void nsDocShellLoadState::SetTriggeringRemoteType(
925 const nsACString& aTriggeringRemoteType) {
926 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "only settable in parent");
927 mTriggeringRemoteType = aTriggeringRemoteType;
930 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
931 void nsDocShellLoadState::AssertProcessCouldTriggerLoadIfSystem() {
932 // Early check to see if we're trying to start a file URI load with a system
933 // principal within a web content process.
934 // If this assertion fails, the load will fail later during
935 // nsContentSecurityManager checks, however this assertion should happen
936 // closer to whichever caller is triggering the system-principal load.
937 if (mozilla::SessionHistoryInParent() &&
938 TriggeringPrincipal()->IsSystemPrincipal() &&
939 mozilla::dom::IsWebRemoteType(GetEffectiveTriggeringRemoteType())) {
940 bool localFile = false;
941 if (NS_SUCCEEDED(NS_URIChainHasFlags(
942 URI(), nsIProtocolHandler::URI_IS_LOCAL_FILE, &localFile)) &&
943 localFile) {
944 NS_WARNING(nsPrintfCString("Unexpected system load of file URI (%s) from "
945 "web content process",
946 URI()->GetSpecOrDefault().get())
947 .get());
948 MOZ_CRASH("Unexpected system load of file URI from web content process");
952 #endif
954 nsresult nsDocShellLoadState::SetupInheritingPrincipal(
955 BrowsingContext::Type aType,
956 const mozilla::OriginAttributes& aOriginAttributes) {
957 // We need a principalToInherit.
959 // If principalIsExplicit is not set there are 4 possibilities:
960 // (1) If the system principal or an expanded principal was passed
961 // in and we're a typeContent docshell, inherit the principal
962 // from the current document instead.
963 // (2) In all other cases when the principal passed in is not null,
964 // use that principal.
965 // (3) If the caller has allowed inheriting from the current document,
966 // or if we're being called from system code (eg chrome JS or pure
967 // C++) then inheritPrincipal should be true and InternalLoad will get
968 // a principal from the current document. If none of these things are
969 // true, then
970 // (4) we don't pass a principal into the channel, and a principal will be
971 // created later from the channel's internal data.
973 // If principalIsExplicit *is* set, there are 4 possibilities
974 // (1) If the system principal or an expanded principal was passed in
975 // and we're a typeContent docshell, return an error.
976 // (2) In all other cases when the principal passed in is not null,
977 // use that principal.
978 // (3) If the caller has allowed inheriting from the current document,
979 // then inheritPrincipal should be true and InternalLoad will get
980 // a principal from the current document. If none of these things are
981 // true, then
982 // (4) we dont' pass a principal into the channel, and a principal will be
983 // created later from the channel's internal data.
984 mPrincipalToInherit = mTriggeringPrincipal;
985 if (mPrincipalToInherit && aType != BrowsingContext::Type::Chrome) {
986 if (mPrincipalToInherit->IsSystemPrincipal()) {
987 if (mPrincipalIsExplicit) {
988 return NS_ERROR_DOM_SECURITY_ERR;
990 mPrincipalToInherit = nullptr;
991 mInheritPrincipal = true;
992 } else if (nsContentUtils::IsExpandedPrincipal(mPrincipalToInherit)) {
993 if (mPrincipalIsExplicit) {
994 return NS_ERROR_DOM_SECURITY_ERR;
996 // Don't inherit from the current page. Just do the safe thing
997 // and pretend that we were loaded by a nullprincipal.
999 // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
1000 // have origin attributes.
1001 mPrincipalToInherit = NullPrincipal::Create(aOriginAttributes);
1002 mInheritPrincipal = false;
1006 if (!mPrincipalToInherit && !mInheritPrincipal && !mPrincipalIsExplicit) {
1007 // See if there's system or chrome JS code running
1008 mInheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
1011 if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
1012 mInheritPrincipal = false;
1013 // Create a new null principal URI based on our precursor principal.
1014 nsCOMPtr<nsIURI> nullPrincipalURI =
1015 NullPrincipal::CreateURI(mPrincipalToInherit);
1016 // If mFirstParty is true and the pref 'privacy.firstparty.isolate' is
1017 // enabled, we will set firstPartyDomain on the origin attributes.
1018 OriginAttributes attrs(aOriginAttributes);
1019 if (mFirstParty) {
1020 attrs.SetFirstPartyDomain(true, nullPrincipalURI);
1022 mPrincipalToInherit = NullPrincipal::Create(attrs, nullPrincipalURI);
1025 return NS_OK;
1028 nsresult nsDocShellLoadState::SetupTriggeringPrincipal(
1029 const mozilla::OriginAttributes& aOriginAttributes) {
1030 // If the triggeringPrincipal is not set, we first try to create a principal
1031 // from the referrer, since the referrer URI reflects the web origin that
1032 // triggered the load. If there is no referrer URI, we fall back to using the
1033 // SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
1034 // and no referrer simulate a load that was triggered by the system. It's
1035 // important to note that this block of code needs to appear *after* the block
1036 // where we munge the principalToInherit, because otherwise we would never
1037 // enter code blocks checking if the principalToInherit is null and we will
1038 // end up with a wrong inheritPrincipal flag.
1039 if (!mTriggeringPrincipal) {
1040 if (mReferrerInfo) {
1041 nsCOMPtr<nsIURI> referrer = mReferrerInfo->GetOriginalReferrer();
1042 mTriggeringPrincipal =
1043 BasePrincipal::CreateContentPrincipal(referrer, aOriginAttributes);
1045 if (!mTriggeringPrincipal) {
1046 return NS_ERROR_FAILURE;
1048 } else {
1049 mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
1052 return NS_OK;
1055 void nsDocShellLoadState::CalculateLoadURIFlags() {
1056 if (mInheritPrincipal) {
1057 MOZ_ASSERT(
1058 !mPrincipalToInherit || !mPrincipalToInherit->IsSystemPrincipal(),
1059 "Should not inherit SystemPrincipal");
1060 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
1063 if (mReferrerInfo && !mReferrerInfo->GetSendReferrer()) {
1064 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
1066 if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
1067 mInternalLoadFlags |=
1068 nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
1071 if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) {
1072 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD;
1075 if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CLASSIFIER) {
1076 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
1079 if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
1080 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
1083 if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE) {
1084 mInternalLoadFlags |=
1085 nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE;
1088 if (!mSrcdocData.IsVoid()) {
1089 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
1092 if (mForceAllowDataURI) {
1093 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
1096 if (mOriginalFrameSrc) {
1097 mInternalLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC;
1101 nsLoadFlags nsDocShellLoadState::CalculateChannelLoadFlags(
1102 BrowsingContext* aBrowsingContext, Maybe<bool> aUriModified,
1103 Maybe<bool> aIsEmbeddingBlockedError) {
1104 MOZ_ASSERT(aBrowsingContext);
1106 nsLoadFlags loadFlags = aBrowsingContext->GetDefaultLoadFlags();
1108 if (FirstParty()) {
1109 // tag first party URL loads
1110 loadFlags |= nsIChannel::LOAD_INITIAL_DOCUMENT_URI;
1113 const uint32_t loadType = LoadType();
1115 // These values aren't available for loads initiated in the Parent process.
1116 MOZ_ASSERT_IF(loadType == LOAD_HISTORY, aUriModified.isSome());
1117 MOZ_ASSERT_IF(loadType == LOAD_ERROR_PAGE, aIsEmbeddingBlockedError.isSome());
1119 if (loadType == LOAD_ERROR_PAGE) {
1120 // Error pages are LOAD_BACKGROUND, unless it's an
1121 // XFO / frame-ancestors error for which we want an error page to load
1122 // but additionally want the onload() event to fire.
1123 if (!*aIsEmbeddingBlockedError) {
1124 loadFlags |= nsIChannel::LOAD_BACKGROUND;
1128 // Mark the channel as being a document URI and allow content sniffing...
1129 loadFlags |=
1130 nsIChannel::LOAD_DOCUMENT_URI | nsIChannel::LOAD_CALL_CONTENT_SNIFFERS;
1132 if (nsDocShell::SandboxFlagsImplyCookies(
1133 aBrowsingContext->GetSandboxFlags())) {
1134 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
1137 // Load attributes depend on load type...
1138 switch (loadType) {
1139 case LOAD_HISTORY: {
1140 // Only send VALIDATE_NEVER if mLSHE's URI was never changed via
1141 // push/replaceState (bug 669671).
1142 if (!*aUriModified) {
1143 loadFlags |= nsIRequest::VALIDATE_NEVER;
1145 break;
1148 case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
1149 case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
1150 loadFlags |=
1151 nsIRequest::LOAD_BYPASS_CACHE | nsIRequest::LOAD_FRESH_CONNECTION;
1152 [[fallthrough]];
1154 case LOAD_REFRESH:
1155 loadFlags |= nsIRequest::VALIDATE_ALWAYS;
1156 break;
1158 case LOAD_NORMAL_BYPASS_CACHE:
1159 case LOAD_NORMAL_BYPASS_PROXY:
1160 case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
1161 case LOAD_RELOAD_BYPASS_CACHE:
1162 case LOAD_RELOAD_BYPASS_PROXY:
1163 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
1164 case LOAD_REPLACE_BYPASS_CACHE:
1165 loadFlags |=
1166 nsIRequest::LOAD_BYPASS_CACHE | nsIRequest::LOAD_FRESH_CONNECTION;
1167 break;
1169 case LOAD_RELOAD_NORMAL:
1170 if (!StaticPrefs::
1171 browser_soft_reload_only_force_validate_top_level_document()) {
1172 loadFlags |= nsIRequest::VALIDATE_ALWAYS;
1173 break;
1175 [[fallthrough]];
1176 case LOAD_NORMAL:
1177 case LOAD_LINK:
1178 // Set cache checking flags
1179 switch (StaticPrefs::browser_cache_check_doc_frequency()) {
1180 case 0:
1181 loadFlags |= nsIRequest::VALIDATE_ONCE_PER_SESSION;
1182 break;
1183 case 1:
1184 loadFlags |= nsIRequest::VALIDATE_ALWAYS;
1185 break;
1186 case 2:
1187 loadFlags |= nsIRequest::VALIDATE_NEVER;
1188 break;
1190 break;
1193 if (HasInternalLoadFlags(nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER)) {
1194 loadFlags |= nsIChannel::LOAD_BYPASS_URL_CLASSIFIER;
1197 // If the user pressed shift-reload, then do not allow ServiceWorker
1198 // interception to occur. See step 12.1 of the SW HandleFetch algorithm.
1199 if (IsForceReloadType(loadType)) {
1200 loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
1203 return loadFlags;
1206 const char* nsDocShellLoadState::ValidateWithOriginalState(
1207 nsDocShellLoadState* aOriginalState) {
1208 MOZ_ASSERT(mLoadIdentifier == aOriginalState->mLoadIdentifier);
1210 // Check that `aOriginalState` is sufficiently similar to this state that
1211 // they're performing the same load.
1212 auto uriEq = [](nsIURI* a, nsIURI* b) -> bool {
1213 bool eq = false;
1214 return a == b || (a && b && NS_SUCCEEDED(a->Equals(b, &eq)) && eq);
1216 if (!uriEq(mURI, aOriginalState->mURI)) {
1217 return "URI";
1219 if (!uriEq(mUnstrippedURI, aOriginalState->mUnstrippedURI)) {
1220 return "UnstrippedURI";
1222 if (!uriEq(mOriginalURI, aOriginalState->mOriginalURI)) {
1223 return "OriginalURI";
1225 if (!uriEq(mBaseURI, aOriginalState->mBaseURI)) {
1226 return "BaseURI";
1229 if (!mTriggeringPrincipal->Equals(aOriginalState->mTriggeringPrincipal)) {
1230 return "TriggeringPrincipal";
1232 if (mTriggeringSandboxFlags != aOriginalState->mTriggeringSandboxFlags) {
1233 return "TriggeringSandboxFlags";
1235 if (mTriggeringRemoteType != aOriginalState->mTriggeringRemoteType) {
1236 return "TriggeringRemoteType";
1239 if (mOriginalURIString != aOriginalState->mOriginalURIString) {
1240 return "OriginalURIString";
1243 if (mRemoteTypeOverride != aOriginalState->mRemoteTypeOverride) {
1244 return "RemoteTypeOverride";
1247 if (mSourceBrowsingContext.ContextId() !=
1248 aOriginalState->mSourceBrowsingContext.ContextId()) {
1249 return "SourceBrowsingContext";
1252 // FIXME: Consider calculating less information in the target process so that
1253 // we can validate more properties more easily.
1254 // FIXME: Identify what other flags will not change when sent through a
1255 // content process.
1257 return nullptr;
1260 DocShellLoadStateInit nsDocShellLoadState::Serialize(
1261 mozilla::ipc::IProtocol* aActor) {
1262 MOZ_ASSERT(aActor);
1263 DocShellLoadStateInit loadState;
1264 loadState.ResultPrincipalURI() = mResultPrincipalURI;
1265 loadState.ResultPrincipalURIIsSome() = mResultPrincipalURIIsSome;
1266 loadState.KeepResultPrincipalURIIfSet() = mKeepResultPrincipalURIIfSet;
1267 loadState.LoadReplace() = mLoadReplace;
1268 loadState.InheritPrincipal() = mInheritPrincipal;
1269 loadState.PrincipalIsExplicit() = mPrincipalIsExplicit;
1270 loadState.ForceAllowDataURI() = mForceAllowDataURI;
1271 loadState.IsExemptFromHTTPSFirstMode() = mIsExemptFromHTTPSFirstMode;
1272 loadState.OriginalFrameSrc() = mOriginalFrameSrc;
1273 loadState.IsFormSubmission() = mIsFormSubmission;
1274 loadState.LoadType() = mLoadType;
1275 loadState.Target() = mTarget;
1276 loadState.TargetBrowsingContext() = mTargetBrowsingContext;
1277 loadState.LoadFlags() = mLoadFlags;
1278 loadState.InternalLoadFlags() = mInternalLoadFlags;
1279 loadState.FirstParty() = mFirstParty;
1280 loadState.HasValidUserGestureActivation() = mHasValidUserGestureActivation;
1281 loadState.AllowFocusMove() = mAllowFocusMove;
1282 loadState.TypeHint() = mTypeHint;
1283 loadState.FileName() = mFileName;
1284 loadState.IsFromProcessingFrameAttributes() =
1285 mIsFromProcessingFrameAttributes;
1286 loadState.URI() = mURI;
1287 loadState.OriginalURI() = mOriginalURI;
1288 loadState.SourceBrowsingContext() = mSourceBrowsingContext;
1289 loadState.BaseURI() = mBaseURI;
1290 loadState.TriggeringPrincipal() = mTriggeringPrincipal;
1291 loadState.PrincipalToInherit() = mPrincipalToInherit;
1292 loadState.PartitionedPrincipalToInherit() = mPartitionedPrincipalToInherit;
1293 loadState.TriggeringSandboxFlags() = mTriggeringSandboxFlags;
1294 loadState.TriggeringWindowId() = mTriggeringWindowId;
1295 loadState.TriggeringStorageAccess() = mTriggeringStorageAccess;
1296 loadState.TriggeringRemoteType() = mTriggeringRemoteType;
1297 loadState.WasSchemelessInput() = mWasSchemelessInput;
1298 loadState.Csp() = mCsp;
1299 loadState.OriginalURIString() = mOriginalURIString;
1300 loadState.CancelContentJSEpoch() = mCancelContentJSEpoch;
1301 loadState.ReferrerInfo() = mReferrerInfo;
1302 loadState.PostDataStream() = mPostDataStream;
1303 loadState.HeadersStream() = mHeadersStream;
1304 loadState.SrcdocData() = mSrcdocData;
1305 loadState.ResultPrincipalURI() = mResultPrincipalURI;
1306 loadState.LoadIdentifier() = mLoadIdentifier;
1307 loadState.ChannelInitialized() = mChannelInitialized;
1308 loadState.IsMetaRefresh() = mIsMetaRefresh;
1309 if (mLoadingSessionHistoryInfo) {
1310 loadState.loadingSessionHistoryInfo().emplace(*mLoadingSessionHistoryInfo);
1312 loadState.UnstrippedURI() = mUnstrippedURI;
1313 loadState.RemoteTypeOverride() = mRemoteTypeOverride;
1315 if (XRE_IsParentProcess()) {
1316 mozilla::ipc::IToplevelProtocol* top = aActor->ToplevelProtocol();
1317 MOZ_RELEASE_ASSERT(top &&
1318 top->GetProtocolId() ==
1319 mozilla::ipc::ProtocolId::PContentMsgStart &&
1320 top->GetSide() == mozilla::ipc::ParentSide,
1321 "nsDocShellLoadState must be sent over PContent");
1322 ContentParent* cp = static_cast<ContentParent*>(top);
1323 cp->StorePendingLoadState(this);
1326 return loadState;
1329 nsIURI* nsDocShellLoadState::GetUnstrippedURI() const { return mUnstrippedURI; }
1331 void nsDocShellLoadState::SetUnstrippedURI(nsIURI* aUnstrippedURI) {
1332 mUnstrippedURI = aUnstrippedURI;