tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DocumentLoadListener.h (26892B)


      1 /* vim: set sw=2 ts=8 et tw=80 : */
      2 
      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 mozilla_net_DocumentLoadListener_h
      8 #define mozilla_net_DocumentLoadListener_h
      9 
     10 #include "mozilla/MozPromise.h"
     11 #include "mozilla/Variant.h"
     12 #include "mozilla/WeakPtr.h"
     13 #include "mozilla/ipc/Endpoint.h"
     14 #include "mozilla/dom/SessionHistoryEntry.h"
     15 #include "EarlyHintsService.h"
     16 #include "mozilla/net/NeckoCommon.h"
     17 #include "mozilla/net/NeckoParent.h"
     18 #include "mozilla/net/PDocumentChannelParent.h"
     19 #include "mozilla/net/ParentChannelListener.h"
     20 #include "nsDOMNavigationTiming.h"
     21 #include "nsIBrowser.h"
     22 #include "nsIChannelEventSink.h"
     23 #include "nsIEarlyHintObserver.h"
     24 #include "nsIInterfaceRequestor.h"
     25 #include "nsIMultiPartChannel.h"
     26 #include "nsIParentChannel.h"
     27 #include "nsIParentRedirectingChannel.h"
     28 #include "nsIProgressEventSink.h"
     29 #include "nsIRedirectResultListener.h"
     30 
     31 #define DOCUMENT_LOAD_LISTENER_IID \
     32  {0x3b393c56, 0x9e01, 0x11e9, {0xa2, 0xa3, 0x2a, 0x2a, 0xe2, 0xdb, 0xcc, 0xe4}}
     33 
     34 namespace mozilla {
     35 namespace dom {
     36 class CanonicalBrowsingContext;
     37 struct NavigationIsolationOptions;
     38 }  // namespace dom
     39 namespace net {
     40 using ChildEndpointPromise =
     41    MozPromise<mozilla::ipc::Endpoint<extensions::PStreamFilterChild>, bool,
     42               true>;
     43 
     44 // If we've been asked to attach a stream filter to our channel,
     45 // then we return this promise and defer until we know the final
     46 // content process. At that point we setup Endpoints between
     47 // mStramFilterProcessId and the new content process, and send
     48 // the parent Endpoint to the new process.
     49 // Once we have confirmation of that being bound in the content
     50 // process, we resolve the promise the child Endpoint.
     51 struct StreamFilterRequest {
     52  StreamFilterRequest() = default;
     53  StreamFilterRequest(StreamFilterRequest&&) = default;
     54  ~StreamFilterRequest() {
     55    if (mPromise) {
     56      mPromise->Reject(false, __func__);
     57    }
     58  }
     59  RefPtr<ChildEndpointPromise::Private> mPromise;
     60  mozilla::ipc::Endpoint<extensions::PStreamFilterChild> mChildEndpoint;
     61 };
     62 }  // namespace net
     63 }  // namespace mozilla
     64 MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::net::StreamFilterRequest)
     65 
     66 namespace mozilla {
     67 namespace net {
     68 
     69 class LoadInfo;
     70 
     71 /**
     72 * DocumentLoadListener represents a connecting document load for a
     73 * CanonicalBrowsingContext (in the parent process).
     74 *
     75 * It creates a network channel for the document load and then waits for it to
     76 * receive a response (after all redirects are resolved). It then decides where
     77 * to handle that load (could be in a different process from the initiator),
     78 * and then sets up a real network nsIChannel to deliver the data to the final
     79 * destination docshell, maybe through an nsIParentChannel/nsIChildChannel IPDL
     80 * layer.
     81 *
     82 * In the case where this was initiated from an nsDocShell, we also create an
     83 * nsIChannel to act as a placeholder within the docshell while this process
     84 * completes, and then notify the docshell of a 'redirect' when we replace this
     85 * channel with the real one.
     86 */
     87 
     88 // TODO: We currently don't implement nsIProgressEventSink and forward those
     89 // to the child. Should we? We get the interface requested.
     90 class DocumentLoadListener : public nsIInterfaceRequestor,
     91                             public nsIAsyncVerifyRedirectReadyCallback,
     92                             public nsIParentChannel,
     93                             public nsIChannelEventSink,
     94                             public HttpChannelSecurityWarningReporter,
     95                             public nsIMultiPartChannelListener,
     96                             public nsIProgressEventSink,
     97                             public nsIEarlyHintObserver {
     98 public:
     99  // See the comment on GetLoadingBrowsingContext for explanation of
    100  // aLoadingBrowsingContext.
    101  DocumentLoadListener(dom::CanonicalBrowsingContext* aLoadingBrowsingContext,
    102                       bool aIsDocumentLoad);
    103 
    104  struct OpenPromiseSucceededType {
    105    nsTArray<mozilla::ipc::Endpoint<extensions::PStreamFilterParent>>
    106        mStreamFilterEndpoints;
    107    uint32_t mRedirectFlags;
    108    uint32_t mLoadFlags;
    109    uint32_t mEarlyHintLinkType;
    110    RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise::Private>
    111        mPromise;
    112  };
    113  struct OpenPromiseFailedType {
    114    nsresult mStatus;
    115    nsresult mLoadGroupStatus;
    116    // This is set to true if the navigation in the content process should not
    117    // be cancelled, as the load is logically continuing within the current
    118    // browsing session, just within a different process or browsing context.
    119    bool mContinueNavigating = false;
    120  };
    121 
    122  using OpenPromise =
    123      MozPromise<OpenPromiseSucceededType, OpenPromiseFailedType, true>;
    124 
    125  // Interface which may be provided when performing an <object> or <embed> load
    126  // with `DocumentLoadListener`, to allow upgrading the Object load to a proper
    127  // Document load.
    128  struct ObjectUpgradeHandler : public SupportsWeakPtr {
    129    using ObjectUpgradePromise =
    130        MozPromise<RefPtr<dom::CanonicalBrowsingContext>, nsresult,
    131                   true /* isExclusive */>;
    132 
    133    // Upgrade an object load to be a potentially remote document.
    134    //
    135    // The returned promise will resolve with the BrowsingContext which has been
    136    // created in the <object> or <embed> element to finish the load with.
    137    virtual RefPtr<ObjectUpgradePromise> UpgradeObjectLoad() = 0;
    138  };
    139 
    140 private:
    141  // Creates the channel, and then calls AsyncOpen on it.
    142  // The DocumentLoadListener will require additional process from the consumer
    143  // in order to complete the redirect to the end channel. This is done by
    144  // returning a RedirectToRealChannelPromise and then waiting for it to be
    145  // resolved or rejected accordingly.
    146  // Once that promise is resolved; the consumer no longer needs to hold a
    147  // reference to the DocumentLoadListener nor will the consumer required to be
    148  // used again.
    149  RefPtr<OpenPromise> Open(nsDocShellLoadState* aLoadState, LoadInfo* aLoadInfo,
    150                           nsLoadFlags aLoadFlags, uint32_t aCacheKey,
    151                           const Maybe<uint64_t>& aChannelId,
    152                           const TimeStamp& aAsyncOpenTime,
    153                           nsDOMNavigationTiming* aTiming,
    154                           Maybe<dom::ClientInfo>&& aInfo, bool aUrgentStart,
    155                           dom::ContentParent* aContentParent, nsresult* aRv);
    156 
    157 public:
    158  RefPtr<OpenPromise> OpenDocument(
    159      nsDocShellLoadState* aLoadState, nsLoadFlags aLoadFlags,
    160      uint32_t aCacheKey, const Maybe<uint64_t>& aChannelId,
    161      const TimeStamp& aAsyncOpenTime, nsDOMNavigationTiming* aTiming,
    162      Maybe<dom::ClientInfo>&& aInfo, bool aUriModified,
    163      Maybe<bool> aIsEmbeddingBlockedError, dom::ContentParent* aContentParent,
    164      nsresult* aRv);
    165 
    166  RefPtr<OpenPromise> OpenObject(
    167      nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
    168      const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
    169      nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
    170      uint64_t aInnerWindowId, nsLoadFlags aLoadFlags,
    171      nsContentPolicyType aContentPolicyType, bool aUrgentStart,
    172      dom::ContentParent* aContentParent,
    173      ObjectUpgradeHandler* aObjectUpgradeHandler, nsresult* aRv);
    174 
    175  // Creates a DocumentLoadListener entirely in the parent process and opens it,
    176  // and never needs a DocumentChannel to connect to an existing docshell.
    177  // Once we get a response it takes the 'process switch' path to find the right
    178  // process and docshell, and delivers the response there directly.
    179  static bool LoadInParent(dom::CanonicalBrowsingContext* aBrowsingContext,
    180                           nsDocShellLoadState* aLoadState,
    181                           bool aSetNavigating);
    182 
    183  // Creates a DocumentLoadListener directly in the parent process and opens it,
    184  // without needing an existing DocumentChannel.
    185  // If successful it registers a unique identifier (return in aOutIdent) to
    186  // keep it alive until a future DocumentChannel can attach to it, or we fail
    187  // and clean up.
    188  static bool SpeculativeLoadInParent(
    189      dom::CanonicalBrowsingContext* aBrowsingContext,
    190      nsDocShellLoadState* aLoadState);
    191 
    192  // Ensures that a load identifier allocated by OpenFromParent has
    193  // been deregistered if it hasn't already been claimed.
    194  // This also cancels the load.
    195  static void CleanupParentLoadAttempt(uint64_t aLoadIdent);
    196 
    197  // Looks up aLoadIdent to find the associated, cleans up the registration
    198  static RefPtr<OpenPromise> ClaimParentLoad(DocumentLoadListener** aListener,
    199                                             uint64_t aLoadIdent,
    200                                             Maybe<uint64_t> aChannelId);
    201 
    202  // Called by the DocumentChannelParent if actor got destroyed or the parent
    203  // channel got deleted.
    204  void Abort();
    205 
    206  NS_DECL_ISUPPORTS
    207  NS_DECL_NSIREQUESTOBSERVER
    208  NS_DECL_NSISTREAMLISTENER
    209  NS_DECL_NSIPARENTCHANNEL
    210  NS_DECL_NSIINTERFACEREQUESTOR
    211  NS_DECL_NSIASYNCVERIFYREDIRECTREADYCALLBACK
    212  NS_DECL_NSICHANNELEVENTSINK
    213  NS_DECL_NSIMULTIPARTCHANNELLISTENER
    214  NS_DECL_NSIPROGRESSEVENTSINK
    215  NS_DECL_NSIEARLYHINTOBSERVER
    216 
    217  // We suspend the underlying channel when replacing ourselves with
    218  // the real listener channel.
    219  // This helper resumes the underlying channel again, and manually
    220  // forwards any nsIStreamListener messages that arrived while we
    221  // were suspended (which might have failed).
    222  // Returns true if the channel was finished before we could resume it.
    223  bool ResumeSuspendedChannel(nsIStreamListener* aListener);
    224 
    225  NS_INLINE_DECL_STATIC_IID(DOCUMENT_LOAD_LISTENER_IID)
    226 
    227  // Called by the DocumentChannel if cancelled.
    228  void Cancel(const nsresult& aStatusCode, const nsACString& aReason);
    229 
    230  nsIChannel* GetChannel() const { return mChannel; }
    231 
    232  uint32_t GetRedirectChannelId() const { return mRedirectChannelId; }
    233 
    234  nsresult ReportSecurityMessage(const nsAString& aMessageTag,
    235                                 const nsAString& aMessageCategory) override {
    236    ReportSecurityMessageParams params;
    237    params.mMessageTag = aMessageTag;
    238    params.mMessageCategory = aMessageCategory;
    239    mSecurityWarningFunctions.AppendElement(
    240        SecurityWarningFunction{VariantIndex<0>{}, std::move(params)});
    241    return NS_OK;
    242  }
    243 
    244  nsresult LogBlockedCORSRequest(const nsAString& aMessage,
    245                                 const nsACString& aCategory,
    246                                 bool aIsWarning) override {
    247    LogBlockedCORSRequestParams params;
    248    params.mMessage = aMessage;
    249    params.mCategory = aCategory;
    250    params.mIsWarning = aIsWarning;
    251    mSecurityWarningFunctions.AppendElement(
    252        SecurityWarningFunction{VariantIndex<1>{}, std::move(params)});
    253    return NS_OK;
    254  }
    255 
    256  nsresult LogMimeTypeMismatch(const nsACString& aMessageName, bool aWarning,
    257                               const nsAString& aURL,
    258                               const nsAString& aContentType) override {
    259    LogMimeTypeMismatchParams params;
    260    params.mMessageName = aMessageName;
    261    params.mWarning = aWarning;
    262    params.mURL = aURL;
    263    params.mContentType = aContentType;
    264    mSecurityWarningFunctions.AppendElement(
    265        SecurityWarningFunction{VariantIndex<2>{}, std::move(params)});
    266    return NS_OK;
    267  }
    268 
    269  // The content process corresponding to this DocumentLoadListener, or nullptr
    270  // if connected to the parent process.
    271  dom::ContentParent* GetContentParent() const { return mContentParent; }
    272 
    273  // The process id of the content process that we are being called from
    274  // or 0 initiated from a parent process load.
    275  base::ProcessId OtherPid() const;
    276 
    277  [[nodiscard]] RefPtr<ChildEndpointPromise> AttachStreamFilter();
    278 
    279  // EarlyHints aren't supported on ParentProcessDocumentChannels yet, allow
    280  // EarlyHints to be cancelled from there (Bug 1819886)
    281  void CancelEarlyHintPreloads();
    282 
    283  // Gets the EarlyHint preloads for this document to pass them to the
    284  // ContentProcess. Registers them in the EarlyHintRegister
    285  void RegisterEarlyHintLinksAndGetConnectArgs(
    286      dom::ContentParentId aCpId, nsTArray<EarlyHintConnectArgs>& aOutLinks);
    287 
    288  // Serializes all data needed to setup the new replacement channel
    289  // in the content process into the RedirectToRealChannelArgs struct.
    290  void SerializeRedirectData(RedirectToRealChannelArgs& aArgs,
    291                             bool aIsCrossProcess, uint32_t aRedirectFlags,
    292                             uint32_t aLoadFlags,
    293                             nsTArray<EarlyHintConnectArgs>&& aEarlyHints,
    294                             uint32_t aEarlyHintLinkType) const;
    295 
    296  uint64_t GetLoadIdentifier() const { return mLoadIdentifier; }
    297  uint32_t GetLoadType() const { return mLoadStateLoadType; }
    298  bool IsDownload() const { return mIsDownload; }
    299  bool IsLoadingJSURI() const { return mIsLoadingJSURI; }
    300  nsDOMNavigationTiming* GetTiming() { return mTiming; }
    301 
    302  mozilla::dom::LoadingSessionHistoryInfo* GetLoadingSessionHistoryInfo() {
    303    return mLoadingSessionHistoryInfo.get();
    304  }
    305 
    306  bool IsDocumentLoad() const { return mIsDocumentLoad; }
    307 
    308  // Determine what process switching behavior a browser element should have.
    309  enum ProcessBehavior : uint8_t {
    310    // Gecko won't automatically change which process this frame, or it's
    311    // subframes, are loaded in.
    312    PROCESS_BEHAVIOR_DISABLED,
    313 
    314    // If `useRemoteTabs` is enabled, Gecko will change which process this frame
    315    // is loaded in automatically, without calling `performProcessSwitch`.
    316    // When `useRemoteSubframes` is enabled, subframes will change processes.
    317    PROCESS_BEHAVIOR_STANDARD,
    318 
    319    // Gecko won't automatically change which process this frame is loaded, but
    320    // when `useRemoteSubframes` is enabled, subframes will change processes.
    321    //
    322    // NOTE: This configuration is included only for backwards compatibility,
    323    // and will be removed, as it can easily lead to invalid behavior.
    324    PROCESS_BEHAVIOR_SUBFRAME_ONLY,
    325  };
    326 
    327 protected:
    328  virtual ~DocumentLoadListener();
    329 
    330 private:
    331  RefPtr<OpenPromise> OpenInParent(nsDocShellLoadState* aLoadState,
    332                                   bool aSupportsRedirectToRealChannel);
    333 
    334  friend class ParentProcessDocumentOpenInfo;
    335 
    336  // Will reject the promise to notify the DLL consumer that we are done.
    337  //
    338  // If `aContinueNavigating` is true, the navigation in the content process
    339  // will not be aborted, as navigation is logically continuing in the existing
    340  // browsing session (e.g. due to a process switch or entering the bfcache).
    341  void DisconnectListeners(nsresult aStatus, nsresult aLoadGroupStatus,
    342                           bool aContinueNavigating = false);
    343 
    344  // Called when we were created without a document channel, and creation has
    345  // failed, and won't ever be attached.
    346  void NotifyDocumentChannelFailed();
    347 
    348  // Initiates the switch from DocumentChannel to the real protocol-specific
    349  // channel, and ensures that RedirectToRealChannelFinished is called when
    350  // this is complete.
    351  void TriggerRedirectToRealChannel(
    352      dom::CanonicalBrowsingContext* aDestinationBrowsingContext,
    353      const Maybe<dom::ContentParent*>& aDestinationProcess,
    354      nsTArray<StreamFilterRequest> aStreamFilterRequests);
    355 
    356  // Called once the content-process side on setting up a replacement
    357  // channel is complete. May wait for the new parent channel to
    358  // finish, and then calls into FinishReplacementChannelSetup.
    359  void RedirectToRealChannelFinished(nsresult aRv);
    360 
    361  // Completes the replacement of the new channel.
    362  // This redirects the ParentChannelListener to forward any future
    363  // messages to the new channel, manually forwards any being held
    364  // by us, and resumes the underlying source channel.
    365  void FinishReplacementChannelSetup(nsresult aResult);
    366 
    367  // TODO: Make nsIRequestObserver MOZ_CAN_RUN_SCRIPT, then remove this. It's a
    368  // scriptable interface so it should be the right thing to do.
    369  MOZ_CAN_RUN_SCRIPT_BOUNDARY
    370  nsresult DoOnStartRequest(nsIRequest*);
    371 
    372  // Called from `OnStartRequest` to make the decision about whether or not to
    373  // change process. This method will return `nullptr` if the current target
    374  // process is appropriate.
    375  // aWillSwitchToRemote is set to true if we initiate a process switch,
    376  // and that the new remote type will be something other than NOT_REMOTE
    377  MOZ_CAN_RUN_SCRIPT
    378  bool MaybeTriggerProcessSwitch(bool* aWillSwitchToRemote);
    379 
    380  // Called when the process switch is going to happen, potentially
    381  // asynchronously, from `MaybeTriggerProcessSwitch`.
    382  //
    383  // aContext should be the target context for the navigation. This will either
    384  // be the loading BrowsingContext, the newly created BrowsingContext for an
    385  // object or embed element load, or a newly created tab for new tab load.
    386  //
    387  // If `aIsNewTab` is specified, the navigation in the original process will be
    388  // aborted immediately, rather than waiting for a process switch to happen and
    389  // the previous page to be unloaded or hidden.
    390  MOZ_CAN_RUN_SCRIPT
    391  void TriggerProcessSwitch(dom::CanonicalBrowsingContext* aContext,
    392                            const dom::NavigationIsolationOptions& aOptions,
    393                            bool aIsNewTab = false);
    394 
    395  // A helper for TriggerRedirectToRealChannel that abstracts over
    396  // the same-process and cross-process switch cases and returns
    397  // a single promise to wait on.
    398  using ParentEndpoint =
    399      mozilla::ipc::Endpoint<extensions::PStreamFilterParent>;
    400  RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise>
    401  RedirectToRealChannel(uint32_t aRedirectFlags, uint32_t aLoadFlags,
    402                        const Maybe<dom::ContentParent*>& aDestinationProcess,
    403                        nsTArray<ParentEndpoint>&& aStreamFilterEndpoints);
    404 
    405  // A helper for RedirectToRealChannel that handles the case where we started
    406  // from a content process and are process switching into the parent process.
    407  RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise>
    408  RedirectToParentProcess(uint32_t aRedirectFlags, uint32_t aLoadFlags);
    409 
    410  // Return the Browsing Context that is performing the load.
    411  // For document loads, the BC is the one that the (sub)doc
    412  // will load into. For <object>/<embed>, it's the embedder document's BC.
    413  dom::CanonicalBrowsingContext* GetLoadingBrowsingContext() const;
    414 
    415  // Return the Browsing Context that document is being loaded into. For
    416  // non-document loads, this will return nullptr.
    417  dom::CanonicalBrowsingContext* GetDocumentBrowsingContext() const;
    418  dom::CanonicalBrowsingContext* GetTopBrowsingContext() const;
    419 
    420  // Return the Window Context which which contains the element which the load
    421  // is being performed in. For toplevel loads, this will return `nullptr`.
    422  dom::WindowGlobalParent* GetParentWindowContext() const;
    423 
    424  void AddURIVisit(nsIChannel* aChannel, uint32_t aLoadFlags);
    425  bool HasCrossOriginOpenerPolicyMismatch() const;
    426  void ApplyPendingFunctions(nsIParentChannel* aChannel) const;
    427 
    428  void Disconnect(bool aContinueNavigating);
    429 
    430  void MaybeReportBlockedByURLClassifier(nsresult aStatus);
    431 
    432  // Returns true if a channel with aStatus will display
    433  // some sort of content (could be the actual channel data,
    434  // attempt a uri fixup and new load, or an error page).
    435  // Returns false if the docshell will ignore the load entirely.
    436  bool DocShellWillDisplayContent(nsresult aStatus);
    437 
    438  void FireStateChange(uint32_t aStateFlags, nsresult aStatus);
    439 
    440  // Returns true if this is a failed load, where we have successfully
    441  // created a fixed URI to attempt loading instead.
    442  // If successful, this calls DisconnectListeners to completely finish
    443  // the current load, and calls BrowsingContext::LoadURI to start the new one.
    444  bool MaybeHandleLoadErrorWithURIFixup(nsresult aStatus);
    445 
    446  // This defines a variant that describes all the attribute setters (and their
    447  // parameters) from nsIParentChannel
    448  //
    449  // SetClassifierMatchedInfo(const nsACString& aList, const nsACString&
    450  // aProvider, const nsACString& aFullHash) = 0;
    451  // SetClassifierMatchedTrackingInfo(const nsACString& aLists, const
    452  // nsACString& aFullHashes) = 0; NotifyClassificationFlags(uint32_t
    453  // aClassificationFlags, bool aIsThirdParty) = 0;
    454  struct ClassifierMatchedInfoParams {
    455    nsCString mList;
    456    nsCString mProvider;
    457    nsCString mFullHash;
    458  };
    459 
    460  struct ClassifierMatchedTrackingInfoParams {
    461    nsCString mLists;
    462    nsCString mFullHashes;
    463  };
    464 
    465  struct ClassificationFlagsParams {
    466    uint32_t mClassificationFlags;
    467    bool mIsThirdParty;
    468  };
    469 
    470  using IParentChannelFunction =
    471      mozilla::Variant<ClassifierMatchedInfoParams,
    472                       ClassifierMatchedTrackingInfoParams,
    473                       ClassificationFlagsParams>;
    474 
    475  // Store a list of all the attribute setters that have been called on this
    476  // channel, so that we can repeat them on the real channel that we redirect
    477  // to.
    478  nsTArray<IParentChannelFunction> mIParentChannelFunctions;
    479 
    480  // This defines a variant this describes all the functions
    481  // from HttpChannelSecurityWarningReporter so that we can forward
    482  // them on to the real channel.
    483 
    484  struct ReportSecurityMessageParams {
    485    nsString mMessageTag;
    486    nsString mMessageCategory;
    487  };
    488 
    489  struct LogBlockedCORSRequestParams {
    490    nsString mMessage;
    491    nsCString mCategory;
    492    bool mIsWarning;
    493  };
    494 
    495  struct LogMimeTypeMismatchParams {
    496    nsCString mMessageName;
    497    bool mWarning = false;
    498    nsString mURL;
    499    nsString mContentType;
    500  };
    501 
    502  using SecurityWarningFunction =
    503      mozilla::Variant<ReportSecurityMessageParams, LogBlockedCORSRequestParams,
    504                       LogMimeTypeMismatchParams>;
    505  nsTArray<SecurityWarningFunction> mSecurityWarningFunctions;
    506 
    507  // TODO Backtrack this.
    508  // The set of nsIStreamListener functions that got called on this
    509  // listener, so that we can replay them onto the replacement channel's
    510  // listener. This should generally only be OnStartRequest, since we
    511  // Suspend() the channel at that point, but it can fail sometimes
    512  // so we have to support holding a list.
    513  nsTArray<StreamListenerFunction> mStreamListenerFunctions;
    514 
    515  nsCOMPtr<nsIChannel> mChannel;
    516 
    517  Maybe<uint64_t> mDocumentChannelId;
    518 
    519  // An instance of ParentChannelListener that we use as a listener
    520  // between mChannel (and any future redirected mChannels) and us.
    521  // This handles service worker interception, and retargetting
    522  // OnDataAvailable/OnStopRequest messages onto the listener that
    523  // replaces us.
    524  RefPtr<ParentChannelListener> mParentChannelListener;
    525 
    526  // Get the channel creation URI for constructing the channel in the content
    527  // process. See the function for more details.
    528  nsIURI* GetChannelCreationURI() const;
    529 
    530  // The original navigation timing information containing various timestamps
    531  // such as when the original load started.
    532  // This will be passed back to the new content process should a process
    533  // switch occurs.
    534  RefPtr<nsDOMNavigationTiming> mTiming;
    535 
    536  net::EarlyHintsService mEarlyHintsService;
    537 
    538  // An optional ObjectUpgradeHandler which can be used to upgrade an <object>
    539  // or <embed> element to contain a nsFrameLoader, allowing us to switch them
    540  // into a different process.
    541  //
    542  // A weak pointer is held in order to avoid reference cycles.
    543  WeakPtr<ObjectUpgradeHandler> mObjectUpgradeHandler;
    544 
    545  // Used to identify an internal redirect in redirect chain.
    546  // True when we have seen at least one non-interal redirect.
    547  bool mHaveVisibleRedirect = false;
    548 
    549  // Pending stream filter requests which should be attached when redirecting to
    550  // the real channel. Moved into `TriggerRedirectToRealChannel` when the
    551  // connection is ready.
    552  nsTArray<StreamFilterRequest> mStreamFilterRequests;
    553 
    554  nsString mSrcdocData;
    555  nsCOMPtr<nsIURI> mBaseURI;
    556 
    557  mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo>
    558      mLoadingSessionHistoryInfo;
    559 
    560  RefPtr<dom::WindowGlobalParent> mParentWindowContext;
    561 
    562  // Flags from nsDocShellLoadState::LoadFlags/Type that we want to make
    563  // available to the new docshell if we switch processes.
    564  uint32_t mLoadStateExternalLoadFlags = 0;
    565  uint32_t mLoadStateInternalLoadFlags = 0;
    566  uint32_t mLoadStateLoadType = 0;
    567 
    568  // Indicates if this load is a download.
    569  bool mIsDownload = false;
    570 
    571  // Indicates if we are loading a javascript URI.
    572  bool mIsLoadingJSURI = false;
    573 
    574  // Corresponding redirect channel registrar Id for the final channel that
    575  // we want to use when redirecting the child, or doing a process switch.
    576  // 0 means redirection is not started.
    577  uint64_t mRedirectChannelId = 0;
    578  // Set to true once we initiate the redirect to a real channel (either
    579  // via a process switch or a same-process redirect, and Suspend the
    580  // underlying channel.
    581  bool mInitiatedRedirectToRealChannel = false;
    582  // The value of GetApplyConversion on mChannel when OnStartRequest
    583  // was called. We override it to false to prevent a conversion
    584  // helper from being installed, but we need to restore the value
    585  // later.
    586  bool mOldApplyConversion = false;
    587  // Set to true if any previous channel that we redirected away
    588  // from had a COOP mismatch.
    589  bool mHasCrossOriginOpenerPolicyMismatch = false;
    590  // Set to true if we've received OnStopRequest, and shouldn't
    591  // setup a reference from the ParentChannelListener to the replacement
    592  // channel.
    593  bool mIsFinished = false;
    594 
    595  // The id of the currently pending load which is
    596  // passed to the childChannel in order to identify it in the new process.
    597  uint64_t mLoadIdentifier = 0;
    598 
    599  Maybe<nsCString> mOriginalUriString;
    600 
    601  // Parent-initiated loads do not support redirects to real channels.
    602  bool mSupportsRedirectToRealChannel = true;
    603 
    604  Maybe<nsCString> mRemoteTypeOverride;
    605 
    606  // The ContentParent which this channel is currently connected to, or nullptr
    607  // if connected to the parent process.
    608  RefPtr<dom::ContentParent> mContentParent;
    609 
    610  void RejectOpenPromise(nsresult aStatus, nsresult aLoadGroupStatus,
    611                         bool aContinueNavigating, StaticString aLocation) {
    612    // It is possible for mOpenPromise to not be set if AsyncOpen failed and
    613    // the DocumentChannel got canceled.
    614    if (!mOpenPromiseResolved && mOpenPromise) {
    615      mOpenPromise->Reject(OpenPromiseFailedType({aStatus, aLoadGroupStatus,
    616                                                  aContinueNavigating}),
    617                           aLocation);
    618      mOpenPromiseResolved = true;
    619    }
    620  }
    621  RefPtr<OpenPromise::Private> mOpenPromise;
    622  bool mOpenPromiseResolved = false;
    623 
    624  const bool mIsDocumentLoad;
    625 
    626  RefPtr<HTTPSFirstDowngradeData> mHTTPSFirstDowngradeData;
    627 };
    628 
    629 inline nsISupports* ToSupports(DocumentLoadListener* aObj) {
    630  return static_cast<nsIInterfaceRequestor*>(aObj);
    631 }
    632 
    633 }  // namespace net
    634 }  // namespace mozilla
    635 
    636 #endif  // mozilla_net_DocumentChannelParent_h