/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=8 et 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 mozilla_net_HttpChannelParent_h #define mozilla_net_HttpChannelParent_h #include "HttpBaseChannel.h" #include "nsHttp.h" #include "mozilla/net/PHttpChannelParent.h" #include "mozilla/net/NeckoCommon.h" #include "mozilla/net/NeckoParent.h" #include "mozilla/MozPromise.h" #include "nsIParentRedirectingChannel.h" #include "nsIProgressEventSink.h" #include "nsIChannelEventSink.h" #include "nsIRedirectResultListener.h" #include "nsHttpChannel.h" #include "mozilla/dom/ipc/IdType.h" #include "nsIMultiPartChannel.h" #include "nsIURI.h" class nsICacheEntry; #define HTTP_CHANNEL_PARENT_IID \ { \ 0x982b2372, 0x7aa5, 0x4e8a, { \ 0xbd, 0x9f, 0x89, 0x74, 0xd7, 0xf0, 0x58, 0xeb \ } \ } namespace mozilla { namespace dom { class BrowserParent; } // namespace dom namespace net { class HttpBackgroundChannelParent; class ParentChannelListener; class ChannelEventQueue; class HttpChannelParent final : public nsIInterfaceRequestor, public PHttpChannelParent, public nsIParentRedirectingChannel, public nsIProgressEventSink, public HttpChannelSecurityWarningReporter, public nsIAsyncVerifyRedirectReadyCallback, public nsIChannelEventSink, public nsIRedirectResultListener, public nsIMultiPartChannelListener { virtual ~HttpChannelParent(); public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSIPARENTCHANNEL NS_DECL_NSIPARENTREDIRECTINGCHANNEL NS_DECL_NSIPROGRESSEVENTSINK NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIASYNCVERIFYREDIRECTREADYCALLBACK NS_DECL_NSICHANNELEVENTSINK NS_DECL_NSIREDIRECTRESULTLISTENER NS_DECL_NSIMULTIPARTCHANNELLISTENER NS_DECLARE_STATIC_IID_ACCESSOR(HTTP_CHANNEL_PARENT_IID) HttpChannelParent(dom::BrowserParent* iframeEmbedding, nsILoadContext* aLoadContext, PBOverrideStatus aOverrideStatus); [[nodiscard]] bool Init(const HttpChannelCreationArgs& aArgs); // Forwarded to nsHttpChannel::SetApplyConversion. void SetApplyConversion(bool aApplyConversion) { if (mChannel) { mChannel->SetApplyConversion(aApplyConversion); } } [[nodiscard]] nsresult OpenAlternativeOutputStream( const nsACString& type, int64_t predictedSize, nsIAsyncOutputStream** _retval); // Callbacks for each asynchronous tasks required in AsyncOpen // procedure, will call InvokeAsyncOpen when all the expected // tasks is finished successfully or when any failure happened. // @see mAsyncOpenBarrier. void TryInvokeAsyncOpen(nsresult aRv); void InvokeAsyncOpen(nsresult rv); void InvokeEarlyHintPreloader(nsresult rv, uint64_t aEarlyHintPreloaderId); // Calls SendSetPriority if mIPCClosed is false. void DoSendSetPriority(int16_t aValue); // Callback while background channel is ready. void OnBackgroundParentReady(HttpBackgroundChannelParent* aBgParent); // Callback while background channel is destroyed. void OnBackgroundParentDestroyed(); base::ProcessId OtherPid() const; // Inform the child actor that our referrer info was modified late during // BeginConnect. void OverrideReferrerInfoDuringBeginConnect(nsIReferrerInfo* aReferrerInfo); // Set the cookie string, which will be informed to the child actor during // PHttpBackgroundChannel::OnStartRequest. Note that CookieService also sends // the information to all actors via PContent, a main thread IPC, which could // be slower than background IPC PHttpBackgroundChannel::OnStartRequest. // Therefore, another cookie notification via PBackground is needed to // guarantee the listener in child has the necessary cookies before // OnStartRequest. void SetCookie(nsCString&& aCookie); using ChildEndpointPromise = MozPromise, bool, true>; [[nodiscard]] RefPtr AttachStreamFilter( Endpoint&& aParentEndpoint, Endpoint&& aChildEndpoint); [[nodiscard]] RefPtr DetachStreamFilters(); // Should only be called from EarlyHintPreloader. mChannel should be null at // the point of calling. Sets mChannel to aChannel. Used by the // EarlyHintPreloader to redirect the channel to this parent as soon as the // final channel becomes available after all http redirects. void SetHttpChannelFromEarlyHintPreloader(HttpBaseChannel* aChannel); protected: // used to connect redirected-to channel in parent with just created // ChildChannel. Used during redirects. [[nodiscard]] bool ConnectChannel(const uint32_t& registrarId); [[nodiscard]] bool DoAsyncOpen( nsIURI* uri, nsIURI* originalUri, nsIURI* docUri, nsIReferrerInfo* aReferrerInfo, nsIURI* aAPIRedirectToURI, nsIURI* topWindowUri, const uint32_t& loadFlags, const RequestHeaderTuples& requestHeaders, const nsCString& requestMethod, const Maybe& uploadStream, const bool& uploadStreamHasHeaders, const int16_t& priority, const ClassOfService& classOfService, const uint8_t& redirectionLimit, const bool& allowSTS, const uint32_t& thirdPartyFlags, const bool& doResumeAt, const uint64_t& startPos, const nsCString& entityID, const bool& allowSpdy, const bool& allowHttp3, const bool& allowAltSvc, const bool& beConservative, const bool& bypassProxy, const uint32_t& tlsFlags, const LoadInfoArgs& aLoadInfoArgs, const uint32_t& aCacheKey, const uint64_t& aRequestContextID, const Maybe& aCorsPreflightArgs, const uint32_t& aInitialRwin, const bool& aBlockAuthPrompt, const bool& aAllowStaleCacheContent, const bool& aPreferCacheLoadOverBypass, const nsCString& aContentTypeHint, const dom::RequestMode& aRequestMode, const uint32_t& aRedirectMode, const uint64_t& aChannelId, const nsString& aIntegrityMetadata, const uint64_t& aContentWindowId, const nsTArray& aPreferredAlternativeTypes, const uint64_t& aBrowserId, const TimeStamp& aLaunchServiceWorkerStart, const TimeStamp& aLaunchServiceWorkerEnd, const TimeStamp& aDispatchFetchEventStart, const TimeStamp& aDispatchFetchEventEnd, const TimeStamp& aHandleFetchEventStart, const TimeStamp& aHandleFetchEventEnd, const bool& aForceMainDocumentChannel, const TimeStamp& aNavigationStartTimeStamp, const uint64_t& aEarlyHintPreloaderId, const nsAString& aClassicScriptHintCharset, const nsAString& aDocumentCharacterSet, const bool& aIsUserAgentHeaderModified); virtual mozilla::ipc::IPCResult RecvSetPriority( const int16_t& priority) override; virtual mozilla::ipc::IPCResult RecvSetClassOfService( const ClassOfService& cos) override; virtual mozilla::ipc::IPCResult RecvSuspend() override; virtual mozilla::ipc::IPCResult RecvResume() override; virtual mozilla::ipc::IPCResult RecvCancel( const nsresult& status, const uint32_t& requestBlockingReason, const nsACString& reason, const mozilla::Maybe& logString) override; virtual mozilla::ipc::IPCResult RecvRedirect2Verify( const nsresult& result, const RequestHeaderTuples& changedHeaders, const uint32_t& aSourceRequestBlockingReason, const Maybe& aTargetLoadInfoForwarder, const uint32_t& loadFlags, nsIReferrerInfo* aReferrerInfo, nsIURI* apiRedirectUri, const Maybe& aCorsPreflightArgs) override; virtual mozilla::ipc::IPCResult RecvDocumentChannelCleanup( const bool& clearCacheEntry) override; virtual mozilla::ipc::IPCResult RecvRemoveCorsPreflightCacheEntry( nsIURI* uri, const mozilla::ipc::PrincipalInfo& requestingPrincipal, const OriginAttributes& originAttributes) override; virtual mozilla::ipc::IPCResult RecvSetCookies( const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes, nsIURI* aHost, const bool& aFromHttp, nsTArray&& aCookies) override; virtual mozilla::ipc::IPCResult RecvBytesRead(const int32_t& aCount) override; virtual mozilla::ipc::IPCResult RecvOpenOriginalCacheInputStream() override; virtual void ActorDestroy(ActorDestroyReason why) override; friend class ParentChannelListener; RefPtr mBrowserParent; [[nodiscard]] nsresult ReportSecurityMessage( const nsAString& aMessageTag, const nsAString& aMessageCategory) override; nsresult LogBlockedCORSRequest(const nsAString& aMessage, const nsACString& aCategory, bool aIsWarning = false) override; nsresult LogMimeTypeMismatch(const nsACString& aMessageName, bool aWarning, const nsAString& aURL, const nsAString& aContentType) override; // Calls SendDeleteSelf and sets mIPCClosed to true because we should not // send any more messages after that. Bug 1274886 [[nodiscard]] bool DoSendDeleteSelf(); // Called to notify the parent channel to not send any more IPC messages. virtual mozilla::ipc::IPCResult RecvDeletingChannel() override; private: already_AddRefed SecurityInfo(); // final step for Redirect2Verify procedure, will be invoked while both // redirecting and redirected channel are ready or any error happened. // OnRedirectVerifyCallback will be invoked for finishing the async // redirect verification procedure. void ContinueRedirect2Verify(const nsresult& aResult); void AsyncOpenFailed(nsresult aRv); // Request to pair with a HttpBackgroundChannelParent with the same channel // id, a promise will be returned so the caller can append callbacks on it. // If called multiple times before mBgParent is available, the same promise // will be returned and the callbacks will be invoked in order. [[nodiscard]] RefPtr WaitForBgParent( uint64_t aChannelId); // Remove the association with background channel after main-thread IPC // is about to be destroyed or no further event is going to be sent, i.e., // DocumentChannelCleanup. void CleanupBackgroundChannel(); // Check if the channel needs to enable the flow control on the IPC channel. // That is, we may suspend the channel if the ODA-s to child process are not // consumed quickly enough. Otherwise, memory explosion could happen. bool NeedFlowControl(); bool IsRedirectDueToAuthRetry(uint32_t redirectFlags); int32_t mSendWindowSize; friend class HttpBackgroundChannelParent; uint64_t mEarlyHintPreloaderId{}; RefPtr mChannel; nsCOMPtr mCacheEntry; nsCOMPtr mRedirectChannel; nsCOMPtr mRedirectCallback; nsCOMPtr mLoadContext; RefPtr mHttpHandler; RefPtr mParentListener; RefPtr mEventQ; RefPtr mBgParent; MozPromiseHolder mPromise; MozPromiseRequestHolder mRequest; // To calculate the delay caused by the e10s back-pressure suspension TimeStamp mResumedTimestamp; Atomic mIPCClosed; // PHttpChannel actor has been Closed() // Corresponding redirect channel registrar Id. 0 means redirection is not // started. uint64_t mRedirectChannelId = 0; PBOverrideStatus mPBOverride; // Set to the canceled status value if the main channel was canceled. nsresult mStatus; // The referrer info, set during nsHttpChannel::BeginConnect, to override the // original one. This info will be sent in OnStartRequest. nsCOMPtr mOverrideReferrerInfo; // The cookie string in Set-Cookie header. This info will be sent in // OnStartRequest. nsCString mCookie; // OnStatus is always called before OnProgress. // Set true in OnStatus if next OnProgress can be ignored // since the information can be recontructed from ODA. uint8_t mIgnoreProgress : 1; uint8_t mHasSuspendedByBackPressure : 1; // Set if we get the result of and cache |mNeedFlowControl| uint8_t mCacheNeedFlowControlInitialized : 1; uint8_t mNeedFlowControl : 1; uint8_t mSuspendedForFlowControl : 1; // Defaults to false. Is set to true at the begining of OnStartRequest. // Used to ensure methods can't be called before OnStartRequest. uint8_t mAfterOnStartRequestBegun : 1; // Number of events to wait before actually invoking AsyncOpen on the main // channel. For each asynchronous step required before InvokeAsyncOpen, should // increase 1 to mAsyncOpenBarrier and invoke TryInvokeAsyncOpen after // finished. This attribute is main thread only. uint8_t mAsyncOpenBarrier = 0; // When true, ODAs are sent from the socket process to the child process // directly. uint8_t mDataSentToChildProcess : 1; }; NS_DEFINE_STATIC_IID_ACCESSOR(HttpChannelParent, HTTP_CHANNEL_PARENT_IID) } // namespace net } // namespace mozilla #endif // mozilla_net_HttpChannelParent_h