/* -*- 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 "ADivertableParentChannel.h" #include "nsHttp.h" #include "mozilla/net/PHttpChannelParent.h" #include "mozilla/net/NeckoCommon.h" #include "mozilla/net/NeckoParent.h" #include "mozilla/MozPromise.h" #include "nsIObserver.h" #include "nsIParentRedirectingChannel.h" #include "nsIProgressEventSink.h" #include "nsHttpChannel.h" #include "nsIAuthPromptProvider.h" #include "mozilla/dom/ipc/IdType.h" #include "nsIDeprecationWarner.h" class nsICacheEntry; class nsIAssociatedContentSecurity; #define HTTP_CHANNEL_PARENT_IID \ { 0x982b2372, 0x7aa5, 0x4e8a, \ { 0xbd, 0x9f, 0x89, 0x74, 0xd7, 0xf0, 0x58, 0xeb } } namespace mozilla { namespace dom{ class TabParent; class PBrowserOrId; } // namespace dom namespace net { class HttpBackgroundChannelParent; class HttpChannelParentListener; class ChannelEventQueue; // Note: nsIInterfaceRequestor must be the first base so that do_QueryObject() // works correctly on this object, as it's needed to compute a void* pointing to // the beginning of this object. class HttpChannelParent final : public nsIInterfaceRequestor , public PHttpChannelParent , public nsIParentRedirectingChannel , public nsIProgressEventSink , public ADivertableParentChannel , public nsIAuthPromptProvider , public nsIDeprecationWarner , public HttpChannelSecurityWarningReporter , public nsIAsyncVerifyRedirectReadyCallback { 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_NSIAUTHPROMPTPROVIDER NS_DECL_NSIDEPRECATIONWARNER NS_DECL_NSIASYNCVERIFYREDIRECTREADYCALLBACK NS_DECLARE_STATIC_IID_ACCESSOR(HTTP_CHANNEL_PARENT_IID) HttpChannelParent(const dom::PBrowserOrId& iframeEmbedding, nsILoadContext* aLoadContext, PBOverrideStatus aStatus); MOZ_MUST_USE bool Init(const HttpChannelCreationArgs& aOpenArgs); // ADivertableParentChannel functions. void DivertTo(nsIStreamListener *aListener) override; MOZ_MUST_USE nsresult SuspendForDiversion() override; MOZ_MUST_USE nsresult SuspendMessageDiversion() override; MOZ_MUST_USE nsresult ResumeMessageDiversion() override; MOZ_MUST_USE nsresult CancelDiversion() override; // Calls OnStartRequest for "DivertTo" listener, then notifies child channel // that it should divert OnDataAvailable and OnStopRequest calls to this // parent channel. void StartDiversion(); // Handles calling OnStart/Stop if there are errors during diversion. // Called asynchronously from FailDiversion. void NotifyDiversionFailed(nsresult aErrorCode); // Forwarded to nsHttpChannel::SetApplyConversion. void SetApplyConversion(bool aApplyConversion) { if (mChannel) { mChannel->SetApplyConversion(aApplyConversion); } } MOZ_MUST_USE nsresult OpenAlternativeOutputStream(const nsACString & type, nsIOutputStream * *_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); // 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 override; protected: // used to connect redirected-to channel in parent with just created // ChildChannel. Used during redirects. MOZ_MUST_USE bool ConnectChannel(const uint32_t& channelId, const bool& shouldIntercept); MOZ_MUST_USE bool DoAsyncOpen(const URIParams& uri, const OptionalURIParams& originalUri, const OptionalURIParams& docUri, const OptionalURIParams& referrerUri, const uint32_t& referrerPolicy, const OptionalURIParams& internalRedirectUri, const OptionalURIParams& topWindowUri, const uint32_t& loadFlags, const RequestHeaderTuples& requestHeaders, const nsCString& requestMethod, const OptionalIPCStream& uploadStream, const bool& uploadStreamHasHeaders, const int16_t& priority, const uint32_t& classOfService, const uint8_t& redirectionLimit, const bool& allowSTS, const uint32_t& thirdPartyFlags, const bool& doResumeAt, const uint64_t& startPos, const nsCString& entityID, const bool& chooseApplicationCache, const nsCString& appCacheClientID, const bool& allowSpdy, const bool& allowAltSvc, const bool& beConservative, const uint32_t& tlsFlags, const OptionalLoadInfoArgs& aLoadInfoArgs, const OptionalHttpResponseHead& aSynthesizedResponseHead, const nsCString& aSecurityInfoSerialization, const uint32_t& aCacheKey, const uint64_t& aRequestContextID, const OptionalCorsPreflightArgs& aCorsPreflightArgs, const uint32_t& aInitialRwin, const bool& aBlockAuthPrompt, const bool& aSuspendAfterSynthesizeResponse, const bool& aAllowStaleCacheContent, const nsCString& aContentTypeHint, const uint32_t& aCorsMode, const uint32_t& aRedirectMode, const uint64_t& aChannelId, const uint64_t& aContentWindowId, const nsCString& aPreferredAlternativeType, const uint64_t& aTopLevelOuterContentWindowId, const TimeStamp& aLaunchServiceWorkerStart, const TimeStamp& aLaunchServiceWorkerEnd, const TimeStamp& aDispatchFetchEventStart, const TimeStamp& aDispatchFetchEventEnd, const TimeStamp& aHandleFetchEventStart, const TimeStamp& aHandleFetchEventEnd, const bool& aForceMainDocumentChannel); virtual mozilla::ipc::IPCResult RecvSetPriority(const int16_t& priority) override; virtual mozilla::ipc::IPCResult RecvSetClassOfService(const uint32_t& cos) override; virtual mozilla::ipc::IPCResult RecvSetCacheTokenCachedCharset(const nsCString& charset) override; virtual mozilla::ipc::IPCResult RecvSuspend() override; virtual mozilla::ipc::IPCResult RecvResume() override; virtual mozilla::ipc::IPCResult RecvCancel(const nsresult& status) override; virtual mozilla::ipc::IPCResult RecvRedirect2Verify(const nsresult& result, const RequestHeaderTuples& changedHeaders, const uint32_t& loadFlags, const uint32_t& referrerPolicy, const OptionalURIParams& aReferrerURI, const OptionalURIParams& apiRedirectUri, const OptionalCorsPreflightArgs& aCorsPreflightArgs, const bool& aChooseAppcache) override; virtual mozilla::ipc::IPCResult RecvUpdateAssociatedContentSecurity(const int32_t& broken, const int32_t& no) override; virtual mozilla::ipc::IPCResult RecvDocumentChannelCleanup(const bool& clearCacheEntry) override; virtual mozilla::ipc::IPCResult RecvMarkOfflineCacheEntryAsForeign() override; virtual mozilla::ipc::IPCResult RecvDivertOnDataAvailable(const nsCString& data, const uint64_t& offset, const uint32_t& count) override; virtual mozilla::ipc::IPCResult RecvDivertOnStopRequest(const nsresult& statusCode) override; virtual mozilla::ipc::IPCResult RecvDivertComplete() override; virtual mozilla::ipc::IPCResult RecvRemoveCorsPreflightCacheEntry(const URIParams& uri, const mozilla::ipc::PrincipalInfo& requestingPrincipal) override; virtual void ActorDestroy(ActorDestroyReason why) override; // Supporting function for ADivertableParentChannel. MOZ_MUST_USE nsresult ResumeForDiversion(); // Asynchronously calls NotifyDiversionFailed. void FailDiversion(nsresult aErrorCode); friend class HttpChannelParentListener; RefPtr mTabParent; MOZ_MUST_USE nsresult ReportSecurityMessage(const nsAString& aMessageTag, const nsAString& aMessageCategory) override; nsresult LogBlockedCORSRequest(const nsAString& aMessage) override; // Calls SendDeleteSelf and sets mIPCClosed to true because we should not // send any more messages after that. Bug 1274886 MOZ_MUST_USE bool DoSendDeleteSelf(); // Called to notify the parent channel to not send any more IPC messages. virtual mozilla::ipc::IPCResult RecvDeletingChannel() override; virtual mozilla::ipc::IPCResult RecvFinishInterceptedRedirect() override; private: void UpdateAndSerializeSecurityInfo(nsACString& aSerializedSecurityInfoOut); void DivertOnDataAvailable(const nsCString& data, const uint64_t& offset, const uint32_t& count); void DivertOnStopRequest(const nsresult& statusCode); void DivertComplete(); void MaybeFlushPendingDiversion(); void ResponseSynthesized(); // 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. already_AddRefed WaitForBgParent(); // 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(); friend class HttpBackgroundChannelParent; friend class DivertDataAvailableEvent; friend class DivertStopRequestEvent; friend class DivertCompleteEvent; RefPtr mChannel; nsCOMPtr mCacheEntry; nsCOMPtr mAssociatedContentSecurity; Atomic mIPCClosed; // PHttpChannel actor has been Closed() nsCOMPtr mRedirectChannel; nsCOMPtr mRedirectCallback; nsAutoPtr mOfflineForeignMarker; // OnStatus is always called before OnProgress. // Set true in OnStatus if next OnProgress can be ignored // since the information can be recontructed from ODA. bool mIgnoreProgress : 1; bool mSentRedirect1BeginFailed : 1; bool mReceivedRedirect2Verify : 1; PBOverrideStatus mPBOverride; nsCOMPtr mLoadContext; RefPtr mHttpHandler; RefPtr mParentListener; // The listener we are diverting to or will divert to if mPendingDiversion // is set. nsCOMPtr mDivertListener; // Set to the canceled status value if the main channel was canceled. nsresult mStatus; // Indicates that diversion has been requested, but we could not start it // yet because the channel is still being opened with a synthesized response. bool mPendingDiversion; // Once set, no OnStart/OnData/OnStop calls should be accepted; conversely, it // must be set when RecvDivertOnData/~DivertOnStop/~DivertComplete are // received from the child channel. bool mDivertingFromChild; // Set if OnStart|StopRequest was called during a diversion from the child. bool mDivertedOnStartRequest; bool mSuspendedForDiversion; // Set if this channel should be suspended after synthesizing a response. bool mSuspendAfterSynthesizeResponse; // Set if this channel will synthesize its response. bool mWillSynthesizeResponse; dom::TabId mNestedFrameId; RefPtr mEventQ; RefPtr mBgParent; // 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; // Corresponding redirect channel registrar Id. 0 means redirection is not started. uint32_t mRedirectRegistrarId = 0; MozPromiseHolder mPromise; MozPromiseRequestHolder mRequest; }; NS_DEFINE_STATIC_IID_ACCESSOR(HttpChannelParent, HTTP_CHANNEL_PARENT_IID) } // namespace net } // namespace mozilla #endif // mozilla_net_HttpChannelParent_h