summaryrefslogtreecommitdiffstats
path: root/docshell/base/nsDocShellLoadState.h
blob: f74e4f24fb28cf99869ba4a45dc8cd7019c8dbea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsDocShellLoadState_h__
#define nsDocShellLoadState_h__

#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/SessionHistoryEntry.h"

// Helper Classes
#include "mozilla/Maybe.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsDocShellLoadTypes.h"
#include "nsTArrayForwardDeclare.h"

class nsIContentSecurityPolicy;
class nsIInputStream;
class nsISHEntry;
class nsIURI;
class nsIDocShell;
class nsIChannel;
class nsIReferrerInfo;
namespace mozilla {
class OriginAttributes;
template <typename, class>
class UniquePtr;
namespace dom {
class DocShellLoadStateInit;
}  // namespace dom
}  // namespace mozilla

/**
 * nsDocShellLoadState contains setup information used in a nsIDocShell::loadURI
 * call.
 */
class nsDocShellLoadState final {
  using BrowsingContext = mozilla::dom::BrowsingContext;
  template <typename T>
  using MaybeDiscarded = mozilla::dom::MaybeDiscarded<T>;

 public:
  NS_INLINE_DECL_REFCOUNTING(nsDocShellLoadState);

  explicit nsDocShellLoadState(nsIURI* aURI);
  explicit nsDocShellLoadState(
      const mozilla::dom::DocShellLoadStateInit& aLoadState,
      mozilla::ipc::IProtocol* aActor, bool* aReadSuccess);
  explicit nsDocShellLoadState(const nsDocShellLoadState& aOther);
  nsDocShellLoadState(nsIURI* aURI, uint64_t aLoadIdentifier);

  static nsresult CreateFromPendingChannel(nsIChannel* aPendingChannel,
                                           uint64_t aLoadIdentifier,
                                           uint64_t aRegistarId,
                                           nsDocShellLoadState** aResult);

  static nsresult CreateFromLoadURIOptions(
      BrowsingContext* aBrowsingContext, const nsAString& aURI,
      const mozilla::dom::LoadURIOptions& aLoadURIOptions,
      nsDocShellLoadState** aResult);
  static nsresult CreateFromLoadURIOptions(
      BrowsingContext* aBrowsingContext, nsIURI* aURI,
      const mozilla::dom::LoadURIOptions& aLoadURIOptions,
      nsDocShellLoadState** aResult);

  // Getters and Setters

  nsIReferrerInfo* GetReferrerInfo() const;

  void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo);

  nsIURI* URI() const;

  void SetURI(nsIURI* aURI);

  nsIURI* OriginalURI() const;

  void SetOriginalURI(nsIURI* aOriginalURI);

  nsIURI* ResultPrincipalURI() const;

  void SetResultPrincipalURI(nsIURI* aResultPrincipalURI);

  bool ResultPrincipalURIIsSome() const;

  void SetResultPrincipalURIIsSome(bool aIsSome);

  bool KeepResultPrincipalURIIfSet() const;

  void SetKeepResultPrincipalURIIfSet(bool aKeep);

  nsIPrincipal* PrincipalToInherit() const;

  void SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit);

  nsIPrincipal* PartitionedPrincipalToInherit() const;

  void SetPartitionedPrincipalToInherit(
      nsIPrincipal* aPartitionedPrincipalToInherit);

  bool LoadReplace() const;

  void SetLoadReplace(bool aLoadReplace);

  nsIPrincipal* TriggeringPrincipal() const;

  void SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal);

  uint32_t TriggeringSandboxFlags() const;

  void SetTriggeringSandboxFlags(uint32_t aTriggeringSandboxFlags);

  nsIContentSecurityPolicy* Csp() const;

  void SetCsp(nsIContentSecurityPolicy* aCsp);

  bool InheritPrincipal() const;

  void SetInheritPrincipal(bool aInheritPrincipal);

  bool PrincipalIsExplicit() const;

  void SetPrincipalIsExplicit(bool aPrincipalIsExplicit);

  // If true, "beforeunload" event listeners were notified by the creater of the
  // LoadState and given the chance to abort the navigation, and should not be
  // notified again.
  bool NotifiedBeforeUnloadListeners() const;

  void SetNotifiedBeforeUnloadListeners(bool aNotifiedBeforeUnloadListeners);

  bool ForceAllowDataURI() const;

  void SetForceAllowDataURI(bool aForceAllowDataURI);

  bool IsExemptFromHTTPSOnlyMode() const;

  void SetIsExemptFromHTTPSOnlyMode(bool aIsExemptFromHTTPSOnlyMode);

  bool OriginalFrameSrc() const;

  void SetOriginalFrameSrc(bool aOriginalFrameSrc);

  bool IsFormSubmission() const;

  void SetIsFormSubmission(bool aIsFormSubmission);

  uint32_t LoadType() const;

  void SetLoadType(uint32_t aLoadType);

  nsISHEntry* SHEntry() const;

  void SetSHEntry(nsISHEntry* aSHEntry);

  const mozilla::dom::LoadingSessionHistoryInfo* GetLoadingSessionHistoryInfo()
      const;

  // Copies aLoadingInfo and stores the copy in this nsDocShellLoadState.
  void SetLoadingSessionHistoryInfo(
      const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo);

  // Stores aLoadingInfo in this nsDocShellLoadState.
  void SetLoadingSessionHistoryInfo(
      mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> aLoadingInfo);

  bool LoadIsFromSessionHistory() const;

  const nsString& Target() const;

  void SetTarget(const nsAString& aTarget);

  nsIInputStream* PostDataStream() const;

  void SetPostDataStream(nsIInputStream* aStream);

  nsIInputStream* HeadersStream() const;

  void SetHeadersStream(nsIInputStream* aHeadersStream);

  bool IsSrcdocLoad() const;

  const nsString& SrcdocData() const;

  void SetSrcdocData(const nsAString& aSrcdocData);

  const MaybeDiscarded<BrowsingContext>& SourceBrowsingContext() const {
    return mSourceBrowsingContext;
  }

  void SetSourceBrowsingContext(BrowsingContext*);

  void SetAllowFocusMove(bool aAllow) { mAllowFocusMove = aAllow; }

  bool AllowFocusMove() const { return mAllowFocusMove; }

  const MaybeDiscarded<BrowsingContext>& TargetBrowsingContext() const {
    return mTargetBrowsingContext;
  }

  void SetTargetBrowsingContext(BrowsingContext* aTargetBrowsingContext);

  nsIURI* BaseURI() const;

  void SetBaseURI(nsIURI* aBaseURI);

  // Helper function allowing convenient work with mozilla::Maybe in C++, hiding
  // resultPrincipalURI and resultPrincipalURIIsSome attributes from the
  // consumer.
  void GetMaybeResultPrincipalURI(
      mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const;

  void SetMaybeResultPrincipalURI(
      mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI);

  uint32_t LoadFlags() const;

  void SetLoadFlags(uint32_t aFlags);

  void SetLoadFlag(uint32_t aFlag);

  void UnsetLoadFlag(uint32_t aFlag);

  bool HasLoadFlags(uint32_t aFlag);

  uint32_t InternalLoadFlags() const;

  void SetInternalLoadFlags(uint32_t aFlags);

  void SetInternalLoadFlag(uint32_t aFlag);

  void UnsetInternalLoadFlag(uint32_t aFlag);

  bool HasInternalLoadFlags(uint32_t aFlag);

  bool FirstParty() const;

  void SetFirstParty(bool aFirstParty);

  bool HasValidUserGestureActivation() const;

  void SetHasValidUserGestureActivation(bool HasValidUserGestureActivation);

  const nsCString& TypeHint() const;

  void SetTypeHint(const nsCString& aTypeHint);

  const nsString& FileName() const;

  void SetFileName(const nsAString& aFileName);

  nsIURI* GetUnstrippedURI() const;

  void SetUnstrippedURI(nsIURI* aUnstrippedURI);

  // Give the type of DocShell we're loading into (chrome/content/etc) and
  // origin attributes for the URI we're loading, figure out if we should
  // inherit our principal from the document the load was requested from, or
  // else if the principal should be set up later in the process (after loads).
  // See comments in function for more info on principal selection algorithm
  nsresult SetupInheritingPrincipal(
      mozilla::dom::BrowsingContext::Type aType,
      const mozilla::OriginAttributes& aOriginAttributes);

  // If no triggering principal exists at the moment, create one using referrer
  // information and origin attributes.
  nsresult SetupTriggeringPrincipal(
      const mozilla::OriginAttributes& aOriginAttributes);

  void SetIsFromProcessingFrameAttributes() {
    mIsFromProcessingFrameAttributes = true;
  }
  bool GetIsFromProcessingFrameAttributes() const {
    return mIsFromProcessingFrameAttributes;
  }

  nsIChannel* GetPendingRedirectedChannel() {
    return mPendingRedirectedChannel;
  }

  uint64_t GetPendingRedirectChannelRegistrarId() const {
    return mChannelRegistrarId;
  }

  void SetOriginalURIString(const nsCString& aOriginalURI) {
    mOriginalURIString.emplace(aOriginalURI);
  }
  const mozilla::Maybe<nsCString>& GetOriginalURIString() const {
    return mOriginalURIString;
  }

  void SetCancelContentJSEpoch(int32_t aCancelEpoch) {
    mCancelContentJSEpoch.emplace(aCancelEpoch);
  }
  const mozilla::Maybe<int32_t>& GetCancelContentJSEpoch() const {
    return mCancelContentJSEpoch;
  }

  uint64_t GetLoadIdentifier() const { return mLoadIdentifier; }

  void SetChannelInitialized(bool aInitilized) {
    mChannelInitialized = aInitilized;
  }

  bool GetChannelInitialized() const { return mChannelInitialized; }

  void SetIsMetaRefresh(bool aMetaRefresh) { mIsMetaRefresh = aMetaRefresh; }

  bool IsMetaRefresh() const { return mIsMetaRefresh; }

  const mozilla::Maybe<nsCString>& GetRemoteTypeOverride() const {
    return mRemoteTypeOverride;
  }

  void SetRemoteTypeOverride(const nsCString& aRemoteTypeOverride) {
    mRemoteTypeOverride = mozilla::Some(aRemoteTypeOverride);
  }

  // Determine the remote type of the process which should be considered
  // responsible for this load for the purposes of security checks.
  //
  // This will generally be the process which created the nsDocShellLoadState
  // originally, however non-errorpage history loads are always considered to be
  // triggered by the parent process, as we can validate them against the
  // history entry.
  const nsCString& GetEffectiveTriggeringRemoteType() const;

  void SetTriggeringRemoteType(const nsACString& aTriggeringRemoteType);

  // When loading a document through nsDocShell::LoadURI(), a special set of
  // flags needs to be set based on other values in nsDocShellLoadState. This
  // function calculates those flags, before the LoadState is passed to
  // nsDocShell::InternalLoad.
  void CalculateLoadURIFlags();

  // Compute the load flags to be used by creating channel.  aUriModified and
  // aIsXFOError are expected to be Nothing when called from Parent process.
  nsLoadFlags CalculateChannelLoadFlags(
      mozilla::dom::BrowsingContext* aBrowsingContext,
      mozilla::Maybe<bool> aUriModified, mozilla::Maybe<bool> aIsXFOError);

  mozilla::dom::DocShellLoadStateInit Serialize(
      mozilla::ipc::IProtocol* aActor);

  void SetLoadIsFromSessionHistory(int32_t aOffset, bool aLoadingCurrentEntry);
  void ClearLoadIsFromSessionHistory();

  void MaybeStripTrackerQueryStrings(mozilla::dom::BrowsingContext* aContext);

 protected:
  // Destructor can't be defaulted or inlined, as header doesn't have all type
  // includes it needs to do so.
  ~nsDocShellLoadState();

  // Given the original `nsDocShellLoadState` which was sent to a content
  // process, validate that they corespond to the same load.
  // Returns a static (telemetry-safe) string naming what did not match, or
  // nullptr if it succeeds.
  const char* ValidateWithOriginalState(nsDocShellLoadState* aOriginalState);

  static nsresult CreateFromLoadURIOptions(
      BrowsingContext* aBrowsingContext, nsIURI* aURI,
      const mozilla::dom::LoadURIOptions& aLoadURIOptions,
      uint32_t aLoadFlagsOverride, nsIInputStream* aPostDataOverride,
      nsDocShellLoadState** aResult);

  // This is the referrer for the load.
  nsCOMPtr<nsIReferrerInfo> mReferrerInfo;

  // The URI we are navigating to. Will not be null once set.
  nsCOMPtr<nsIURI> mURI;

  // The URI to set as the originalURI on the channel that does the load. If
  // null, aURI will be set as the originalURI.
  nsCOMPtr<nsIURI> mOriginalURI;

  // The URI to be set to loadInfo.resultPrincipalURI
  // - When Nothing, there will be no change
  // - When Some, the principal URI will overwrite even
  //   with a null value.
  //
  // Valid only if mResultPrincipalURIIsSome is true (has the same meaning as
  // isSome() on mozilla::Maybe.)
  nsCOMPtr<nsIURI> mResultPrincipalURI;
  bool mResultPrincipalURIIsSome;

  // The principal of the load, that is, the entity responsible for causing the
  // load to occur. In most cases the referrer and the triggeringPrincipal's URI
  // will be identical.
  //
  // Please note that this is the principal that is used for security checks. If
  // the argument aURI is provided by the web, then please do not pass a
  // SystemPrincipal as the triggeringPrincipal.
  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;

  // The SandboxFlags of the load, that are, the SandboxFlags of the entity
  // responsible for causing the load to occur. Most likely this are the
  // SandboxFlags of the document that started the load.
  uint32_t mTriggeringSandboxFlags;

  // The CSP of the load, that is, the CSP of the entity responsible for causing
  // the load to occur. Most likely this is the CSP of the document that started
  // the load. In case the entity starting the load did not use a CSP, then mCsp
  // can be null. Please note that this is also the CSP that will be applied to
  // the load in case the load encounters a server side redirect.
  nsCOMPtr<nsIContentSecurityPolicy> mCsp;

  // If a refresh is caused by http-equiv="refresh" we want to set
  // aResultPrincipalURI, but we do not want to overwrite the channel's
  // ResultPrincipalURI, if it has already been set on the channel by a protocol
  // handler.
  bool mKeepResultPrincipalURIIfSet;

  // If set LOAD_REPLACE flag will be set on the channel. If aOriginalURI is
  // null, this argument is ignored.
  bool mLoadReplace;

  // If this attribute is true and no triggeringPrincipal is specified,
  // copy the principal from the referring document.
  bool mInheritPrincipal;

  // If this attribute is true only ever use the principal specified
  // by the triggeringPrincipal and inheritPrincipal attributes.
  // If there are security reasons for why this is unsafe, such
  // as trying to use a systemprincipal as the triggeringPrincipal
  // for a content docshell the load fails.
  bool mPrincipalIsExplicit;

  bool mNotifiedBeforeUnloadListeners;

  // Principal we're inheriting. If null, this means the principal should be
  // inherited from the current document. If set to NullPrincipal, the channel
  // will fill in principal information later in the load. See internal comments
  // of SetupInheritingPrincipal for more info.
  //
  // When passed to InternalLoad, If this argument is null then
  // principalToInherit is computed differently. See nsDocShell::InternalLoad
  // for more comments.

  nsCOMPtr<nsIPrincipal> mPrincipalToInherit;

  nsCOMPtr<nsIPrincipal> mPartitionedPrincipalToInherit;

  // If this attribute is true, then a top-level navigation
  // to a data URI will be allowed.
  bool mForceAllowDataURI;

  // If this attribute is true, then the top-level navigaion
  // will be exempt from HTTPS-Only-Mode upgrades.
  bool mIsExemptFromHTTPSOnlyMode;

  // If this attribute is true, this load corresponds to a frame
  // element loading its original src (or srcdoc) attribute.
  bool mOriginalFrameSrc;

  // If this attribute is true, then the load was initiated by a
  // form submission. This is important to know for the CSP directive
  // navigate-to.
  bool mIsFormSubmission;

  // Contains a load type as specified by the nsDocShellLoadTypes::load*
  // constants
  uint32_t mLoadType;

  // Active Session History entry (if loading from SH)
  nsCOMPtr<nsISHEntry> mSHEntry;

  // Loading session history info for the load
  mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo>
      mLoadingSessionHistoryInfo;

  // Target for load, like _content, _blank etc.
  nsString mTarget;

  // When set, this is the Target Browsing Context for the navigation
  // after retargeting.
  MaybeDiscarded<BrowsingContext> mTargetBrowsingContext;

  // Post data stream (if POSTing)
  nsCOMPtr<nsIInputStream> mPostDataStream;

  // Additional Headers
  nsCOMPtr<nsIInputStream> mHeadersStream;

  // When set, the load will be interpreted as a srcdoc load, where contents of
  // this string will be loaded instead of the URI. Setting srcdocData sets
  // isSrcdocLoad to true
  nsString mSrcdocData;

  // When set, this is the Source Browsing Context for the navigation.
  MaybeDiscarded<BrowsingContext> mSourceBrowsingContext;

  // Used for srcdoc loads to give view-source knowledge of the load's base URI
  // as this information isn't embedded in the load's URI.
  nsCOMPtr<nsIURI> mBaseURI;

  // Set of Load Flags, taken from nsDocShellLoadTypes.h and nsIWebNavigation
  uint32_t mLoadFlags;

  // Set of internal load flags
  uint32_t mInternalLoadFlags;

  // Is this a First Party Load?
  bool mFirstParty;

  // Is this load triggered by a user gesture?
  bool mHasValidUserGestureActivation;

  // Whether this load can steal the focus from the source browsing context.
  bool mAllowFocusMove;

  // A hint as to the content-type of the resulting data. If no hint, IsVoid()
  // should return true.
  nsCString mTypeHint;

  // Non-void when the link should be downloaded as the given filename.
  // mFileName being non-void but empty means that no filename hint was
  // specified, but link should still trigger a download. If not a download,
  // mFileName.IsVoid() should return true.
  nsString mFileName;

  // This will be true if this load is triggered by attribute changes.
  // See nsILoadInfo.isFromProcessingFrameAttributes
  bool mIsFromProcessingFrameAttributes;

  // If set, a pending cross-process redirected channel should be used to
  // perform the load. The channel will be stored in this value.
  nsCOMPtr<nsIChannel> mPendingRedirectedChannel;

  // An optional string representation of mURI, before any
  // fixups were applied, so that we can send it to a search
  // engine service if needed.
  mozilla::Maybe<nsCString> mOriginalURIString;

  // An optional value to pass to nsIDocShell::setCancelJSEpoch
  // when initiating the load.
  mozilla::Maybe<int32_t> mCancelContentJSEpoch;

  // If mPendingRedirectChannel is set, then this is the identifier
  // that the parent-process equivalent channel has been registered
  // with using RedirectChannelRegistrar.
  uint64_t mChannelRegistrarId;

  // An identifier to make it possible to examine if two loads are
  // equal, and which browsing context they belong to (see
  // BrowsingContext::{Get, Set}CurrentLoadIdentifier)
  const uint64_t mLoadIdentifier;

  // Optional value to indicate that a channel has been
  // pre-initialized in the parent process.
  bool mChannelInitialized;

  // True if the load was triggered by a meta refresh.
  bool mIsMetaRefresh;

  // True if the nsDocShellLoadState was received over IPC.
  bool mWasCreatedRemotely = false;

  // The original URI before query stripping happened. If it's present, it shows
  // the query stripping happened. Otherwise, it will be a nullptr.
  nsCOMPtr<nsIURI> mUnstrippedURI;

  // If set, the remote type which the load should be completed within.
  mozilla::Maybe<nsCString> mRemoteTypeOverride;

  // Remote type of the process which originally requested the load.
  nsCString mTriggeringRemoteType;
};

#endif /* nsDocShellLoadState_h__ */