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 #ifndef nsDocShellLoadState_h__
8 #define nsDocShellLoadState_h__
9 
10 #include "mozilla/dom/BrowsingContext.h"
11 #include "mozilla/dom/SessionHistoryEntry.h"
12 
13 // Helper Classes
14 #include "mozilla/Maybe.h"
15 #include "nsCOMPtr.h"
16 #include "nsString.h"
17 #include "nsDocShellLoadTypes.h"
18 #include "nsTArrayForwardDeclare.h"
19 
20 class nsIContentSecurityPolicy;
21 class nsIInputStream;
22 class nsISHEntry;
23 class nsIURI;
24 class nsIDocShell;
25 class nsIChannel;
26 class nsIReferrerInfo;
27 class OriginAttibutes;
28 namespace mozilla {
29 template <typename, class>
30 class UniquePtr;
31 namespace dom {
32 class DocShellLoadStateInit;
33 }  // namespace dom
34 }  // namespace mozilla
35 
36 /**
37  * nsDocShellLoadState contains setup information used in a nsIDocShell::loadURI
38  * call.
39  */
40 class nsDocShellLoadState final {
41   using BrowsingContext = mozilla::dom::BrowsingContext;
42   template <typename T>
43   using MaybeDiscarded = mozilla::dom::MaybeDiscarded<T>;
44 
45  public:
46   NS_INLINE_DECL_REFCOUNTING(nsDocShellLoadState);
47 
48   explicit nsDocShellLoadState(nsIURI* aURI);
49   explicit nsDocShellLoadState(
50       const mozilla::dom::DocShellLoadStateInit& aLoadState);
51   explicit nsDocShellLoadState(const nsDocShellLoadState& aOther);
52   nsDocShellLoadState(nsIURI* aURI, uint64_t aLoadIdentifier);
53 
54   static nsresult CreateFromPendingChannel(nsIChannel* aPendingChannel,
55                                            uint64_t aLoadIdentifier,
56                                            uint64_t aRegistarId,
57                                            nsDocShellLoadState** aResult);
58 
59   static nsresult CreateFromLoadURIOptions(
60       BrowsingContext* aBrowsingContext, const nsAString& aURI,
61       const mozilla::dom::LoadURIOptions& aLoadURIOptions,
62       nsDocShellLoadState** aResult);
63 
64   // Getters and Setters
65 
66   nsIReferrerInfo* GetReferrerInfo() const;
67 
68   void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo);
69 
70   nsIURI* URI() const;
71 
72   void SetURI(nsIURI* aURI);
73 
74   nsIURI* OriginalURI() const;
75 
76   void SetOriginalURI(nsIURI* aOriginalURI);
77 
78   nsIURI* ResultPrincipalURI() const;
79 
80   void SetResultPrincipalURI(nsIURI* aResultPrincipalURI);
81 
82   bool ResultPrincipalURIIsSome() const;
83 
84   void SetResultPrincipalURIIsSome(bool aIsSome);
85 
86   bool KeepResultPrincipalURIIfSet() const;
87 
88   void SetKeepResultPrincipalURIIfSet(bool aKeep);
89 
90   nsIPrincipal* PrincipalToInherit() const;
91 
92   void SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit);
93 
94   nsIPrincipal* PartitionedPrincipalToInherit() const;
95 
96   void SetPartitionedPrincipalToInherit(
97       nsIPrincipal* aPartitionedPrincipalToInherit);
98 
99   bool LoadReplace() const;
100 
101   void SetLoadReplace(bool aLoadReplace);
102 
103   nsIPrincipal* TriggeringPrincipal() const;
104 
105   void SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal);
106 
107   uint32_t TriggeringSandboxFlags() const;
108 
109   void SetTriggeringSandboxFlags(uint32_t aTriggeringSandboxFlags);
110 
111   nsIContentSecurityPolicy* Csp() const;
112 
113   void SetCsp(nsIContentSecurityPolicy* aCsp);
114 
115   bool InheritPrincipal() const;
116 
117   void SetInheritPrincipal(bool aInheritPrincipal);
118 
119   bool PrincipalIsExplicit() const;
120 
121   void SetPrincipalIsExplicit(bool aPrincipalIsExplicit);
122 
123   // If true, "beforeunload" event listeners were notified by the creater of the
124   // LoadState and given the chance to abort the navigation, and should not be
125   // notified again.
126   bool NotifiedBeforeUnloadListeners() const;
127 
128   void SetNotifiedBeforeUnloadListeners(bool aNotifiedBeforeUnloadListeners);
129 
130   bool ForceAllowDataURI() const;
131 
132   void SetForceAllowDataURI(bool aForceAllowDataURI);
133 
134   bool IsExemptFromHTTPSOnlyMode() const;
135 
136   void SetIsExemptFromHTTPSOnlyMode(bool aIsExemptFromHTTPSOnlyMode);
137 
138   bool OriginalFrameSrc() const;
139 
140   void SetOriginalFrameSrc(bool aOriginalFrameSrc);
141 
142   bool IsFormSubmission() const;
143 
144   void SetIsFormSubmission(bool aIsFormSubmission);
145 
146   uint32_t LoadType() const;
147 
148   void SetLoadType(uint32_t aLoadType);
149 
150   nsISHEntry* SHEntry() const;
151 
152   void SetSHEntry(nsISHEntry* aSHEntry);
153 
154   const mozilla::dom::LoadingSessionHistoryInfo* GetLoadingSessionHistoryInfo()
155       const;
156 
157   // Copies aLoadingInfo and stores the copy in this nsDocShellLoadState.
158   void SetLoadingSessionHistoryInfo(
159       const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo);
160 
161   // Stores aLoadingInfo in this nsDocShellLoadState.
162   void SetLoadingSessionHistoryInfo(
163       mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> aLoadingInfo);
164 
165   bool LoadIsFromSessionHistory() const;
166 
167   const nsString& Target() const;
168 
169   void SetTarget(const nsAString& aTarget);
170 
171   nsIInputStream* PostDataStream() const;
172 
173   void SetPostDataStream(nsIInputStream* aStream);
174 
175   nsIInputStream* HeadersStream() const;
176 
177   void SetHeadersStream(nsIInputStream* aHeadersStream);
178 
179   bool IsSrcdocLoad() const;
180 
181   const nsString& SrcdocData() const;
182 
183   void SetSrcdocData(const nsAString& aSrcdocData);
184 
SourceBrowsingContext()185   const MaybeDiscarded<BrowsingContext>& SourceBrowsingContext() const {
186     return mSourceBrowsingContext;
187   }
188 
189   void SetSourceBrowsingContext(BrowsingContext*);
190 
SetAllowFocusMove(bool aAllow)191   void SetAllowFocusMove(bool aAllow) { mAllowFocusMove = aAllow; }
192 
AllowFocusMove()193   bool AllowFocusMove() const { return mAllowFocusMove; }
194 
TargetBrowsingContext()195   const MaybeDiscarded<BrowsingContext>& TargetBrowsingContext() const {
196     return mTargetBrowsingContext;
197   }
198 
199   void SetTargetBrowsingContext(BrowsingContext* aTargetBrowsingContext);
200 
201   nsIURI* BaseURI() const;
202 
203   void SetBaseURI(nsIURI* aBaseURI);
204 
205   // Helper function allowing convenient work with mozilla::Maybe in C++, hiding
206   // resultPrincipalURI and resultPrincipalURIIsSome attributes from the
207   // consumer.
208   void GetMaybeResultPrincipalURI(
209       mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const;
210 
211   void SetMaybeResultPrincipalURI(
212       mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI);
213 
214   uint32_t LoadFlags() const;
215 
216   void SetLoadFlags(uint32_t aFlags);
217 
218   void SetLoadFlag(uint32_t aFlag);
219 
220   void UnsetLoadFlag(uint32_t aFlag);
221 
222   bool HasLoadFlags(uint32_t aFlag);
223 
224   uint32_t InternalLoadFlags() const;
225 
226   void SetInternalLoadFlags(uint32_t aFlags);
227 
228   void SetInternalLoadFlag(uint32_t aFlag);
229 
230   void UnsetInternalLoadFlag(uint32_t aFlag);
231 
232   bool HasInternalLoadFlags(uint32_t aFlag);
233 
234   bool FirstParty() const;
235 
236   void SetFirstParty(bool aFirstParty);
237 
238   bool HasValidUserGestureActivation() const;
239 
240   void SetHasValidUserGestureActivation(bool HasValidUserGestureActivation);
241 
242   const nsCString& TypeHint() const;
243 
244   void SetTypeHint(const nsCString& aTypeHint);
245 
246   const nsString& FileName() const;
247 
248   void SetFileName(const nsAString& aFileName);
249 
250   nsIURI* GetUnstrippedURI() const;
251 
252   // Give the type of DocShell we're loading into (chrome/content/etc) and
253   // origin attributes for the URI we're loading, figure out if we should
254   // inherit our principal from the document the load was requested from, or
255   // else if the principal should be set up later in the process (after loads).
256   // See comments in function for more info on principal selection algorithm
257   nsresult SetupInheritingPrincipal(
258       mozilla::dom::BrowsingContext::Type aType,
259       const mozilla::OriginAttributes& aOriginAttributes);
260 
261   // If no triggering principal exists at the moment, create one using referrer
262   // information and origin attributes.
263   nsresult SetupTriggeringPrincipal(
264       const mozilla::OriginAttributes& aOriginAttributes);
265 
SetIsFromProcessingFrameAttributes()266   void SetIsFromProcessingFrameAttributes() {
267     mIsFromProcessingFrameAttributes = true;
268   }
GetIsFromProcessingFrameAttributes()269   bool GetIsFromProcessingFrameAttributes() const {
270     return mIsFromProcessingFrameAttributes;
271   }
272 
GetPendingRedirectedChannel()273   nsIChannel* GetPendingRedirectedChannel() {
274     return mPendingRedirectedChannel;
275   }
276 
GetPendingRedirectChannelRegistrarId()277   uint64_t GetPendingRedirectChannelRegistrarId() const {
278     return mChannelRegistrarId;
279   }
280 
SetOriginalURIString(const nsCString & aOriginalURI)281   void SetOriginalURIString(const nsCString& aOriginalURI) {
282     mOriginalURIString.emplace(aOriginalURI);
283   }
GetOriginalURIString()284   const mozilla::Maybe<nsCString>& GetOriginalURIString() const {
285     return mOriginalURIString;
286   }
287 
SetCancelContentJSEpoch(int32_t aCancelEpoch)288   void SetCancelContentJSEpoch(int32_t aCancelEpoch) {
289     mCancelContentJSEpoch.emplace(aCancelEpoch);
290   }
GetCancelContentJSEpoch()291   const mozilla::Maybe<int32_t>& GetCancelContentJSEpoch() const {
292     return mCancelContentJSEpoch;
293   }
294 
GetLoadIdentifier()295   uint64_t GetLoadIdentifier() const { return mLoadIdentifier; }
296 
SetChannelInitialized(bool aInitilized)297   void SetChannelInitialized(bool aInitilized) {
298     mChannelInitialized = aInitilized;
299   }
300 
GetChannelInitialized()301   bool GetChannelInitialized() const { return mChannelInitialized; }
302 
SetIsMetaRefresh(bool aMetaRefresh)303   void SetIsMetaRefresh(bool aMetaRefresh) { mIsMetaRefresh = aMetaRefresh; }
304 
IsMetaRefresh()305   bool IsMetaRefresh() const { return mIsMetaRefresh; }
306 
GetRemoteTypeOverride()307   const mozilla::Maybe<nsCString>& GetRemoteTypeOverride() const {
308     return mRemoteTypeOverride;
309   }
310 
SetRemoteTypeOverride(const nsCString & aRemoteTypeOverride)311   void SetRemoteTypeOverride(const nsCString& aRemoteTypeOverride) {
312     mRemoteTypeOverride = mozilla::Some(aRemoteTypeOverride);
313   }
314 
315   // When loading a document through nsDocShell::LoadURI(), a special set of
316   // flags needs to be set based on other values in nsDocShellLoadState. This
317   // function calculates those flags, before the LoadState is passed to
318   // nsDocShell::InternalLoad.
319   void CalculateLoadURIFlags();
320 
321   // Compute the load flags to be used by creating channel.  aUriModified and
322   // aIsXFOError are expected to be Nothing when called from Parent process.
323   nsLoadFlags CalculateChannelLoadFlags(
324       mozilla::dom::BrowsingContext* aBrowsingContext,
325       mozilla::Maybe<bool> aUriModified, mozilla::Maybe<bool> aIsXFOError);
326 
327   mozilla::dom::DocShellLoadStateInit Serialize();
328 
329   void SetLoadIsFromSessionHistory(int32_t aOffset, bool aLoadingCurrentEntry);
330   void ClearLoadIsFromSessionHistory();
331 
332   void MaybeStripTrackerQueryStrings(mozilla::dom::BrowsingContext* aContext,
333                                      nsIURI* aCurrentUnstrippedURI = nullptr);
334 
335  protected:
336   // Destructor can't be defaulted or inlined, as header doesn't have all type
337   // includes it needs to do so.
338   ~nsDocShellLoadState();
339 
340  protected:
341   // This is the referrer for the load.
342   nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
343 
344   // The URI we are navigating to. Will not be null once set.
345   nsCOMPtr<nsIURI> mURI;
346 
347   // The URI to set as the originalURI on the channel that does the load. If
348   // null, aURI will be set as the originalURI.
349   nsCOMPtr<nsIURI> mOriginalURI;
350 
351   // The URI to be set to loadInfo.resultPrincipalURI
352   // - When Nothing, there will be no change
353   // - When Some, the principal URI will overwrite even
354   //   with a null value.
355   //
356   // Valid only if mResultPrincipalURIIsSome is true (has the same meaning as
357   // isSome() on mozilla::Maybe.)
358   nsCOMPtr<nsIURI> mResultPrincipalURI;
359   bool mResultPrincipalURIIsSome;
360 
361   // The principal of the load, that is, the entity responsible for causing the
362   // load to occur. In most cases the referrer and the triggeringPrincipal's URI
363   // will be identical.
364   //
365   // Please note that this is the principal that is used for security checks. If
366   // the argument aURI is provided by the web, then please do not pass a
367   // SystemPrincipal as the triggeringPrincipal.
368   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
369 
370   // The SandboxFlags of the load, that are, the SandboxFlags of the entity
371   // responsible for causing the load to occur. Most likely this are the
372   // SandboxFlags of the document that started the load.
373   uint32_t mTriggeringSandboxFlags;
374 
375   // The CSP of the load, that is, the CSP of the entity responsible for causing
376   // the load to occur. Most likely this is the CSP of the document that started
377   // the load. In case the entity starting the load did not use a CSP, then mCsp
378   // can be null. Please note that this is also the CSP that will be applied to
379   // the load in case the load encounters a server side redirect.
380   nsCOMPtr<nsIContentSecurityPolicy> mCsp;
381 
382   // If a refresh is caused by http-equiv="refresh" we want to set
383   // aResultPrincipalURI, but we do not want to overwrite the channel's
384   // ResultPrincipalURI, if it has already been set on the channel by a protocol
385   // handler.
386   bool mKeepResultPrincipalURIIfSet;
387 
388   // If set LOAD_REPLACE flag will be set on the channel. If aOriginalURI is
389   // null, this argument is ignored.
390   bool mLoadReplace;
391 
392   // If this attribute is true and no triggeringPrincipal is specified,
393   // copy the principal from the referring document.
394   bool mInheritPrincipal;
395 
396   // If this attribute is true only ever use the principal specified
397   // by the triggeringPrincipal and inheritPrincipal attributes.
398   // If there are security reasons for why this is unsafe, such
399   // as trying to use a systemprincipal as the triggeringPrincipal
400   // for a content docshell the load fails.
401   bool mPrincipalIsExplicit;
402 
403   bool mNotifiedBeforeUnloadListeners;
404 
405   // Principal we're inheriting. If null, this means the principal should be
406   // inherited from the current document. If set to NullPrincipal, the channel
407   // will fill in principal information later in the load. See internal comments
408   // of SetupInheritingPrincipal for more info.
409   //
410   // When passed to InternalLoad, If this argument is null then
411   // principalToInherit is computed differently. See nsDocShell::InternalLoad
412   // for more comments.
413 
414   nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
415 
416   nsCOMPtr<nsIPrincipal> mPartitionedPrincipalToInherit;
417 
418   // If this attribute is true, then a top-level navigation
419   // to a data URI will be allowed.
420   bool mForceAllowDataURI;
421 
422   // If this attribute is true, then the top-level navigaion
423   // will be exempt from HTTPS-Only-Mode upgrades.
424   bool mIsExemptFromHTTPSOnlyMode;
425 
426   // If this attribute is true, this load corresponds to a frame
427   // element loading its original src (or srcdoc) attribute.
428   bool mOriginalFrameSrc;
429 
430   // If this attribute is true, then the load was initiated by a
431   // form submission. This is important to know for the CSP directive
432   // navigate-to.
433   bool mIsFormSubmission;
434 
435   // Contains a load type as specified by the nsDocShellLoadTypes::load*
436   // constants
437   uint32_t mLoadType;
438 
439   // Active Session History entry (if loading from SH)
440   nsCOMPtr<nsISHEntry> mSHEntry;
441 
442   // Loading session history info for the load
443   mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo>
444       mLoadingSessionHistoryInfo;
445 
446   // Target for load, like _content, _blank etc.
447   nsString mTarget;
448 
449   // When set, this is the Target Browsing Context for the navigation
450   // after retargeting.
451   MaybeDiscarded<BrowsingContext> mTargetBrowsingContext;
452 
453   // Post data stream (if POSTing)
454   nsCOMPtr<nsIInputStream> mPostDataStream;
455 
456   // Additional Headers
457   nsCOMPtr<nsIInputStream> mHeadersStream;
458 
459   // When set, the load will be interpreted as a srcdoc load, where contents of
460   // this string will be loaded instead of the URI. Setting srcdocData sets
461   // isSrcdocLoad to true
462   nsString mSrcdocData;
463 
464   // When set, this is the Source Browsing Context for the navigation.
465   MaybeDiscarded<BrowsingContext> mSourceBrowsingContext;
466 
467   // Used for srcdoc loads to give view-source knowledge of the load's base URI
468   // as this information isn't embedded in the load's URI.
469   nsCOMPtr<nsIURI> mBaseURI;
470 
471   // Set of Load Flags, taken from nsDocShellLoadTypes.h and nsIWebNavigation
472   uint32_t mLoadFlags;
473 
474   // Set of internal load flags
475   uint32_t mInternalLoadFlags;
476 
477   // Is this a First Party Load?
478   bool mFirstParty;
479 
480   // Is this load triggered by a user gesture?
481   bool mHasValidUserGestureActivation;
482 
483   // Whether this load can steal the focus from the source browsing context.
484   bool mAllowFocusMove;
485 
486   // A hint as to the content-type of the resulting data. If no hint, IsVoid()
487   // should return true.
488   nsCString mTypeHint;
489 
490   // Non-void when the link should be downloaded as the given filename.
491   // mFileName being non-void but empty means that no filename hint was
492   // specified, but link should still trigger a download. If not a download,
493   // mFileName.IsVoid() should return true.
494   nsString mFileName;
495 
496   // This will be true if this load is triggered by attribute changes.
497   // See nsILoadInfo.isFromProcessingFrameAttributes
498   bool mIsFromProcessingFrameAttributes;
499 
500   // If set, a pending cross-process redirected channel should be used to
501   // perform the load. The channel will be stored in this value.
502   nsCOMPtr<nsIChannel> mPendingRedirectedChannel;
503 
504   // An optional string representation of mURI, before any
505   // fixups were applied, so that we can send it to a search
506   // engine service if needed.
507   mozilla::Maybe<nsCString> mOriginalURIString;
508 
509   // An optional value to pass to nsIDocShell::setCancelJSEpoch
510   // when initiating the load.
511   mozilla::Maybe<int32_t> mCancelContentJSEpoch;
512 
513   // If mPendingRedirectChannel is set, then this is the identifier
514   // that the parent-process equivalent channel has been registered
515   // with using RedirectChannelRegistrar.
516   uint64_t mChannelRegistrarId;
517 
518   // An identifier to make it possible to examine if two loads are
519   // equal, and which browsing context they belong to (see
520   // BrowsingContext::{Get, Set}CurrentLoadIdentifier)
521   const uint64_t mLoadIdentifier;
522 
523   // Optional value to indicate that a channel has been
524   // pre-initialized in the parent process.
525   bool mChannelInitialized;
526 
527   // True if the load was triggered by a meta refresh.
528   bool mIsMetaRefresh;
529 
530   // The original URI before query stripping happened. If it's present, it shows
531   // the query stripping happened. Otherwise, it will be a nullptr.
532   nsCOMPtr<nsIURI> mUnstrippedURI;
533 
534   // If set, the remote type which the load should be completed within.
535   mozilla::Maybe<nsCString> mRemoteTypeOverride;
536 };
537 
538 #endif /* nsDocShellLoadState_h__ */
539