diff options
Diffstat (limited to 'netwerk/protocol/http/HttpChannelChild.h')
-rw-r--r-- | netwerk/protocol/http/HttpChannelChild.h | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h new file mode 100644 index 0000000000..edd209a9f1 --- /dev/null +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -0,0 +1,390 @@ +/* -*- 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_HttpChannelChild_h +#define mozilla_net_HttpChannelChild_h + +#include "mozilla/UniquePtr.h" +#include "mozilla/net/HttpBaseChannel.h" +#include "mozilla/net/PHttpChannelChild.h" +#include "mozilla/net/ChannelEventQueue.h" + +#include "nsIStreamListener.h" +#include "nsILoadGroup.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIProgressEventSink.h" +#include "nsICacheInfoChannel.h" +#include "nsIApplicationCache.h" +#include "nsIApplicationCacheChannel.h" +#include "nsIUploadChannel2.h" +#include "nsIResumableChannel.h" +#include "nsIProxiedChannel.h" +#include "nsIAsyncVerifyRedirectCallback.h" +#include "nsIAssociatedContentSecurity.h" +#include "nsIChildChannel.h" +#include "nsIHttpChannelChild.h" +#include "nsIDivertableChannel.h" +#include "mozilla/net/DNS.h" + +class nsInputStreamPump; + +namespace mozilla { +namespace net { + +class InterceptedChannelContent; +class InterceptStreamListener; + +class HttpChannelChild final : public PHttpChannelChild + , public HttpBaseChannel + , public HttpAsyncAborter<HttpChannelChild> + , public nsICacheInfoChannel + , public nsIProxiedChannel + , public nsIApplicationCacheChannel + , public nsIAsyncVerifyRedirectCallback + , public nsIAssociatedContentSecurity + , public nsIChildChannel + , public nsIHttpChannelChild + , public nsIDivertableChannel +{ + virtual ~HttpChannelChild(); +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSICACHEINFOCHANNEL + NS_DECL_NSIPROXIEDCHANNEL + NS_DECL_NSIAPPLICATIONCACHECONTAINER + NS_DECL_NSIAPPLICATIONCACHECHANNEL + NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK + NS_DECL_NSIASSOCIATEDCONTENTSECURITY + NS_DECL_NSICHILDCHANNEL + NS_DECL_NSIHTTPCHANNELCHILD + NS_DECL_NSIDIVERTABLECHANNEL + + HttpChannelChild(); + + // Methods HttpBaseChannel didn't implement for us or that we override. + // + // nsIRequest + NS_IMETHOD Cancel(nsresult status) override; + NS_IMETHOD Suspend() override; + NS_IMETHOD Resume() override; + // nsIChannel + NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo) override; + NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) override; + NS_IMETHOD AsyncOpen2(nsIStreamListener *aListener) override; + + // HttpBaseChannel::nsIHttpChannel + NS_IMETHOD SetRequestHeader(const nsACString& aHeader, + const nsACString& aValue, + bool aMerge) override; + NS_IMETHOD SetEmptyRequestHeader(const nsACString& aHeader) override; + NS_IMETHOD RedirectTo(nsIURI *newURI) override; + NS_IMETHOD GetProtocolVersion(nsACString& aProtocolVersion) override; + // nsIHttpChannelInternal + NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey) override; + NS_IMETHOD ForceIntercepted(uint64_t aInterceptionID) override; + // nsISupportsPriority + NS_IMETHOD SetPriority(int32_t value) override; + // nsIClassOfService + NS_IMETHOD SetClassFlags(uint32_t inFlags) override; + NS_IMETHOD AddClassFlags(uint32_t inFlags) override; + NS_IMETHOD ClearClassFlags(uint32_t inFlags) override; + // nsIResumableChannel + NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID) override; + + // IPDL holds a reference while the PHttpChannel protocol is live (starting at + // AsyncOpen, and ending at either OnStopRequest or any IPDL error, either of + // which call NeckoChild::DeallocPHttpChannelChild()). + void AddIPDLReference(); + void ReleaseIPDLReference(); + + bool IsSuspended(); + + bool RecvNotifyTrackingProtectionDisabled() override; + void FlushedForDiversion(); + +protected: + bool RecvOnStartRequest(const nsresult& channelStatus, + const nsHttpResponseHead& responseHead, + const bool& useResponseHead, + const nsHttpHeaderArray& requestHeaders, + const bool& isFromCache, + const bool& cacheEntryAvailable, + const uint32_t& cacheExpirationTime, + const nsCString& cachedCharset, + const nsCString& securityInfoSerialization, + const NetAddr& selfAddr, + const NetAddr& peerAddr, + const int16_t& redirectCount, + const uint32_t& cacheKey, + const nsCString& altDataType) override; + bool RecvOnTransportAndData(const nsresult& channelStatus, + const nsresult& status, + const uint64_t& progress, + const uint64_t& progressMax, + const uint64_t& offset, + const uint32_t& count, + const nsCString& data) override; + bool RecvOnStopRequest(const nsresult& statusCode, const ResourceTimingStruct& timing) override; + bool RecvOnProgress(const int64_t& progress, const int64_t& progressMax) override; + bool RecvOnStatus(const nsresult& status) override; + bool RecvFailedAsyncOpen(const nsresult& status) override; + bool RecvRedirect1Begin(const uint32_t& registrarId, + const URIParams& newURI, + const uint32_t& redirectFlags, + const nsHttpResponseHead& responseHead, + const nsCString& securityInfoSerialization, + const nsCString& channelId) override; + bool RecvRedirect3Complete() override; + bool RecvAssociateApplicationCache(const nsCString& groupID, + const nsCString& clientID) override; + bool RecvFlushedForDiversion() override; + bool RecvDivertMessages() override; + bool RecvDeleteSelf() override; + bool RecvFinishInterceptedRedirect() override; + + bool RecvReportSecurityMessage(const nsString& messageTag, + const nsString& messageCategory) override; + + bool RecvIssueDeprecationWarning(const uint32_t& warning, + const bool& asError) override; + + bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr); + virtual void DoNotifyListenerCleanup() override; + + NS_IMETHOD GetResponseSynthesized(bool* aSynthesized) override; + +private: + + class OverrideRunnable : public Runnable { + public: + OverrideRunnable(HttpChannelChild* aChannel, + HttpChannelChild* aNewChannel, + InterceptStreamListener* aListener, + nsIInputStream* aInput, + nsAutoPtr<nsHttpResponseHead>& aHead); + + NS_IMETHOD Run() override; + void OverrideWithSynthesizedResponse(); + private: + RefPtr<HttpChannelChild> mChannel; + RefPtr<HttpChannelChild> mNewChannel; + RefPtr<InterceptStreamListener> mListener; + nsCOMPtr<nsIInputStream> mInput; + nsAutoPtr<nsHttpResponseHead> mHead; + }; + + nsresult ContinueAsyncOpen(); + + void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext); + void DoOnStatus(nsIRequest* aRequest, nsresult status); + void DoOnProgress(nsIRequest* aRequest, int64_t progress, int64_t progressMax); + void DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream, + uint64_t offset, uint32_t count); + void DoPreOnStopRequest(nsresult aStatus); + void DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus, nsISupports* aContext); + + bool ShouldInterceptURI(nsIURI* aURI, bool& aShouldUpgrade); + + // Discard the prior interception and continue with the original network request. + void ResetInterception(); + + // Override this channel's pending response with a synthesized one. The content will be + // asynchronously read from the pump. + void OverrideWithSynthesizedResponse(nsAutoPtr<nsHttpResponseHead>& aResponseHead, + nsIInputStream* aSynthesizedInput, + InterceptStreamListener* aStreamListener); + + void ForceIntercepted(nsIInputStream* aSynthesizedInput); + + RequestHeaderTuples mClientSetRequestHeaders; + nsCOMPtr<nsIChildChannel> mRedirectChannelChild; + RefPtr<InterceptStreamListener> mInterceptListener; + RefPtr<nsInputStreamPump> mSynthesizedResponsePump; + nsCOMPtr<nsIInputStream> mSynthesizedInput; + int64_t mSynthesizedStreamLength; + + bool mIsFromCache; + bool mCacheEntryAvailable; + uint32_t mCacheExpirationTime; + nsCString mCachedCharset; + nsCOMPtr<nsISupports> mCacheKey; + + nsCString mProtocolVersion; + + // If ResumeAt is called before AsyncOpen, we need to send extra data upstream + bool mSendResumeAt; + + bool mIPCOpen; + bool mKeptAlive; // IPC kept open, but only for security info + RefPtr<ChannelEventQueue> mEventQ; + + // If nsUnknownDecoder is involved OnStartRequest call will be delayed and + // this queue keeps OnDataAvailable data until OnStartRequest is finally + // called. + nsTArray<UniquePtr<ChannelEvent>> mUnknownDecoderEventQ; + bool mUnknownDecoderInvolved; + + // Once set, OnData and possibly OnStop will be diverted to the parent. + bool mDivertingToParent; + // Once set, no OnStart/OnData/OnStop callbacks should be received from the + // parent channel, nor dequeued from the ChannelEventQueue. + bool mFlushedForDiversion; + // Set if SendSuspend is called. Determines if SendResume is needed when + // diverting callbacks to parent. + bool mSuspendSent; + + // Set if a response was synthesized, indicating that any forthcoming redirects + // should be intercepted. + bool mSynthesizedResponse; + + // Set if a synthesized response should cause us to explictly allows intercepting + // an expected forthcoming redirect. + bool mShouldInterceptSubsequentRedirect; + // Set if a redirection is being initiated to facilitate providing a synthesized + // response to a channel using a different principal than the current one. + bool mRedirectingForSubsequentSynthesizedResponse; + + // Set if a manual redirect mode channel needs to be intercepted in the + // parent. + bool mPostRedirectChannelShouldIntercept; + // Set if a manual redirect mode channel needs to be upgraded to a secure URI + // when it's being considered for interception. Can only be true if + // mPostRedirectChannelShouldIntercept is true. + bool mPostRedirectChannelShouldUpgrade; + + // Set if the corresponding parent channel should force an interception to occur + // before the network transaction is initiated. + bool mShouldParentIntercept; + + // Set if the corresponding parent channel should suspend after a response + // is synthesized. + bool mSuspendParentAfterSynthesizeResponse; + + // Needed to call AsyncOpen in FinishInterceptedRedirect + nsCOMPtr<nsIStreamListener> mInterceptedRedirectListener; + nsCOMPtr<nsISupports> mInterceptedRedirectContext; + // Needed to call CleanupRedirectingChannel in FinishInterceptedRedirect + RefPtr<HttpChannelChild> mInterceptingChannel; + // Used to call OverrideWithSynthesizedResponse in FinishInterceptedRedirect + RefPtr<OverrideRunnable> mOverrideRunnable; + + void FinishInterceptedRedirect(); + void CleanupRedirectingChannel(nsresult rv); + + // true after successful AsyncOpen until OnStopRequest completes. + bool RemoteChannelExists() { return mIPCOpen && !mKeptAlive; } + + void AssociateApplicationCache(const nsCString &groupID, + const nsCString &clientID); + void OnStartRequest(const nsresult& channelStatus, + const nsHttpResponseHead& responseHead, + const bool& useResponseHead, + const nsHttpHeaderArray& requestHeaders, + const bool& isFromCache, + const bool& cacheEntryAvailable, + const uint32_t& cacheExpirationTime, + const nsCString& cachedCharset, + const nsCString& securityInfoSerialization, + const NetAddr& selfAddr, + const NetAddr& peerAddr, + const uint32_t& cacheKey, + const nsCString& altDataType); + void MaybeDivertOnData(const nsCString& data, + const uint64_t& offset, + const uint32_t& count); + void OnTransportAndData(const nsresult& channelStatus, + const nsresult& status, + const uint64_t progress, + const uint64_t& progressMax, + const uint64_t& offset, + const uint32_t& count, + const nsCString& data); + void OnStopRequest(const nsresult& channelStatus, const ResourceTimingStruct& timing); + void MaybeDivertOnStop(const nsresult& aChannelStatus); + void OnProgress(const int64_t& progress, const int64_t& progressMax); + void OnStatus(const nsresult& status); + void FailedAsyncOpen(const nsresult& status); + void HandleAsyncAbort(); + void Redirect1Begin(const uint32_t& registrarId, + const URIParams& newUri, + const uint32_t& redirectFlags, + const nsHttpResponseHead& responseHead, + const nsACString& securityInfoSerialization, + const nsACString& channelId); + bool Redirect3Complete(OverrideRunnable* aRunnable); + void DeleteSelf(); + + // Create a a new channel to be used in a redirection, based on the provided + // response headers. + nsresult SetupRedirect(nsIURI* uri, + const nsHttpResponseHead* responseHead, + const uint32_t& redirectFlags, + nsIChannel** outChannel); + + // Perform a redirection without communicating with the parent process at all. + void BeginNonIPCRedirect(nsIURI* responseURI, + const nsHttpResponseHead* responseHead); + + // Override the default security info pointer during a non-IPC redirection. + void OverrideSecurityInfoForNonIPCRedirect(nsISupports* securityInfo); + + friend class AssociateApplicationCacheEvent; + friend class StartRequestEvent; + friend class StopRequestEvent; + friend class TransportAndDataEvent; + friend class MaybeDivertOnDataHttpEvent; + friend class MaybeDivertOnStopHttpEvent; + friend class ProgressEvent; + friend class StatusEvent; + friend class FailedAsyncOpenEvent; + friend class Redirect1Event; + friend class Redirect3Event; + friend class DeleteSelfEvent; + friend class HttpAsyncAborter<HttpChannelChild>; + friend class InterceptStreamListener; + friend class InterceptedChannelContent; +}; + +// A stream listener interposed between the nsInputStreamPump used for intercepted channels +// and this channel's original listener. This is only used to ensure the original listener +// sees the channel as the request object, and to synthesize OnStatus and OnProgress notifications. +class InterceptStreamListener : public nsIStreamListener + , public nsIProgressEventSink +{ + RefPtr<HttpChannelChild> mOwner; + nsCOMPtr<nsISupports> mContext; + virtual ~InterceptStreamListener() {} + public: + InterceptStreamListener(HttpChannelChild* aOwner, nsISupports* aContext) + : mOwner(aOwner) + , mContext(aContext) + { + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIPROGRESSEVENTSINK + + void Cleanup(); +}; + +//----------------------------------------------------------------------------- +// inline functions +//----------------------------------------------------------------------------- + +inline bool +HttpChannelChild::IsSuspended() +{ + return mSuspendCount != 0; +} + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_HttpChannelChild_h |