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