nsBaseChannel.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef nsBaseChannel_h__
  6. #define nsBaseChannel_h__
  7. #include "nsString.h"
  8. #include "nsAutoPtr.h"
  9. #include "nsCOMPtr.h"
  10. #include "nsHashPropertyBag.h"
  11. #include "nsInputStreamPump.h"
  12. #include "nsIChannel.h"
  13. #include "nsIURI.h"
  14. #include "nsILoadGroup.h"
  15. #include "nsILoadInfo.h"
  16. #include "nsIStreamListener.h"
  17. #include "nsIInterfaceRequestor.h"
  18. #include "nsIProgressEventSink.h"
  19. #include "nsITransport.h"
  20. #include "nsIAsyncVerifyRedirectCallback.h"
  21. #include "nsIThreadRetargetableRequest.h"
  22. #include "nsIThreadRetargetableStreamListener.h"
  23. #include "PrivateBrowsingChannel.h"
  24. #include "nsThreadUtils.h"
  25. class nsIInputStream;
  26. //-----------------------------------------------------------------------------
  27. // nsBaseChannel is designed to be subclassed. The subclass is responsible for
  28. // implementing the OpenContentStream method, which will be called by the
  29. // nsIChannel::AsyncOpen and nsIChannel::Open implementations.
  30. //
  31. // nsBaseChannel implements nsIInterfaceRequestor to provide a convenient way
  32. // for subclasses to query both the nsIChannel::notificationCallbacks and
  33. // nsILoadGroup::notificationCallbacks for supported interfaces.
  34. //
  35. // nsBaseChannel implements nsITransportEventSink to support progress & status
  36. // notifications generated by the transport layer.
  37. class nsBaseChannel : public nsHashPropertyBag
  38. , public nsIChannel
  39. , public nsIThreadRetargetableRequest
  40. , public nsIInterfaceRequestor
  41. , public nsITransportEventSink
  42. , public nsIAsyncVerifyRedirectCallback
  43. , public mozilla::net::PrivateBrowsingChannel<nsBaseChannel>
  44. , protected nsIStreamListener
  45. , protected nsIThreadRetargetableStreamListener
  46. {
  47. public:
  48. NS_DECL_ISUPPORTS_INHERITED
  49. NS_DECL_NSIREQUEST
  50. NS_DECL_NSICHANNEL
  51. NS_DECL_NSIINTERFACEREQUESTOR
  52. NS_DECL_NSITRANSPORTEVENTSINK
  53. NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
  54. NS_DECL_NSITHREADRETARGETABLEREQUEST
  55. NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
  56. nsBaseChannel();
  57. // This method must be called to initialize the basechannel instance.
  58. nsresult Init() {
  59. return NS_OK;
  60. }
  61. protected:
  62. // -----------------------------------------------
  63. // Methods to be implemented by the derived class:
  64. virtual ~nsBaseChannel();
  65. private:
  66. // Implemented by subclass to supply data stream. The parameter, async, is
  67. // true when called from nsIChannel::AsyncOpen and false otherwise. When
  68. // async is true, the resulting stream will be used with a nsIInputStreamPump
  69. // instance. This means that if it is a non-blocking stream that supports
  70. // nsIAsyncInputStream that it will be read entirely on the main application
  71. // thread, and its AsyncWait method will be called whenever ReadSegments
  72. // returns NS_BASE_STREAM_WOULD_BLOCK. Otherwise, if the stream is blocking,
  73. // then it will be read on one of the background I/O threads, and it does not
  74. // need to implement ReadSegments. If async is false, this method may return
  75. // NS_ERROR_NOT_IMPLEMENTED to cause the basechannel to implement Open in
  76. // terms of AsyncOpen (see NS_ImplementChannelOpen).
  77. // A callee is allowed to return an nsIChannel instead of an nsIInputStream.
  78. // That case will be treated as a redirect to the new channel. By default
  79. // *channel will be set to null by the caller, so callees who don't want to
  80. // return one an just not touch it.
  81. virtual nsresult OpenContentStream(bool async, nsIInputStream **stream,
  82. nsIChannel** channel) = 0;
  83. // The basechannel calls this method from its OnTransportStatus method to
  84. // determine whether to call nsIProgressEventSink::OnStatus in addition to
  85. // nsIProgressEventSink::OnProgress. This method may be overriden by the
  86. // subclass to enable nsIProgressEventSink::OnStatus events. If this method
  87. // returns true, then the statusArg out param specifies the "statusArg" value
  88. // to pass to the OnStatus method. By default, OnStatus messages are
  89. // suppressed. The status parameter passed to this method is the status value
  90. // from the OnTransportStatus method.
  91. virtual bool GetStatusArg(nsresult status, nsString &statusArg) {
  92. return false;
  93. }
  94. // Called when the callbacks available to this channel may have changed.
  95. virtual void OnCallbacksChanged() {
  96. }
  97. // Called when our channel is done, to allow subclasses to drop resources.
  98. virtual void OnChannelDone() {
  99. }
  100. public:
  101. // ----------------------------------------------
  102. // Methods provided for use by the derived class:
  103. // Redirect to another channel. This method takes care of notifying
  104. // observers of this redirect as well as of opening the new channel, if asked
  105. // to do so. It also cancels |this| with the status code
  106. // NS_BINDING_REDIRECTED. A failure return from this method means that the
  107. // redirect could not be performed (no channel was opened; this channel
  108. // wasn't canceled.) The redirectFlags parameter consists of the flag values
  109. // defined on nsIChannelEventSink.
  110. nsresult Redirect(nsIChannel *newChannel, uint32_t redirectFlags,
  111. bool openNewChannel);
  112. // Tests whether a type hint was set. Subclasses can use this to decide
  113. // whether to call SetContentType.
  114. // NOTE: This is only reliable if the subclass didn't itself call
  115. // SetContentType, and should also not be called after OpenContentStream.
  116. bool HasContentTypeHint() const;
  117. // The URI member should be initialized before the channel is used, and then
  118. // it should never be changed again until the channel is destroyed.
  119. nsIURI *URI() {
  120. return mURI;
  121. }
  122. void SetURI(nsIURI *uri) {
  123. NS_ASSERTION(uri, "must specify a non-null URI");
  124. NS_ASSERTION(!mURI, "must not modify URI");
  125. NS_ASSERTION(!mOriginalURI, "how did that get set so early?");
  126. mURI = uri;
  127. mOriginalURI = uri;
  128. }
  129. nsIURI *OriginalURI() {
  130. return mOriginalURI;
  131. }
  132. // The security info is a property of the transport-layer, which should be
  133. // assigned by the subclass.
  134. nsISupports *SecurityInfo() {
  135. return mSecurityInfo;
  136. }
  137. void SetSecurityInfo(nsISupports *info) {
  138. mSecurityInfo = info;
  139. }
  140. // Test the load flags
  141. bool HasLoadFlag(uint32_t flag) {
  142. return (mLoadFlags & flag) != 0;
  143. }
  144. // This is a short-cut to calling nsIRequest::IsPending()
  145. virtual bool Pending() const {
  146. return mPump || mWaitingOnAsyncRedirect;
  147. }
  148. // Helper function for querying the channel's notification callbacks.
  149. template <class T> void GetCallback(nsCOMPtr<T> &result) {
  150. GetInterface(NS_GET_TEMPLATE_IID(T), getter_AddRefs(result));
  151. }
  152. // Helper function for calling QueryInterface on this.
  153. nsQueryInterface do_QueryInterface() {
  154. return nsQueryInterface(static_cast<nsIChannel *>(this));
  155. }
  156. // MSVC needs this:
  157. nsQueryInterface do_QueryInterface(nsISupports *obj) {
  158. return nsQueryInterface(obj);
  159. }
  160. // If a subclass does not want to feed transport-layer progress events to the
  161. // base channel via nsITransportEventSink, then it may set this flag to cause
  162. // the base channel to synthesize progress events when it receives data from
  163. // the content stream. By default, progress events are not synthesized.
  164. void EnableSynthesizedProgressEvents(bool enable) {
  165. mSynthProgressEvents = enable;
  166. }
  167. // Some subclasses may wish to manually insert a stream listener between this
  168. // and the channel's listener. The following methods make that possible.
  169. void SetStreamListener(nsIStreamListener *listener) {
  170. mListener = listener;
  171. }
  172. nsIStreamListener *StreamListener() {
  173. return mListener;
  174. }
  175. // Pushes a new stream converter in front of the channel's stream listener.
  176. // The fromType and toType values are passed to nsIStreamConverterService's
  177. // AsyncConvertData method. If invalidatesContentLength is true, then the
  178. // channel's content-length property will be assigned a value of -1. This is
  179. // necessary when the converter changes the length of the resulting data
  180. // stream, which is almost always the case for a "stream converter" ;-)
  181. // This function optionally returns a reference to the new converter.
  182. nsresult PushStreamConverter(const char *fromType, const char *toType,
  183. bool invalidatesContentLength = true,
  184. nsIStreamListener **converter = nullptr);
  185. protected:
  186. void DisallowThreadRetargeting() {
  187. mAllowThreadRetargeting = false;
  188. }
  189. private:
  190. NS_DECL_NSISTREAMLISTENER
  191. NS_DECL_NSIREQUESTOBSERVER
  192. // Called to setup mPump and call AsyncRead on it.
  193. nsresult BeginPumpingData();
  194. // Called when the callbacks available to this channel may have changed.
  195. void CallbacksChanged() {
  196. mProgressSink = nullptr;
  197. mQueriedProgressSink = false;
  198. OnCallbacksChanged();
  199. }
  200. // Called when our channel is done. This should drop no-longer-needed pointers.
  201. void ChannelDone() {
  202. mListener = nullptr;
  203. mListenerContext = nullptr;
  204. OnChannelDone();
  205. }
  206. // Handle an async redirect callback. This will only be called if we
  207. // returned success from AsyncOpen while posting a redirect runnable.
  208. void HandleAsyncRedirect(nsIChannel* newChannel);
  209. void ContinueHandleAsyncRedirect(nsresult result);
  210. nsresult ContinueRedirect();
  211. // start URI classifier if requested
  212. void ClassifyURI();
  213. class RedirectRunnable : public mozilla::Runnable
  214. {
  215. public:
  216. RedirectRunnable(nsBaseChannel* chan, nsIChannel* newChannel)
  217. : mChannel(chan), mNewChannel(newChannel)
  218. {
  219. NS_PRECONDITION(newChannel, "Must have channel to redirect to");
  220. }
  221. NS_IMETHOD Run() override
  222. {
  223. mChannel->HandleAsyncRedirect(mNewChannel);
  224. return NS_OK;
  225. }
  226. private:
  227. RefPtr<nsBaseChannel> mChannel;
  228. nsCOMPtr<nsIChannel> mNewChannel;
  229. };
  230. friend class RedirectRunnable;
  231. RefPtr<nsInputStreamPump> mPump;
  232. nsCOMPtr<nsIProgressEventSink> mProgressSink;
  233. nsCOMPtr<nsIURI> mOriginalURI;
  234. nsCOMPtr<nsISupports> mOwner;
  235. nsCOMPtr<nsISupports> mSecurityInfo;
  236. nsCOMPtr<nsIChannel> mRedirectChannel;
  237. nsCString mContentType;
  238. nsCString mContentCharset;
  239. uint32_t mLoadFlags;
  240. bool mQueriedProgressSink;
  241. bool mSynthProgressEvents;
  242. bool mAllowThreadRetargeting;
  243. bool mWaitingOnAsyncRedirect;
  244. bool mOpenRedirectChannel;
  245. uint32_t mRedirectFlags;
  246. protected:
  247. nsCOMPtr<nsIURI> mURI;
  248. nsCOMPtr<nsILoadGroup> mLoadGroup;
  249. nsCOMPtr<nsILoadInfo> mLoadInfo;
  250. nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
  251. nsCOMPtr<nsIStreamListener> mListener;
  252. nsCOMPtr<nsISupports> mListenerContext;
  253. nsresult mStatus;
  254. uint32_t mContentDispositionHint;
  255. nsAutoPtr<nsString> mContentDispositionFilename;
  256. int64_t mContentLength;
  257. bool mWasOpened;
  258. friend class mozilla::net::PrivateBrowsingChannel<nsBaseChannel>;
  259. };
  260. #endif // !nsBaseChannel_h__