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/. */
6
7 #include "nsDocShellLoadState.h"
8 #include "nsIDocShell.h"
9 #include "nsDocShell.h"
10 #include "nsISHEntry.h"
11 #include "nsIURIFixup.h"
12 #include "nsIWebNavigation.h"
13 #include "nsIChannel.h"
14 #include "nsNetUtil.h"
15 #include "nsQueryObject.h"
16 #include "ReferrerInfo.h"
17 #include "mozilla/BasePrincipal.h"
18 #include "mozilla/ClearOnShutdown.h"
19 #include "mozilla/Components.h"
20 #include "mozilla/dom/BrowsingContext.h"
21 #include "mozilla/dom/ContentChild.h"
22 #include "mozilla/dom/LoadURIOptionsBinding.h"
23 #include "mozilla/StaticPrefs_fission.h"
24
25 #include "mozilla/OriginAttributes.h"
26 #include "mozilla/NullPrincipal.h"
27 #include "mozilla/StaticPtr.h"
28
29 #include "mozilla/dom/PContent.h"
30
31 using namespace mozilla;
32 using namespace mozilla::dom;
33
34 // Global reference to the URI fixup service.
35 static mozilla::StaticRefPtr<nsIURIFixup> sURIFixup;
36
37 namespace {
GetFixupURIInfo(const nsACString & aStringURI,uint32_t aFixupFlags,nsIInputStream ** aPostData)38 already_AddRefed<nsIURIFixupInfo> GetFixupURIInfo(const nsACString& aStringURI,
39 uint32_t aFixupFlags,
40 nsIInputStream** aPostData) {
41 nsCOMPtr<nsIURIFixupInfo> info;
42 if (XRE_IsContentProcess()) {
43 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
44 if (!contentChild) {
45 return nullptr;
46 }
47
48 RefPtr<nsIInputStream> postData;
49 RefPtr<nsIURI> fixedURI, preferredURI;
50 nsAutoString providerName;
51 nsAutoCString stringURI(aStringURI);
52 // TODO (Bug 1375244): This synchronous IPC messaging should be changed.
53 if (contentChild->SendGetFixupURIInfo(stringURI, aFixupFlags, &providerName,
54 &postData, &fixedURI,
55 &preferredURI)) {
56 if (preferredURI) {
57 info = do_CreateInstance("@mozilla.org/docshell/uri-fixup-info;1");
58 if (NS_WARN_IF(!info)) {
59 return nullptr;
60 }
61 info->SetKeywordProviderName(providerName);
62 if (aPostData) {
63 postData.forget(aPostData);
64 }
65 info->SetFixedURI(fixedURI);
66 info->SetPreferredURI(preferredURI);
67 }
68 }
69 } else {
70 sURIFixup->GetFixupURIInfo(aStringURI, aFixupFlags, aPostData,
71 getter_AddRefs(info));
72 }
73 return info.forget();
74 }
75 } // anonymous namespace
76
nsDocShellLoadState(nsIURI * aURI)77 nsDocShellLoadState::nsDocShellLoadState(nsIURI* aURI)
78 : mURI(aURI),
79 mResultPrincipalURIIsSome(false),
80 mKeepResultPrincipalURIIfSet(false),
81 mLoadReplace(false),
82 mInheritPrincipal(false),
83 mPrincipalIsExplicit(false),
84 mForceAllowDataURI(false),
85 mOriginalFrameSrc(false),
86 mIsFormSubmission(false),
87 mLoadType(LOAD_NORMAL),
88 mTarget(),
89 mSrcdocData(VoidString()),
90 mLoadFlags(0),
91 mFirstParty(false),
92 mHasValidUserGestureActivation(false),
93 mTypeHint(VoidCString()),
94 mFileName(VoidString()),
95 mIsHttpsOnlyModeUpgradeExempt(false),
96 mIsFromProcessingFrameAttributes(false),
97 mLoadIdentifier(0) {
98 MOZ_ASSERT(aURI, "Cannot create a LoadState with a null URI!");
99 }
100
nsDocShellLoadState(const DocShellLoadStateInit & aLoadState)101 nsDocShellLoadState::nsDocShellLoadState(
102 const DocShellLoadStateInit& aLoadState) {
103 MOZ_ASSERT(aLoadState.URI(), "Cannot create a LoadState with a null URI!");
104 mResultPrincipalURI = aLoadState.ResultPrincipalURI();
105 mResultPrincipalURIIsSome = aLoadState.ResultPrincipalURIIsSome();
106 mKeepResultPrincipalURIIfSet = aLoadState.KeepResultPrincipalURIIfSet();
107 mLoadReplace = aLoadState.LoadReplace();
108 mInheritPrincipal = aLoadState.InheritPrincipal();
109 mPrincipalIsExplicit = aLoadState.PrincipalIsExplicit();
110 mForceAllowDataURI = aLoadState.ForceAllowDataURI();
111 mOriginalFrameSrc = aLoadState.OriginalFrameSrc();
112 mIsFormSubmission = aLoadState.IsFormSubmission();
113 mLoadType = aLoadState.LoadType();
114 mTarget = aLoadState.Target();
115 mLoadFlags = aLoadState.LoadFlags();
116 mFirstParty = aLoadState.FirstParty();
117 mHasValidUserGestureActivation = aLoadState.HasValidUserGestureActivation();
118 mTypeHint = aLoadState.TypeHint();
119 mFileName = aLoadState.FileName();
120 mIsHttpsOnlyModeUpgradeExempt = aLoadState.IsHttpsOnlyModeUpgradeExempt();
121 mIsFromProcessingFrameAttributes =
122 aLoadState.IsFromProcessingFrameAttributes();
123 mReferrerInfo = aLoadState.ReferrerInfo();
124 mURI = aLoadState.URI();
125 mOriginalURI = aLoadState.OriginalURI();
126 mSourceBrowsingContext = aLoadState.SourceBrowsingContext();
127 mBaseURI = aLoadState.BaseURI();
128 mTriggeringPrincipal = aLoadState.TriggeringPrincipal();
129 mPrincipalToInherit = aLoadState.PrincipalToInherit();
130 mStoragePrincipalToInherit = aLoadState.StoragePrincipalToInherit();
131 mCsp = aLoadState.Csp();
132 mOriginalURIString = aLoadState.OriginalURIString();
133 mCancelContentJSEpoch = aLoadState.CancelContentJSEpoch();
134 mPostDataStream = aLoadState.PostDataStream();
135 mHeadersStream = aLoadState.HeadersStream();
136 mSrcdocData = aLoadState.SrcdocData();
137 mLoadIdentifier = aLoadState.LoadIdentifier();
138 }
139
nsDocShellLoadState(const nsDocShellLoadState & aOther)140 nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
141 : mReferrerInfo(aOther.mReferrerInfo),
142 mURI(aOther.mURI),
143 mOriginalURI(aOther.mOriginalURI),
144 mResultPrincipalURI(aOther.mResultPrincipalURI),
145 mResultPrincipalURIIsSome(aOther.mResultPrincipalURIIsSome),
146 mTriggeringPrincipal(aOther.mTriggeringPrincipal),
147 mCsp(aOther.mCsp),
148 mKeepResultPrincipalURIIfSet(aOther.mKeepResultPrincipalURIIfSet),
149 mLoadReplace(aOther.mLoadReplace),
150 mInheritPrincipal(aOther.mInheritPrincipal),
151 mPrincipalIsExplicit(aOther.mPrincipalIsExplicit),
152 mPrincipalToInherit(aOther.mPrincipalToInherit),
153 mStoragePrincipalToInherit(aOther.mStoragePrincipalToInherit),
154 mForceAllowDataURI(aOther.mForceAllowDataURI),
155 mOriginalFrameSrc(aOther.mOriginalFrameSrc),
156 mIsFormSubmission(aOther.mIsFormSubmission),
157 mLoadType(aOther.mLoadType),
158 mSHEntry(aOther.mSHEntry),
159 mTarget(aOther.mTarget),
160 mPostDataStream(aOther.mPostDataStream),
161 mHeadersStream(aOther.mHeadersStream),
162 mSrcdocData(aOther.mSrcdocData),
163 mSourceBrowsingContext(aOther.mSourceBrowsingContext),
164 mBaseURI(aOther.mBaseURI),
165 mLoadFlags(aOther.mLoadFlags),
166 mFirstParty(aOther.mFirstParty),
167 mHasValidUserGestureActivation(aOther.mHasValidUserGestureActivation),
168 mTypeHint(aOther.mTypeHint),
169 mFileName(aOther.mFileName),
170 mIsHttpsOnlyModeUpgradeExempt(aOther.mIsHttpsOnlyModeUpgradeExempt),
171 mIsFromProcessingFrameAttributes(aOther.mIsFromProcessingFrameAttributes),
172 mPendingRedirectedChannel(aOther.mPendingRedirectedChannel),
173 mOriginalURIString(aOther.mOriginalURIString),
174 mCancelContentJSEpoch(aOther.mCancelContentJSEpoch),
175 mLoadIdentifier(aOther.mLoadIdentifier) {}
176
~nsDocShellLoadState()177 nsDocShellLoadState::~nsDocShellLoadState() {}
178
CreateFromPendingChannel(nsIChannel * aPendingChannel,nsDocShellLoadState ** aResult)179 nsresult nsDocShellLoadState::CreateFromPendingChannel(
180 nsIChannel* aPendingChannel, nsDocShellLoadState** aResult) {
181 // Create the nsDocShellLoadState object with default state pulled from the
182 // passed-in channel.
183 nsCOMPtr<nsIURI> uri;
184 nsresult rv = aPendingChannel->GetURI(getter_AddRefs(uri));
185 if (NS_WARN_IF(NS_FAILED(rv))) {
186 return rv;
187 }
188
189 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(uri);
190 loadState->mPendingRedirectedChannel = aPendingChannel;
191
192 // Pull relevant state from the channel, and store it on the
193 // nsDocShellLoadState.
194 nsCOMPtr<nsIURI> originalUri;
195 rv = aPendingChannel->GetOriginalURI(getter_AddRefs(originalUri));
196 if (NS_WARN_IF(NS_FAILED(rv))) {
197 return rv;
198 }
199 loadState->SetOriginalURI(originalUri);
200
201 nsCOMPtr<nsILoadInfo> loadInfo = aPendingChannel->LoadInfo();
202 loadState->SetTriggeringPrincipal(loadInfo->TriggeringPrincipal());
203
204 // Return the newly created loadState.
205 loadState.forget(aResult);
206 return NS_OK;
207 }
208
CreateFromLoadURIOptions(BrowsingContext * aBrowsingContext,const nsAString & aURI,const LoadURIOptions & aLoadURIOptions,nsDocShellLoadState ** aResult)209 nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
210 BrowsingContext* aBrowsingContext, const nsAString& aURI,
211 const LoadURIOptions& aLoadURIOptions, nsDocShellLoadState** aResult) {
212 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
213
214 NS_ASSERTION(
215 (loadFlags & nsDocShell::INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,
216 "Unexpected flags");
217
218 nsCOMPtr<nsIURI> uri;
219 nsCOMPtr<nsIInputStream> postData(aLoadURIOptions.mPostData);
220 nsresult rv = NS_OK;
221
222 NS_ConvertUTF16toUTF8 uriString(aURI);
223 // Cleanup the empty spaces that might be on each end.
224 uriString.Trim(" ");
225 // Eliminate embedded newlines, which single-line text fields now allow:
226 uriString.StripCRLF();
227 NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
228
229 // Just create a URI and see what happens...
230 rv = NS_NewURI(getter_AddRefs(uri), uriString);
231 bool fixup = true;
232 if (NS_SUCCEEDED(rv) && uri &&
233 (uri->SchemeIs("about") || uri->SchemeIs("chrome"))) {
234 // Avoid third party fixup as a performance optimization.
235 loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
236 fixup = false;
237 } else if (!sURIFixup) {
238 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
239 if (uriFixup) {
240 sURIFixup = uriFixup;
241 ClearOnShutdown(&sURIFixup);
242 } else {
243 fixup = false;
244 }
245 }
246
247 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
248 if (fixup) {
249 uint32_t fixupFlags;
250 if (NS_FAILED(sURIFixup->WebNavigationFlagsToFixupFlags(
251 uriString, loadFlags, &fixupFlags))) {
252 return NS_ERROR_FAILURE;
253 }
254
255 // If we don't allow keyword lookups for this URL string, make sure to
256 // update loadFlags to indicate this as well.
257 if (!(fixupFlags & nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) {
258 loadFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
259 }
260 // Ensure URIFixup will use the right search engine in Private Browsing.
261 if (aBrowsingContext->UsePrivateBrowsing()) {
262 fixupFlags |= nsIURIFixup::FIXUP_FLAG_PRIVATE_CONTEXT;
263 }
264
265 nsCOMPtr<nsIInputStream> fixupStream;
266 fixupInfo =
267 GetFixupURIInfo(uriString, fixupFlags, getter_AddRefs(fixupStream));
268 if (fixupInfo) {
269 // We could fix the uri, clear NS_ERROR_MALFORMED_URI.
270 rv = NS_OK;
271 fixupInfo->GetPreferredURI(getter_AddRefs(uri));
272 fixupInfo->SetConsumer(aBrowsingContext);
273 }
274
275 if (fixupStream) {
276 // GetFixupURIInfo only returns a post data stream if it succeeded
277 // and changed the URI, in which case we should override the
278 // passed-in post data.
279 postData = fixupStream;
280 }
281
282 if (fixupInfo &&
283 loadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
284 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
285 if (serv) {
286 serv->NotifyObservers(fixupInfo, "keyword-uri-fixup",
287 PromiseFlatString(aURI).get());
288 }
289 }
290 }
291
292 if (rv == NS_ERROR_MALFORMED_URI) {
293 MOZ_ASSERT(!uri);
294 return rv;
295 }
296
297 if (NS_FAILED(rv) || !uri) {
298 return NS_ERROR_FAILURE;
299 }
300
301 uint64_t available;
302 if (postData) {
303 rv = postData->Available(&available);
304 NS_ENSURE_SUCCESS(rv, rv);
305 if (available == 0) {
306 return NS_ERROR_INVALID_ARG;
307 }
308 }
309
310 if (aLoadURIOptions.mHeaders) {
311 rv = aLoadURIOptions.mHeaders->Available(&available);
312 NS_ENSURE_SUCCESS(rv, rv);
313 if (available == 0) {
314 return NS_ERROR_INVALID_ARG;
315 }
316 }
317
318 bool forceAllowDataURI =
319 loadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
320
321 // Don't pass certain flags that aren't needed and end up confusing
322 // ConvertLoadTypeToDocShellInfoLoadType. We do need to ensure that they are
323 // passed to LoadURI though, since it uses them.
324 uint32_t extraFlags = (loadFlags & EXTRA_LOAD_FLAGS);
325 loadFlags &= ~EXTRA_LOAD_FLAGS;
326
327 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(uri);
328 loadState->SetReferrerInfo(aLoadURIOptions.mReferrerInfo);
329
330 /*
331 * If the user "Disables Protection on This Page", we have to make sure to
332 * remember the users decision when opening links in child tabs [Bug 906190]
333 */
334 if (loadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_MIXED_CONTENT) {
335 loadState->SetLoadType(
336 MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, loadFlags));
337 } else {
338 loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags));
339 }
340
341 loadState->SetLoadFlags(extraFlags);
342 loadState->SetFirstParty(true);
343 loadState->SetHasValidUserGestureActivation(
344 aLoadURIOptions.mHasValidUserGestureActivation);
345 loadState->SetPostDataStream(postData);
346 loadState->SetHeadersStream(aLoadURIOptions.mHeaders);
347 loadState->SetBaseURI(aLoadURIOptions.mBaseURI);
348 loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal);
349 loadState->SetCsp(aLoadURIOptions.mCsp);
350 loadState->SetForceAllowDataURI(forceAllowDataURI);
351 loadState->SetOriginalURIString(uriString);
352 if (aLoadURIOptions.mCancelContentJSEpoch) {
353 loadState->SetCancelContentJSEpoch(aLoadURIOptions.mCancelContentJSEpoch);
354 }
355 loadState->SetIsHttpsOnlyModeUpgradeExempt(
356 aLoadURIOptions.mIsHttpsOnlyModeUpgradeExempt);
357
358 if (fixupInfo) {
359 nsAutoString searchProvider, keyword;
360 fixupInfo->GetKeywordProviderName(searchProvider);
361 fixupInfo->GetKeywordAsSent(keyword);
362 nsDocShell::MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
363 }
364
365 loadState.forget(aResult);
366 return NS_OK;
367 }
368
GetReferrerInfo() const369 nsIReferrerInfo* nsDocShellLoadState::GetReferrerInfo() const {
370 return mReferrerInfo;
371 }
372
SetReferrerInfo(nsIReferrerInfo * aReferrerInfo)373 void nsDocShellLoadState::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
374 mReferrerInfo = aReferrerInfo;
375 }
376
URI() const377 nsIURI* nsDocShellLoadState::URI() const { return mURI; }
378
SetURI(nsIURI * aURI)379 void nsDocShellLoadState::SetURI(nsIURI* aURI) { mURI = aURI; }
380
OriginalURI() const381 nsIURI* nsDocShellLoadState::OriginalURI() const { return mOriginalURI; }
382
SetOriginalURI(nsIURI * aOriginalURI)383 void nsDocShellLoadState::SetOriginalURI(nsIURI* aOriginalURI) {
384 mOriginalURI = aOriginalURI;
385 }
386
ResultPrincipalURI() const387 nsIURI* nsDocShellLoadState::ResultPrincipalURI() const {
388 return mResultPrincipalURI;
389 }
390
SetResultPrincipalURI(nsIURI * aResultPrincipalURI)391 void nsDocShellLoadState::SetResultPrincipalURI(nsIURI* aResultPrincipalURI) {
392 mResultPrincipalURI = aResultPrincipalURI;
393 }
394
ResultPrincipalURIIsSome() const395 bool nsDocShellLoadState::ResultPrincipalURIIsSome() const {
396 return mResultPrincipalURIIsSome;
397 }
398
SetResultPrincipalURIIsSome(bool aIsSome)399 void nsDocShellLoadState::SetResultPrincipalURIIsSome(bool aIsSome) {
400 mResultPrincipalURIIsSome = aIsSome;
401 }
402
KeepResultPrincipalURIIfSet() const403 bool nsDocShellLoadState::KeepResultPrincipalURIIfSet() const {
404 return mKeepResultPrincipalURIIfSet;
405 }
406
SetKeepResultPrincipalURIIfSet(bool aKeep)407 void nsDocShellLoadState::SetKeepResultPrincipalURIIfSet(bool aKeep) {
408 mKeepResultPrincipalURIIfSet = aKeep;
409 }
410
LoadReplace() const411 bool nsDocShellLoadState::LoadReplace() const { return mLoadReplace; }
412
SetLoadReplace(bool aLoadReplace)413 void nsDocShellLoadState::SetLoadReplace(bool aLoadReplace) {
414 mLoadReplace = aLoadReplace;
415 }
416
TriggeringPrincipal() const417 nsIPrincipal* nsDocShellLoadState::TriggeringPrincipal() const {
418 return mTriggeringPrincipal;
419 }
420
SetTriggeringPrincipal(nsIPrincipal * aTriggeringPrincipal)421 void nsDocShellLoadState::SetTriggeringPrincipal(
422 nsIPrincipal* aTriggeringPrincipal) {
423 mTriggeringPrincipal = aTriggeringPrincipal;
424 }
425
PrincipalToInherit() const426 nsIPrincipal* nsDocShellLoadState::PrincipalToInherit() const {
427 return mPrincipalToInherit;
428 }
429
SetPrincipalToInherit(nsIPrincipal * aPrincipalToInherit)430 void nsDocShellLoadState::SetPrincipalToInherit(
431 nsIPrincipal* aPrincipalToInherit) {
432 mPrincipalToInherit = aPrincipalToInherit;
433 }
434
StoragePrincipalToInherit() const435 nsIPrincipal* nsDocShellLoadState::StoragePrincipalToInherit() const {
436 return mStoragePrincipalToInherit;
437 }
438
SetStoragePrincipalToInherit(nsIPrincipal * aStoragePrincipalToInherit)439 void nsDocShellLoadState::SetStoragePrincipalToInherit(
440 nsIPrincipal* aStoragePrincipalToInherit) {
441 mStoragePrincipalToInherit = aStoragePrincipalToInherit;
442 }
443
SetCsp(nsIContentSecurityPolicy * aCsp)444 void nsDocShellLoadState::SetCsp(nsIContentSecurityPolicy* aCsp) {
445 mCsp = aCsp;
446 }
447
Csp() const448 nsIContentSecurityPolicy* nsDocShellLoadState::Csp() const { return mCsp; }
449
InheritPrincipal() const450 bool nsDocShellLoadState::InheritPrincipal() const { return mInheritPrincipal; }
451
SetInheritPrincipal(bool aInheritPrincipal)452 void nsDocShellLoadState::SetInheritPrincipal(bool aInheritPrincipal) {
453 mInheritPrincipal = aInheritPrincipal;
454 }
455
PrincipalIsExplicit() const456 bool nsDocShellLoadState::PrincipalIsExplicit() const {
457 return mPrincipalIsExplicit;
458 }
459
SetPrincipalIsExplicit(bool aPrincipalIsExplicit)460 void nsDocShellLoadState::SetPrincipalIsExplicit(bool aPrincipalIsExplicit) {
461 mPrincipalIsExplicit = aPrincipalIsExplicit;
462 }
463
ForceAllowDataURI() const464 bool nsDocShellLoadState::ForceAllowDataURI() const {
465 return mForceAllowDataURI;
466 }
467
SetForceAllowDataURI(bool aForceAllowDataURI)468 void nsDocShellLoadState::SetForceAllowDataURI(bool aForceAllowDataURI) {
469 mForceAllowDataURI = aForceAllowDataURI;
470 }
471
OriginalFrameSrc() const472 bool nsDocShellLoadState::OriginalFrameSrc() const { return mOriginalFrameSrc; }
473
SetOriginalFrameSrc(bool aOriginalFrameSrc)474 void nsDocShellLoadState::SetOriginalFrameSrc(bool aOriginalFrameSrc) {
475 mOriginalFrameSrc = aOriginalFrameSrc;
476 }
477
IsFormSubmission() const478 bool nsDocShellLoadState::IsFormSubmission() const { return mIsFormSubmission; }
479
SetIsFormSubmission(bool aIsFormSubmission)480 void nsDocShellLoadState::SetIsFormSubmission(bool aIsFormSubmission) {
481 mIsFormSubmission = aIsFormSubmission;
482 }
483
LoadType() const484 uint32_t nsDocShellLoadState::LoadType() const { return mLoadType; }
485
SetLoadType(uint32_t aLoadType)486 void nsDocShellLoadState::SetLoadType(uint32_t aLoadType) {
487 mLoadType = aLoadType;
488 }
489
SHEntry() const490 nsISHEntry* nsDocShellLoadState::SHEntry() const { return mSHEntry; }
491
SetSHEntry(nsISHEntry * aSHEntry)492 void nsDocShellLoadState::SetSHEntry(nsISHEntry* aSHEntry) {
493 mSHEntry = aSHEntry;
494 }
495
SetSessionHistoryInfo(const mozilla::dom::SessionHistoryInfoAndId & aIdAndInfo)496 void nsDocShellLoadState::SetSessionHistoryInfo(
497 const mozilla::dom::SessionHistoryInfoAndId& aIdAndInfo) {
498 mSessionHistoryInfo = aIdAndInfo;
499 }
500
GetSessionHistoryID() const501 uint64_t nsDocShellLoadState::GetSessionHistoryID() const {
502 return mSessionHistoryInfo.mId;
503 }
504
505 const mozilla::dom::SessionHistoryInfo&
GetSessionHistoryInfo() const506 nsDocShellLoadState::GetSessionHistoryInfo() const {
507 return *mSessionHistoryInfo.mInfo;
508 }
509
Target() const510 const nsString& nsDocShellLoadState::Target() const { return mTarget; }
511
SetTarget(const nsAString & aTarget)512 void nsDocShellLoadState::SetTarget(const nsAString& aTarget) {
513 mTarget = aTarget;
514 }
515
PostDataStream() const516 nsIInputStream* nsDocShellLoadState::PostDataStream() const {
517 return mPostDataStream;
518 }
519
SetPostDataStream(nsIInputStream * aStream)520 void nsDocShellLoadState::SetPostDataStream(nsIInputStream* aStream) {
521 mPostDataStream = aStream;
522 }
523
HeadersStream() const524 nsIInputStream* nsDocShellLoadState::HeadersStream() const {
525 return mHeadersStream;
526 }
527
SetHeadersStream(nsIInputStream * aHeadersStream)528 void nsDocShellLoadState::SetHeadersStream(nsIInputStream* aHeadersStream) {
529 mHeadersStream = aHeadersStream;
530 }
531
SrcdocData() const532 const nsString& nsDocShellLoadState::SrcdocData() const { return mSrcdocData; }
533
SetSrcdocData(const nsAString & aSrcdocData)534 void nsDocShellLoadState::SetSrcdocData(const nsAString& aSrcdocData) {
535 mSrcdocData = aSrcdocData;
536 }
537
SetSourceBrowsingContext(BrowsingContext * aSourceBrowsingContext)538 void nsDocShellLoadState::SetSourceBrowsingContext(
539 BrowsingContext* aSourceBrowsingContext) {
540 mSourceBrowsingContext = aSourceBrowsingContext;
541 }
542
BaseURI() const543 nsIURI* nsDocShellLoadState::BaseURI() const { return mBaseURI; }
544
SetBaseURI(nsIURI * aBaseURI)545 void nsDocShellLoadState::SetBaseURI(nsIURI* aBaseURI) { mBaseURI = aBaseURI; }
546
GetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>> & aRPURI) const547 void nsDocShellLoadState::GetMaybeResultPrincipalURI(
548 mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const {
549 bool isSome = ResultPrincipalURIIsSome();
550 aRPURI.reset();
551
552 if (!isSome) {
553 return;
554 }
555
556 nsCOMPtr<nsIURI> uri = ResultPrincipalURI();
557 aRPURI.emplace(std::move(uri));
558 }
559
SetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>> const & aRPURI)560 void nsDocShellLoadState::SetMaybeResultPrincipalURI(
561 mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI) {
562 SetResultPrincipalURI(aRPURI.refOr(nullptr));
563 SetResultPrincipalURIIsSome(aRPURI.isSome());
564 }
565
LoadFlags() const566 uint32_t nsDocShellLoadState::LoadFlags() const { return mLoadFlags; }
567
SetLoadFlags(uint32_t aLoadFlags)568 void nsDocShellLoadState::SetLoadFlags(uint32_t aLoadFlags) {
569 mLoadFlags = aLoadFlags;
570 }
571
SetLoadFlag(uint32_t aFlag)572 void nsDocShellLoadState::SetLoadFlag(uint32_t aFlag) { mLoadFlags |= aFlag; }
573
UnsetLoadFlag(uint32_t aFlag)574 void nsDocShellLoadState::UnsetLoadFlag(uint32_t aFlag) {
575 mLoadFlags &= ~aFlag;
576 }
577
HasLoadFlags(uint32_t aFlags)578 bool nsDocShellLoadState::HasLoadFlags(uint32_t aFlags) {
579 return (mLoadFlags & aFlags) == aFlags;
580 }
581
FirstParty() const582 bool nsDocShellLoadState::FirstParty() const { return mFirstParty; }
583
SetFirstParty(bool aFirstParty)584 void nsDocShellLoadState::SetFirstParty(bool aFirstParty) {
585 mFirstParty = aFirstParty;
586 }
587
HasValidUserGestureActivation() const588 bool nsDocShellLoadState::HasValidUserGestureActivation() const {
589 return mHasValidUserGestureActivation;
590 }
591
SetHasValidUserGestureActivation(bool aHasValidUserGestureActivation)592 void nsDocShellLoadState::SetHasValidUserGestureActivation(
593 bool aHasValidUserGestureActivation) {
594 mHasValidUserGestureActivation = aHasValidUserGestureActivation;
595 }
596
TypeHint() const597 const nsCString& nsDocShellLoadState::TypeHint() const { return mTypeHint; }
598
SetTypeHint(const nsCString & aTypeHint)599 void nsDocShellLoadState::SetTypeHint(const nsCString& aTypeHint) {
600 mTypeHint = aTypeHint;
601 }
602
FileName() const603 const nsString& nsDocShellLoadState::FileName() const { return mFileName; }
604
SetFileName(const nsAString & aFileName)605 void nsDocShellLoadState::SetFileName(const nsAString& aFileName) {
606 MOZ_DIAGNOSTIC_ASSERT(aFileName.FindChar(char16_t(0)) == kNotFound,
607 "The filename should never contain null characters");
608 mFileName = aFileName;
609 }
610
IsHttpsOnlyModeUpgradeExempt() const611 bool nsDocShellLoadState::IsHttpsOnlyModeUpgradeExempt() const {
612 return mIsHttpsOnlyModeUpgradeExempt;
613 }
614
SetIsHttpsOnlyModeUpgradeExempt(bool aIsExempt)615 void nsDocShellLoadState::SetIsHttpsOnlyModeUpgradeExempt(bool aIsExempt) {
616 mIsHttpsOnlyModeUpgradeExempt = aIsExempt;
617 }
618
SetupInheritingPrincipal(BrowsingContext::Type aType,const mozilla::OriginAttributes & aOriginAttributes)619 nsresult nsDocShellLoadState::SetupInheritingPrincipal(
620 BrowsingContext::Type aType,
621 const mozilla::OriginAttributes& aOriginAttributes) {
622 // We need a principalToInherit.
623 //
624 // If principalIsExplicit is not set there are 4 possibilities:
625 // (1) If the system principal or an expanded principal was passed
626 // in and we're a typeContent docshell, inherit the principal
627 // from the current document instead.
628 // (2) In all other cases when the principal passed in is not null,
629 // use that principal.
630 // (3) If the caller has allowed inheriting from the current document,
631 // or if we're being called from system code (eg chrome JS or pure
632 // C++) then inheritPrincipal should be true and InternalLoad will get
633 // a principal from the current document. If none of these things are
634 // true, then
635 // (4) we don't pass a principal into the channel, and a principal will be
636 // created later from the channel's internal data.
637 //
638 // If principalIsExplicit *is* set, there are 4 possibilities
639 // (1) If the system principal or an expanded principal was passed in
640 // and we're a typeContent docshell, return an error.
641 // (2) In all other cases when the principal passed in is not null,
642 // use that principal.
643 // (3) If the caller has allowed inheriting from the current document,
644 // then inheritPrincipal should be true and InternalLoad will get
645 // a principal from the current document. If none of these things are
646 // true, then
647 // (4) we dont' pass a principal into the channel, and a principal will be
648 // created later from the channel's internal data.
649 mPrincipalToInherit = mTriggeringPrincipal;
650 if (mPrincipalToInherit && aType != BrowsingContext::Type::Chrome) {
651 if (mPrincipalToInherit->IsSystemPrincipal()) {
652 if (mPrincipalIsExplicit) {
653 return NS_ERROR_DOM_SECURITY_ERR;
654 }
655 mPrincipalToInherit = nullptr;
656 mInheritPrincipal = true;
657 } else if (nsContentUtils::IsExpandedPrincipal(mPrincipalToInherit)) {
658 if (mPrincipalIsExplicit) {
659 return NS_ERROR_DOM_SECURITY_ERR;
660 }
661 // Don't inherit from the current page. Just do the safe thing
662 // and pretend that we were loaded by a nullprincipal.
663 //
664 // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
665 // have origin attributes.
666 mPrincipalToInherit = NullPrincipal::CreateWithInheritedAttributes(
667 aOriginAttributes, false);
668 mInheritPrincipal = false;
669 }
670 }
671
672 if (!mPrincipalToInherit && !mInheritPrincipal && !mPrincipalIsExplicit) {
673 // See if there's system or chrome JS code running
674 mInheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
675 }
676
677 if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
678 mInheritPrincipal = false;
679 // If mFirstParty is true and the pref 'privacy.firstparty.isolate' is
680 // enabled, we will set firstPartyDomain on the origin attributes.
681 mPrincipalToInherit = NullPrincipal::CreateWithInheritedAttributes(
682 aOriginAttributes, mFirstParty);
683 }
684
685 return NS_OK;
686 }
687
SetupTriggeringPrincipal(const mozilla::OriginAttributes & aOriginAttributes)688 nsresult nsDocShellLoadState::SetupTriggeringPrincipal(
689 const mozilla::OriginAttributes& aOriginAttributes) {
690 // If the triggeringPrincipal is not set, we first try to create a principal
691 // from the referrer, since the referrer URI reflects the web origin that
692 // triggered the load. If there is no referrer URI, we fall back to using the
693 // SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
694 // and no referrer simulate a load that was triggered by the system. It's
695 // important to note that this block of code needs to appear *after* the block
696 // where we munge the principalToInherit, because otherwise we would never
697 // enter code blocks checking if the principalToInherit is null and we will
698 // end up with a wrong inheritPrincipal flag.
699 if (!mTriggeringPrincipal) {
700 if (mReferrerInfo) {
701 nsCOMPtr<nsIURI> referrer = mReferrerInfo->GetOriginalReferrer();
702 mTriggeringPrincipal =
703 BasePrincipal::CreateContentPrincipal(referrer, aOriginAttributes);
704
705 if (!mTriggeringPrincipal) {
706 return NS_ERROR_FAILURE;
707 }
708 } else {
709 mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
710 }
711 }
712 return NS_OK;
713 }
714
CalculateLoadURIFlags()715 void nsDocShellLoadState::CalculateLoadURIFlags() {
716 uint32_t oldLoadFlags = mLoadFlags;
717 mLoadFlags = 0;
718
719 if (mInheritPrincipal) {
720 MOZ_ASSERT(
721 !mPrincipalToInherit || !mPrincipalToInherit->IsSystemPrincipal(),
722 "Should not inherit SystemPrincipal");
723 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
724 }
725
726 if (mReferrerInfo && !mReferrerInfo->GetSendReferrer()) {
727 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
728 }
729 if (oldLoadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
730 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
731 }
732
733 if (oldLoadFlags & nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) {
734 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD;
735 }
736
737 if (oldLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CLASSIFIER) {
738 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
739 }
740
741 if (oldLoadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
742 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
743 }
744
745 if (oldLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE) {
746 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE;
747 }
748
749 if (!mSrcdocData.IsVoid()) {
750 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
751 }
752
753 if (mForceAllowDataURI) {
754 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
755 }
756
757 if (mOriginalFrameSrc) {
758 mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC;
759 }
760 }
761
CalculateChannelLoadFlags(BrowsingContext * aBrowsingContext,Maybe<bool> aUriModified,Maybe<bool> aIsXFOError)762 nsLoadFlags nsDocShellLoadState::CalculateChannelLoadFlags(
763 BrowsingContext* aBrowsingContext, Maybe<bool> aUriModified,
764 Maybe<bool> aIsXFOError) {
765 MOZ_ASSERT(aBrowsingContext);
766
767 nsLoadFlags loadFlags = aBrowsingContext->GetDefaultLoadFlags();
768
769 if (FirstParty()) {
770 // tag first party URL loads
771 loadFlags |= nsIChannel::LOAD_INITIAL_DOCUMENT_URI;
772 }
773
774 const uint32_t loadType = LoadType();
775
776 // These values aren't available for loads initiated in the Parent process.
777 MOZ_ASSERT_IF(loadType == LOAD_HISTORY, aUriModified.isSome());
778 MOZ_ASSERT_IF(loadType == LOAD_ERROR_PAGE, aIsXFOError.isSome());
779
780 if (loadType == LOAD_ERROR_PAGE) {
781 // Error pages are LOAD_BACKGROUND, unless it's an
782 // XFO error for which we want an error page to load
783 // but additionally want the onload() event to fire.
784 if (!*aIsXFOError) {
785 loadFlags |= nsIChannel::LOAD_BACKGROUND;
786 }
787 }
788
789 // Mark the channel as being a document URI and allow content sniffing...
790 loadFlags |=
791 nsIChannel::LOAD_DOCUMENT_URI | nsIChannel::LOAD_CALL_CONTENT_SNIFFERS;
792
793 if (nsDocShell::SandboxFlagsImplyCookies(
794 aBrowsingContext->GetSandboxFlags())) {
795 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
796 }
797
798 // Load attributes depend on load type...
799 switch (loadType) {
800 case LOAD_HISTORY: {
801 // Only send VALIDATE_NEVER if mLSHE's URI was never changed via
802 // push/replaceState (bug 669671).
803 if (!*aUriModified) {
804 loadFlags |= nsIRequest::VALIDATE_NEVER;
805 }
806 break;
807 }
808
809 case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
810 case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
811 loadFlags |=
812 nsIRequest::LOAD_BYPASS_CACHE | nsIRequest::LOAD_FRESH_CONNECTION;
813 [[fallthrough]];
814
815 case LOAD_RELOAD_NORMAL:
816 case LOAD_REFRESH:
817 loadFlags |= nsIRequest::VALIDATE_ALWAYS;
818 break;
819
820 case LOAD_NORMAL_BYPASS_CACHE:
821 case LOAD_NORMAL_BYPASS_PROXY:
822 case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
823 case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
824 case LOAD_RELOAD_BYPASS_CACHE:
825 case LOAD_RELOAD_BYPASS_PROXY:
826 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
827 case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
828 case LOAD_REPLACE_BYPASS_CACHE:
829 loadFlags |=
830 nsIRequest::LOAD_BYPASS_CACHE | nsIRequest::LOAD_FRESH_CONNECTION;
831 break;
832
833 case LOAD_NORMAL:
834 case LOAD_LINK:
835 // Set cache checking flags
836 switch (StaticPrefs::browser_cache_check_doc_frequency()) {
837 case 0:
838 loadFlags |= nsIRequest::VALIDATE_ONCE_PER_SESSION;
839 break;
840 case 1:
841 loadFlags |= nsIRequest::VALIDATE_ALWAYS;
842 break;
843 case 2:
844 loadFlags |= nsIRequest::VALIDATE_NEVER;
845 break;
846 }
847 break;
848 }
849
850 if (HasLoadFlags(nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER)) {
851 loadFlags |= nsIChannel::LOAD_BYPASS_URL_CLASSIFIER;
852 }
853
854 // If the user pressed shift-reload, then do not allow ServiceWorker
855 // interception to occur. See step 12.1 of the SW HandleFetch algorithm.
856 if (IsForceReloadType(loadType)) {
857 loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
858 }
859
860 return loadFlags;
861 }
862
Serialize()863 DocShellLoadStateInit nsDocShellLoadState::Serialize() {
864 DocShellLoadStateInit loadState;
865 loadState.ResultPrincipalURI() = mResultPrincipalURI;
866 loadState.ResultPrincipalURIIsSome() = mResultPrincipalURIIsSome;
867 loadState.KeepResultPrincipalURIIfSet() = mKeepResultPrincipalURIIfSet;
868 loadState.LoadReplace() = mLoadReplace;
869 loadState.InheritPrincipal() = mInheritPrincipal;
870 loadState.PrincipalIsExplicit() = mPrincipalIsExplicit;
871 loadState.ForceAllowDataURI() = mForceAllowDataURI;
872 loadState.OriginalFrameSrc() = mOriginalFrameSrc;
873 loadState.IsFormSubmission() = mIsFormSubmission;
874 loadState.LoadType() = mLoadType;
875 loadState.Target() = mTarget;
876 loadState.LoadFlags() = mLoadFlags;
877 loadState.FirstParty() = mFirstParty;
878 loadState.HasValidUserGestureActivation() = mHasValidUserGestureActivation;
879 loadState.TypeHint() = mTypeHint;
880 loadState.FileName() = mFileName;
881 loadState.IsHttpsOnlyModeUpgradeExempt() = mIsHttpsOnlyModeUpgradeExempt;
882 loadState.IsFromProcessingFrameAttributes() =
883 mIsFromProcessingFrameAttributes;
884 loadState.URI() = mURI;
885 loadState.OriginalURI() = mOriginalURI;
886 loadState.SourceBrowsingContext() = mSourceBrowsingContext;
887 loadState.BaseURI() = mBaseURI;
888 loadState.TriggeringPrincipal() = mTriggeringPrincipal;
889 loadState.PrincipalToInherit() = mPrincipalToInherit;
890 loadState.StoragePrincipalToInherit() = mStoragePrincipalToInherit;
891 loadState.Csp() = mCsp;
892 loadState.OriginalURIString() = mOriginalURIString;
893 loadState.CancelContentJSEpoch() = mCancelContentJSEpoch;
894 loadState.ReferrerInfo() = mReferrerInfo;
895 loadState.PostDataStream() = mPostDataStream;
896 loadState.HeadersStream() = mHeadersStream;
897 loadState.SrcdocData() = mSrcdocData;
898 loadState.ResultPrincipalURI() = mResultPrincipalURI;
899 loadState.LoadIdentifier() = mLoadIdentifier;
900 return loadState;
901 }
902