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