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 "nsIDocShellTreeItem.h"
10 #include "nsIScriptSecurityManager.h"
11 #include "nsIWebNavigation.h"
12 #include "nsIChildChannel.h"
14 #include "mozilla/OriginAttributes.h"
15 #include "mozilla/NullPrincipal.h"
17 #include "mozilla/dom/PContent.h"
19 nsDocShellLoadState::nsDocShellLoadState(nsIURI
* aURI
)
21 mResultPrincipalURIIsSome(false),
22 mKeepResultPrincipalURIIfSet(false),
24 mInheritPrincipal(false),
25 mPrincipalIsExplicit(false),
26 mForceAllowDataURI(false),
27 mOriginalFrameSrc(false),
29 mReferrerPolicy(mozilla::net::RP_Unset
),
30 mLoadType(LOAD_NORMAL
),
32 mSrcdocData(VoidString()),
35 mTypeHint(VoidCString()),
36 mFileName(VoidString()),
37 mIsFromProcessingFrameAttributes(false) {
38 MOZ_ASSERT(aURI
, "Cannot create a LoadState with a null URI!");
41 nsDocShellLoadState::nsDocShellLoadState(DocShellLoadStateInit
& aLoadState
) {
42 MOZ_ASSERT(aLoadState
.URI(), "Cannot create a LoadState with a null URI!");
43 mResultPrincipalURIIsSome
= aLoadState
.ResultPrincipalURIIsSome();
44 mKeepResultPrincipalURIIfSet
= aLoadState
.KeepResultPrincipalURIIfSet();
45 mLoadReplace
= aLoadState
.LoadReplace();
46 mInheritPrincipal
= aLoadState
.InheritPrincipal();
47 mPrincipalIsExplicit
= aLoadState
.PrincipalIsExplicit();
48 mForceAllowDataURI
= aLoadState
.ForceAllowDataURI();
49 mOriginalFrameSrc
= aLoadState
.OriginalFrameSrc();
50 mSendReferrer
= aLoadState
.SendReferrer();
51 mReferrerPolicy
= (mozilla::net::ReferrerPolicy
)aLoadState
.ReferrerPolicy();
52 mLoadType
= aLoadState
.LoadType();
53 mTarget
= aLoadState
.Target();
54 mLoadFlags
= aLoadState
.LoadFlags();
55 mFirstParty
= aLoadState
.FirstParty();
56 mTypeHint
= aLoadState
.TypeHint();
57 mFileName
= aLoadState
.FileName();
58 mIsFromProcessingFrameAttributes
=
59 aLoadState
.IsFromProcessingFrameAttributes();
60 mReferrer
= aLoadState
.Referrer();
61 mURI
= aLoadState
.URI();
62 mOriginalURI
= aLoadState
.OriginalURI();
63 mBaseURI
= aLoadState
.BaseURI();
64 mTriggeringPrincipal
= aLoadState
.TriggeringPrincipal();
65 mPrincipalToInherit
= aLoadState
.PrincipalToInherit();
68 nsDocShellLoadState::~nsDocShellLoadState() {}
70 nsresult
nsDocShellLoadState::CreateFromPendingChannel(
71 nsIChildChannel
* aPendingChannel
, nsDocShellLoadState
** aResult
) {
72 nsCOMPtr
<nsIChannel
> channel
= do_QueryInterface(aPendingChannel
);
73 if (NS_WARN_IF(!channel
)) {
74 return NS_ERROR_UNEXPECTED
;
77 // Create the nsDocShellLoadState object with default state pulled from the
80 nsresult rv
= channel
->GetURI(getter_AddRefs(uri
));
81 if (NS_WARN_IF(NS_FAILED(rv
))) {
85 RefPtr
<nsDocShellLoadState
> loadState
= new nsDocShellLoadState(uri
);
86 loadState
->mPendingRedirectedChannel
= aPendingChannel
;
88 // Pull relevant state from the channel, and store it on the
89 // nsDocShellLoadState.
90 nsCOMPtr
<nsIURI
> originalUri
;
91 rv
= channel
->GetOriginalURI(getter_AddRefs(originalUri
));
92 if (NS_WARN_IF(NS_FAILED(rv
))) {
95 loadState
->SetOriginalURI(originalUri
);
97 nsCOMPtr
<nsILoadInfo
> loadInfo
= channel
->GetLoadInfo();
98 if (NS_WARN_IF(!loadInfo
)) {
99 return NS_ERROR_FAILURE
;
101 loadState
->SetTriggeringPrincipal(loadInfo
->TriggeringPrincipal());
103 // Return the newly created loadState.
104 loadState
.forget(aResult
);
108 nsIURI
* nsDocShellLoadState::Referrer() const { return mReferrer
; }
110 void nsDocShellLoadState::SetReferrer(nsIURI
* aReferrer
) {
111 mReferrer
= aReferrer
;
114 nsIURI
* nsDocShellLoadState::URI() const { return mURI
; }
116 void nsDocShellLoadState::SetURI(nsIURI
* aURI
) { mURI
= aURI
; }
118 nsIURI
* nsDocShellLoadState::OriginalURI() const { return mOriginalURI
; }
120 void nsDocShellLoadState::SetOriginalURI(nsIURI
* aOriginalURI
) {
121 mOriginalURI
= aOriginalURI
;
124 nsIURI
* nsDocShellLoadState::ResultPrincipalURI() const {
125 return mResultPrincipalURI
;
128 void nsDocShellLoadState::SetResultPrincipalURI(nsIURI
* aResultPrincipalURI
) {
129 mResultPrincipalURI
= aResultPrincipalURI
;
132 bool nsDocShellLoadState::ResultPrincipalURIIsSome() const {
133 return mResultPrincipalURIIsSome
;
136 void nsDocShellLoadState::SetResultPrincipalURIIsSome(bool aIsSome
) {
137 mResultPrincipalURIIsSome
= aIsSome
;
140 bool nsDocShellLoadState::KeepResultPrincipalURIIfSet() const {
141 return mKeepResultPrincipalURIIfSet
;
144 void nsDocShellLoadState::SetKeepResultPrincipalURIIfSet(bool aKeep
) {
145 mKeepResultPrincipalURIIfSet
= aKeep
;
148 bool nsDocShellLoadState::LoadReplace() const { return mLoadReplace
; }
150 void nsDocShellLoadState::SetLoadReplace(bool aLoadReplace
) {
151 mLoadReplace
= aLoadReplace
;
154 nsIPrincipal
* nsDocShellLoadState::TriggeringPrincipal() const {
155 return mTriggeringPrincipal
;
158 void nsDocShellLoadState::SetTriggeringPrincipal(
159 nsIPrincipal
* aTriggeringPrincipal
) {
160 mTriggeringPrincipal
= aTriggeringPrincipal
;
163 nsIPrincipal
* nsDocShellLoadState::PrincipalToInherit() const {
164 return mPrincipalToInherit
;
167 void nsDocShellLoadState::SetPrincipalToInherit(
168 nsIPrincipal
* aPrincipalToInherit
) {
169 mPrincipalToInherit
= aPrincipalToInherit
;
172 bool nsDocShellLoadState::InheritPrincipal() const { return mInheritPrincipal
; }
174 void nsDocShellLoadState::SetInheritPrincipal(bool aInheritPrincipal
) {
175 mInheritPrincipal
= aInheritPrincipal
;
178 bool nsDocShellLoadState::PrincipalIsExplicit() const {
179 return mPrincipalIsExplicit
;
182 void nsDocShellLoadState::SetPrincipalIsExplicit(bool aPrincipalIsExplicit
) {
183 mPrincipalIsExplicit
= aPrincipalIsExplicit
;
186 bool nsDocShellLoadState::ForceAllowDataURI() const {
187 return mForceAllowDataURI
;
190 void nsDocShellLoadState::SetForceAllowDataURI(bool aForceAllowDataURI
) {
191 mForceAllowDataURI
= aForceAllowDataURI
;
194 bool nsDocShellLoadState::OriginalFrameSrc() const { return mOriginalFrameSrc
; }
196 void nsDocShellLoadState::SetOriginalFrameSrc(bool aOriginalFrameSrc
) {
197 mOriginalFrameSrc
= aOriginalFrameSrc
;
200 uint32_t nsDocShellLoadState::LoadType() const { return mLoadType
; }
202 void nsDocShellLoadState::SetLoadType(uint32_t aLoadType
) {
203 mLoadType
= aLoadType
;
206 nsISHEntry
* nsDocShellLoadState::SHEntry() const { return mSHEntry
; }
208 void nsDocShellLoadState::SetSHEntry(nsISHEntry
* aSHEntry
) {
212 const nsString
& nsDocShellLoadState::Target() const { return mTarget
; }
214 void nsDocShellLoadState::SetTarget(const nsAString
& aTarget
) {
218 nsIInputStream
* nsDocShellLoadState::PostDataStream() const {
219 return mPostDataStream
;
222 void nsDocShellLoadState::SetPostDataStream(nsIInputStream
* aStream
) {
223 mPostDataStream
= aStream
;
226 nsIInputStream
* nsDocShellLoadState::HeadersStream() const {
227 return mHeadersStream
;
230 void nsDocShellLoadState::SetHeadersStream(nsIInputStream
* aHeadersStream
) {
231 mHeadersStream
= aHeadersStream
;
234 bool nsDocShellLoadState::SendReferrer() const { return mSendReferrer
; }
236 void nsDocShellLoadState::SetSendReferrer(bool aSendReferrer
) {
237 mSendReferrer
= aSendReferrer
;
240 mozilla::net::ReferrerPolicy
nsDocShellLoadState::ReferrerPolicy() const {
241 return mReferrerPolicy
;
244 void nsDocShellLoadState::SetReferrerPolicy(
245 mozilla::net::ReferrerPolicy aReferrerPolicy
) {
246 mReferrerPolicy
= aReferrerPolicy
;
249 const nsString
& nsDocShellLoadState::SrcdocData() const { return mSrcdocData
; }
251 void nsDocShellLoadState::SetSrcdocData(const nsAString
& aSrcdocData
) {
252 mSrcdocData
= aSrcdocData
;
255 nsIDocShell
* nsDocShellLoadState::SourceDocShell() const {
256 return mSourceDocShell
;
259 void nsDocShellLoadState::SetSourceDocShell(nsIDocShell
* aSourceDocShell
) {
260 mSourceDocShell
= aSourceDocShell
;
263 nsIURI
* nsDocShellLoadState::BaseURI() const { return mBaseURI
; }
265 void nsDocShellLoadState::SetBaseURI(nsIURI
* aBaseURI
) { mBaseURI
= aBaseURI
; }
267 void nsDocShellLoadState::GetMaybeResultPrincipalURI(
268 mozilla::Maybe
<nsCOMPtr
<nsIURI
>>& aRPURI
) const {
269 bool isSome
= ResultPrincipalURIIsSome();
276 nsCOMPtr
<nsIURI
> uri
= ResultPrincipalURI();
277 aRPURI
.emplace(std::move(uri
));
280 void nsDocShellLoadState::SetMaybeResultPrincipalURI(
281 mozilla::Maybe
<nsCOMPtr
<nsIURI
>> const& aRPURI
) {
282 SetResultPrincipalURI(aRPURI
.refOr(nullptr));
283 SetResultPrincipalURIIsSome(aRPURI
.isSome());
286 uint32_t nsDocShellLoadState::LoadFlags() const { return mLoadFlags
; }
288 void nsDocShellLoadState::SetLoadFlags(uint32_t aLoadFlags
) {
289 mLoadFlags
= aLoadFlags
;
292 void nsDocShellLoadState::SetLoadFlag(uint32_t aFlag
) { mLoadFlags
|= aFlag
; }
294 void nsDocShellLoadState::UnsetLoadFlag(uint32_t aFlag
) {
295 mLoadFlags
&= ~aFlag
;
298 bool nsDocShellLoadState::HasLoadFlags(uint32_t aFlags
) {
299 return (mLoadFlags
& aFlags
) == aFlags
;
302 bool nsDocShellLoadState::FirstParty() const { return mFirstParty
; }
304 void nsDocShellLoadState::SetFirstParty(bool aFirstParty
) {
305 mFirstParty
= aFirstParty
;
308 const nsCString
& nsDocShellLoadState::TypeHint() const { return mTypeHint
; }
310 void nsDocShellLoadState::SetTypeHint(const nsCString
& aTypeHint
) {
311 mTypeHint
= aTypeHint
;
314 const nsString
& nsDocShellLoadState::FileName() const { return mFileName
; }
316 void nsDocShellLoadState::SetFileName(const nsAString
& aFileName
) {
317 mFileName
= aFileName
;
320 nsresult
nsDocShellLoadState::SetupInheritingPrincipal(
321 uint32_t aItemType
, const mozilla::OriginAttributes
& aOriginAttributes
) {
322 // We need a principalToInherit.
324 // If principalIsExplicit is not set there are 4 possibilities:
325 // (1) If the system principal or an expanded principal was passed
326 // in and we're a typeContent docshell, inherit the principal
327 // from the current document instead.
328 // (2) In all other cases when the principal passed in is not null,
329 // use that principal.
330 // (3) If the caller has allowed inheriting from the current document,
331 // or if we're being called from system code (eg chrome JS or pure
332 // C++) then inheritPrincipal should be true and InternalLoad will get
333 // a principal from the current document. If none of these things are
335 // (4) we don't pass a principal into the channel, and a principal will be
336 // created later from the channel's internal data.
338 // If principalIsExplicit *is* set, there are 4 possibilities
339 // (1) If the system principal or an expanded principal was passed in
340 // and we're a typeContent docshell, return an error.
341 // (2) In all other cases when the principal passed in is not null,
342 // use that principal.
343 // (3) If the caller has allowed inheriting from the current document,
344 // then inheritPrincipal should be true and InternalLoad will get
345 // a principal from the current document. If none of these things are
347 // (4) we dont' pass a principal into the channel, and a principal will be
348 // created later from the channel's internal data.
349 mPrincipalToInherit
= mTriggeringPrincipal
;
350 if (mPrincipalToInherit
&& aItemType
!= nsIDocShellTreeItem::typeChrome
) {
351 if (nsContentUtils::IsSystemPrincipal(mPrincipalToInherit
)) {
352 if (mPrincipalIsExplicit
) {
353 return NS_ERROR_DOM_SECURITY_ERR
;
355 mPrincipalToInherit
= nullptr;
356 mInheritPrincipal
= true;
357 } else if (nsContentUtils::IsExpandedPrincipal(mPrincipalToInherit
)) {
358 if (mPrincipalIsExplicit
) {
359 return NS_ERROR_DOM_SECURITY_ERR
;
361 // Don't inherit from the current page. Just do the safe thing
362 // and pretend that we were loaded by a nullprincipal.
364 // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
365 // have origin attributes.
366 mPrincipalToInherit
= NullPrincipal::CreateWithInheritedAttributes(
367 aOriginAttributes
, false);
368 mInheritPrincipal
= false;
372 if (!mPrincipalToInherit
&& !mInheritPrincipal
&& !mPrincipalIsExplicit
) {
373 // See if there's system or chrome JS code running
374 mInheritPrincipal
= nsContentUtils::LegacyIsCallerChromeOrNativeCode();
377 if (mLoadFlags
& nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL
) {
378 mInheritPrincipal
= false;
379 // If mFirstParty is true and the pref 'privacy.firstparty.isolate' is
380 // enabled, we will set firstPartyDomain on the origin attributes.
381 mPrincipalToInherit
= NullPrincipal::CreateWithInheritedAttributes(
382 aOriginAttributes
, mFirstParty
);
388 nsresult
nsDocShellLoadState::SetupTriggeringPrincipal(
389 const mozilla::OriginAttributes
& aOriginAttributes
) {
390 // If the triggeringPrincipal is not set, we first try to create a principal
391 // from the referrer, since the referrer URI reflects the web origin that
392 // triggered the load. If there is no referrer URI, we fall back to using the
393 // SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
394 // and no referrer simulate a load that was triggered by the system. It's
395 // important to note that this block of code needs to appear *after* the block
396 // where we munge the principalToInherit, because otherwise we would never
397 // enter code blocks checking if the principalToInherit is null and we will
398 // end up with a wrong inheritPrincipal flag.
399 if (!mTriggeringPrincipal
) {
401 mTriggeringPrincipal
=
402 BasePrincipal::CreateCodebasePrincipal(mReferrer
, aOriginAttributes
);
404 if (!mTriggeringPrincipal
) {
405 return NS_ERROR_FAILURE
;
408 mTriggeringPrincipal
= nsContentUtils::GetSystemPrincipal();
414 void nsDocShellLoadState::CalculateLoadURIFlags() {
415 uint32_t oldLoadFlags
= mLoadFlags
;
418 if (mInheritPrincipal
) {
419 MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(mPrincipalToInherit
),
420 "Should not inherit SystemPrincipal");
421 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL
;
424 if (!mSendReferrer
) {
425 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
;
428 if (oldLoadFlags
& nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP
) {
429 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP
;
432 if (oldLoadFlags
& nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD
) {
433 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD
;
436 if (oldLoadFlags
& nsIWebNavigation::LOAD_FLAGS_BYPASS_CLASSIFIER
) {
437 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER
;
440 if (oldLoadFlags
& nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_COOKIES
) {
441 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES
;
444 if (!mSrcdocData
.IsVoid()) {
445 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC
;
448 if (mForceAllowDataURI
) {
449 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI
;
452 if (mOriginalFrameSrc
) {
453 mLoadFlags
|= nsDocShell::INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC
;
457 DocShellLoadStateInit
nsDocShellLoadState::Serialize() {
458 DocShellLoadStateInit loadState
;
459 loadState
.ResultPrincipalURIIsSome() = mResultPrincipalURIIsSome
;
460 loadState
.KeepResultPrincipalURIIfSet() = mKeepResultPrincipalURIIfSet
;
461 loadState
.LoadReplace() = mLoadReplace
;
462 loadState
.InheritPrincipal() = mInheritPrincipal
;
463 loadState
.PrincipalIsExplicit() = mPrincipalIsExplicit
;
464 loadState
.ForceAllowDataURI() = mForceAllowDataURI
;
465 loadState
.OriginalFrameSrc() = mOriginalFrameSrc
;
466 loadState
.SendReferrer() = mSendReferrer
;
467 loadState
.ReferrerPolicy() = mReferrerPolicy
;
468 loadState
.LoadType() = mLoadType
;
469 loadState
.Target() = mTarget
;
470 loadState
.LoadFlags() = mLoadFlags
;
471 loadState
.FirstParty() = mFirstParty
;
472 loadState
.TypeHint() = mTypeHint
;
473 loadState
.FileName() = mFileName
;
474 loadState
.IsFromProcessingFrameAttributes() =
475 mIsFromProcessingFrameAttributes
;
476 loadState
.Referrer() = mReferrer
;
477 loadState
.URI() = mURI
;
478 loadState
.OriginalURI() = mOriginalURI
;
479 loadState
.BaseURI() = mBaseURI
;
480 loadState
.TriggeringPrincipal() = mTriggeringPrincipal
;
481 loadState
.PrincipalToInherit() = mPrincipalToInherit
;