summaryrefslogtreecommitdiffstats
path: root/docshell/base/nsDocShellLoadState.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--docshell/base/nsDocShellLoadState.h609
1 files changed, 609 insertions, 0 deletions
diff --git a/docshell/base/nsDocShellLoadState.h b/docshell/base/nsDocShellLoadState.h
new file mode 100644
index 0000000000..a34ca1b54b
--- /dev/null
+++ b/docshell/base/nsDocShellLoadState.h
@@ -0,0 +1,609 @@
+/* -*- 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);
+
+ uint64_t TriggeringWindowId() const;
+
+ void SetTriggeringWindowId(uint64_t aTriggeringWindowId);
+
+ bool TriggeringStorageAccess() const;
+
+ void SetTriggeringStorageAccess(bool aTriggeringStorageAccess);
+
+ 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 IsExemptFromHTTPSFirstMode() const;
+
+ void SetIsExemptFromHTTPSFirstMode(bool aIsExemptFromHTTPSFirstMode);
+
+ 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);
+ }
+
+ void SetWasSchemelessInput(bool aWasSchemelessInput) {
+ mWasSchemelessInput = aWasSchemelessInput;
+ }
+
+ bool GetWasSchemelessInput() { return mWasSchemelessInput; }
+
+ // 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);
+
+ // Diagnostic assert if this is a system-principal triggered load, and it is
+ // trivial to determine that the effective triggering remote type would not be
+ // allowed to perform this load.
+ //
+ // This is called early during the load to crash as close to the cause as
+ // possible. See bug 1838686 for details.
+#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
+ void AssertProcessCouldTriggerLoadIfSystem();
+#else
+ void AssertProcessCouldTriggerLoadIfSystem() {}
+#endif
+
+ // 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
+ // aIsEmbeddingBlockedError are expected to be Nothing when called from parent
+ // process.
+ nsLoadFlags CalculateChannelLoadFlags(
+ mozilla::dom::BrowsingContext* aBrowsingContext,
+ mozilla::Maybe<bool> aUriModified,
+ mozilla::Maybe<bool> aIsEmbeddingBlockedError);
+
+ 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 window ID and current "has storage access" value of the entity
+ // triggering the load. This allows the identification of self-initiated
+ // same-origin navigations that should propogate unpartitioned storage access.
+ uint64_t mTriggeringWindowId;
+ bool mTriggeringStorageAccess;
+
+ // 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 mIsExemptFromHTTPSFirstMode;
+
+ // 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.
+ 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;
+
+ // if the to-be-loaded address had it protocol added through a fixup
+ bool mWasSchemelessInput = false;
+};
+
+#endif /* nsDocShellLoadState_h__ */