Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim: set sw=2 ts=8 et tw=80 : */ |
michael@0 | 3 | |
michael@0 | 4 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 7 | |
michael@0 | 8 | #ifndef mozilla_net_HttpBaseChannel_h |
michael@0 | 9 | #define mozilla_net_HttpBaseChannel_h |
michael@0 | 10 | |
michael@0 | 11 | #include "nsHttp.h" |
michael@0 | 12 | #include "nsAutoPtr.h" |
michael@0 | 13 | #include "nsHashPropertyBag.h" |
michael@0 | 14 | #include "nsProxyInfo.h" |
michael@0 | 15 | #include "nsHttpRequestHead.h" |
michael@0 | 16 | #include "nsHttpResponseHead.h" |
michael@0 | 17 | #include "nsHttpConnectionInfo.h" |
michael@0 | 18 | #include "nsIEncodedChannel.h" |
michael@0 | 19 | #include "nsIHttpChannel.h" |
michael@0 | 20 | #include "nsHttpHandler.h" |
michael@0 | 21 | #include "nsIHttpChannelInternal.h" |
michael@0 | 22 | #include "nsIUploadChannel.h" |
michael@0 | 23 | #include "nsIUploadChannel2.h" |
michael@0 | 24 | #include "nsIProgressEventSink.h" |
michael@0 | 25 | #include "nsIURI.h" |
michael@0 | 26 | #include "nsIEffectiveTLDService.h" |
michael@0 | 27 | #include "nsIStringEnumerator.h" |
michael@0 | 28 | #include "nsISupportsPriority.h" |
michael@0 | 29 | #include "nsIApplicationCache.h" |
michael@0 | 30 | #include "nsIResumableChannel.h" |
michael@0 | 31 | #include "nsITraceableChannel.h" |
michael@0 | 32 | #include "nsILoadContext.h" |
michael@0 | 33 | #include "mozilla/net/NeckoCommon.h" |
michael@0 | 34 | #include "nsThreadUtils.h" |
michael@0 | 35 | #include "PrivateBrowsingChannel.h" |
michael@0 | 36 | #include "mozilla/net/DNS.h" |
michael@0 | 37 | #include "nsITimedChannel.h" |
michael@0 | 38 | #include "nsISecurityConsoleMessage.h" |
michael@0 | 39 | |
michael@0 | 40 | extern PRLogModuleInfo *gHttpLog; |
michael@0 | 41 | |
michael@0 | 42 | namespace mozilla { |
michael@0 | 43 | namespace net { |
michael@0 | 44 | |
michael@0 | 45 | /* |
michael@0 | 46 | * This class is a partial implementation of nsIHttpChannel. It contains code |
michael@0 | 47 | * shared by nsHttpChannel and HttpChannelChild. |
michael@0 | 48 | * - Note that this class has nothing to do with nsBaseChannel, which is an |
michael@0 | 49 | * earlier effort at a base class for channels that somehow never made it all |
michael@0 | 50 | * the way to the HTTP channel. |
michael@0 | 51 | */ |
michael@0 | 52 | class HttpBaseChannel : public nsHashPropertyBag |
michael@0 | 53 | , public nsIEncodedChannel |
michael@0 | 54 | , public nsIHttpChannel |
michael@0 | 55 | , public nsIHttpChannelInternal |
michael@0 | 56 | , public nsIUploadChannel |
michael@0 | 57 | , public nsIUploadChannel2 |
michael@0 | 58 | , public nsISupportsPriority |
michael@0 | 59 | , public nsIResumableChannel |
michael@0 | 60 | , public nsITraceableChannel |
michael@0 | 61 | , public PrivateBrowsingChannel<HttpBaseChannel> |
michael@0 | 62 | , public nsITimedChannel |
michael@0 | 63 | { |
michael@0 | 64 | public: |
michael@0 | 65 | NS_DECL_ISUPPORTS_INHERITED |
michael@0 | 66 | NS_DECL_NSIUPLOADCHANNEL |
michael@0 | 67 | NS_DECL_NSIUPLOADCHANNEL2 |
michael@0 | 68 | NS_DECL_NSITRACEABLECHANNEL |
michael@0 | 69 | NS_DECL_NSITIMEDCHANNEL |
michael@0 | 70 | |
michael@0 | 71 | HttpBaseChannel(); |
michael@0 | 72 | virtual ~HttpBaseChannel(); |
michael@0 | 73 | |
michael@0 | 74 | virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo, |
michael@0 | 75 | uint32_t aProxyResolveFlags, |
michael@0 | 76 | nsIURI *aProxyURI); |
michael@0 | 77 | |
michael@0 | 78 | // nsIRequest |
michael@0 | 79 | NS_IMETHOD GetName(nsACString& aName); |
michael@0 | 80 | NS_IMETHOD IsPending(bool *aIsPending); |
michael@0 | 81 | NS_IMETHOD GetStatus(nsresult *aStatus); |
michael@0 | 82 | NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup); |
michael@0 | 83 | NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup); |
michael@0 | 84 | NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags); |
michael@0 | 85 | NS_IMETHOD SetLoadFlags(nsLoadFlags aLoadFlags); |
michael@0 | 86 | |
michael@0 | 87 | // nsIChannel |
michael@0 | 88 | NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI); |
michael@0 | 89 | NS_IMETHOD SetOriginalURI(nsIURI *aOriginalURI); |
michael@0 | 90 | NS_IMETHOD GetURI(nsIURI **aURI); |
michael@0 | 91 | NS_IMETHOD GetOwner(nsISupports **aOwner); |
michael@0 | 92 | NS_IMETHOD SetOwner(nsISupports *aOwner); |
michael@0 | 93 | NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks); |
michael@0 | 94 | NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks); |
michael@0 | 95 | NS_IMETHOD GetContentType(nsACString& aContentType); |
michael@0 | 96 | NS_IMETHOD SetContentType(const nsACString& aContentType); |
michael@0 | 97 | NS_IMETHOD GetContentCharset(nsACString& aContentCharset); |
michael@0 | 98 | NS_IMETHOD SetContentCharset(const nsACString& aContentCharset); |
michael@0 | 99 | NS_IMETHOD GetContentDisposition(uint32_t *aContentDisposition); |
michael@0 | 100 | NS_IMETHOD SetContentDisposition(uint32_t aContentDisposition); |
michael@0 | 101 | NS_IMETHOD GetContentDispositionFilename(nsAString& aContentDispositionFilename); |
michael@0 | 102 | NS_IMETHOD SetContentDispositionFilename(const nsAString& aContentDispositionFilename); |
michael@0 | 103 | NS_IMETHOD GetContentDispositionHeader(nsACString& aContentDispositionHeader); |
michael@0 | 104 | NS_IMETHOD GetContentLength(int64_t *aContentLength); |
michael@0 | 105 | NS_IMETHOD SetContentLength(int64_t aContentLength); |
michael@0 | 106 | NS_IMETHOD Open(nsIInputStream **aResult); |
michael@0 | 107 | |
michael@0 | 108 | // nsIEncodedChannel |
michael@0 | 109 | NS_IMETHOD GetApplyConversion(bool *value); |
michael@0 | 110 | NS_IMETHOD SetApplyConversion(bool value); |
michael@0 | 111 | NS_IMETHOD GetContentEncodings(nsIUTF8StringEnumerator** aEncodings); |
michael@0 | 112 | |
michael@0 | 113 | // HttpBaseChannel::nsIHttpChannel |
michael@0 | 114 | NS_IMETHOD GetRequestMethod(nsACString& aMethod); |
michael@0 | 115 | NS_IMETHOD SetRequestMethod(const nsACString& aMethod); |
michael@0 | 116 | NS_IMETHOD GetReferrer(nsIURI **referrer); |
michael@0 | 117 | NS_IMETHOD SetReferrer(nsIURI *referrer); |
michael@0 | 118 | NS_IMETHOD GetProxyURI(nsIURI **proxyURI); |
michael@0 | 119 | NS_IMETHOD GetRequestHeader(const nsACString& aHeader, nsACString& aValue); |
michael@0 | 120 | NS_IMETHOD SetRequestHeader(const nsACString& aHeader, |
michael@0 | 121 | const nsACString& aValue, bool aMerge); |
michael@0 | 122 | NS_IMETHOD VisitRequestHeaders(nsIHttpHeaderVisitor *visitor); |
michael@0 | 123 | NS_IMETHOD GetResponseHeader(const nsACString &header, nsACString &value); |
michael@0 | 124 | NS_IMETHOD SetResponseHeader(const nsACString& header, |
michael@0 | 125 | const nsACString& value, bool merge); |
michael@0 | 126 | NS_IMETHOD VisitResponseHeaders(nsIHttpHeaderVisitor *visitor); |
michael@0 | 127 | NS_IMETHOD GetAllowPipelining(bool *value); |
michael@0 | 128 | NS_IMETHOD SetAllowPipelining(bool value); |
michael@0 | 129 | NS_IMETHOD GetRedirectionLimit(uint32_t *value); |
michael@0 | 130 | NS_IMETHOD SetRedirectionLimit(uint32_t value); |
michael@0 | 131 | NS_IMETHOD IsNoStoreResponse(bool *value); |
michael@0 | 132 | NS_IMETHOD IsNoCacheResponse(bool *value); |
michael@0 | 133 | NS_IMETHOD GetResponseStatus(uint32_t *aValue); |
michael@0 | 134 | NS_IMETHOD GetResponseStatusText(nsACString& aValue); |
michael@0 | 135 | NS_IMETHOD GetRequestSucceeded(bool *aValue); |
michael@0 | 136 | NS_IMETHOD RedirectTo(nsIURI *newURI); |
michael@0 | 137 | |
michael@0 | 138 | // nsIHttpChannelInternal |
michael@0 | 139 | NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI); |
michael@0 | 140 | NS_IMETHOD SetDocumentURI(nsIURI *aDocumentURI); |
michael@0 | 141 | NS_IMETHOD GetRequestVersion(uint32_t *major, uint32_t *minor); |
michael@0 | 142 | NS_IMETHOD GetResponseVersion(uint32_t *major, uint32_t *minor); |
michael@0 | 143 | NS_IMETHOD SetCookie(const char *aCookieHeader); |
michael@0 | 144 | NS_IMETHOD GetForceAllowThirdPartyCookie(bool *aForce); |
michael@0 | 145 | NS_IMETHOD SetForceAllowThirdPartyCookie(bool aForce); |
michael@0 | 146 | NS_IMETHOD GetCanceled(bool *aCanceled); |
michael@0 | 147 | NS_IMETHOD GetChannelIsForDownload(bool *aChannelIsForDownload); |
michael@0 | 148 | NS_IMETHOD SetChannelIsForDownload(bool aChannelIsForDownload); |
michael@0 | 149 | NS_IMETHOD SetCacheKeysRedirectChain(nsTArray<nsCString> *cacheKeys); |
michael@0 | 150 | NS_IMETHOD GetLocalAddress(nsACString& addr); |
michael@0 | 151 | NS_IMETHOD GetLocalPort(int32_t* port); |
michael@0 | 152 | NS_IMETHOD GetRemoteAddress(nsACString& addr); |
michael@0 | 153 | NS_IMETHOD GetRemotePort(int32_t* port); |
michael@0 | 154 | NS_IMETHOD GetAllowSpdy(bool *aAllowSpdy); |
michael@0 | 155 | NS_IMETHOD SetAllowSpdy(bool aAllowSpdy); |
michael@0 | 156 | NS_IMETHOD GetLoadAsBlocking(bool *aLoadAsBlocking); |
michael@0 | 157 | NS_IMETHOD SetLoadAsBlocking(bool aLoadAsBlocking); |
michael@0 | 158 | NS_IMETHOD GetLoadUnblocked(bool *aLoadUnblocked); |
michael@0 | 159 | NS_IMETHOD SetLoadUnblocked(bool aLoadUnblocked); |
michael@0 | 160 | NS_IMETHOD GetApiRedirectToURI(nsIURI * *aApiRedirectToURI); |
michael@0 | 161 | NS_IMETHOD AddSecurityMessage(const nsAString &aMessageTag, const nsAString &aMessageCategory); |
michael@0 | 162 | NS_IMETHOD TakeAllSecurityMessages(nsCOMArray<nsISecurityConsoleMessage> &aMessages); |
michael@0 | 163 | NS_IMETHOD GetResponseTimeoutEnabled(bool *aEnable); |
michael@0 | 164 | NS_IMETHOD SetResponseTimeoutEnabled(bool aEnable); |
michael@0 | 165 | |
michael@0 | 166 | inline void CleanRedirectCacheChainIfNecessary() |
michael@0 | 167 | { |
michael@0 | 168 | mRedirectedCachekeys = nullptr; |
michael@0 | 169 | } |
michael@0 | 170 | NS_IMETHOD HTTPUpgrade(const nsACString & aProtocolName, |
michael@0 | 171 | nsIHttpUpgradeListener *aListener); |
michael@0 | 172 | |
michael@0 | 173 | // nsISupportsPriority |
michael@0 | 174 | NS_IMETHOD GetPriority(int32_t *value); |
michael@0 | 175 | NS_IMETHOD AdjustPriority(int32_t delta); |
michael@0 | 176 | |
michael@0 | 177 | // nsIResumableChannel |
michael@0 | 178 | NS_IMETHOD GetEntityID(nsACString& aEntityID); |
michael@0 | 179 | |
michael@0 | 180 | class nsContentEncodings : public nsIUTF8StringEnumerator |
michael@0 | 181 | { |
michael@0 | 182 | public: |
michael@0 | 183 | NS_DECL_ISUPPORTS |
michael@0 | 184 | NS_DECL_NSIUTF8STRINGENUMERATOR |
michael@0 | 185 | |
michael@0 | 186 | nsContentEncodings(nsIHttpChannel* aChannel, const char* aEncodingHeader); |
michael@0 | 187 | virtual ~nsContentEncodings(); |
michael@0 | 188 | |
michael@0 | 189 | private: |
michael@0 | 190 | nsresult PrepareForNext(void); |
michael@0 | 191 | |
michael@0 | 192 | // We do not own the buffer. The channel owns it. |
michael@0 | 193 | const char* mEncodingHeader; |
michael@0 | 194 | const char* mCurStart; // points to start of current header |
michael@0 | 195 | const char* mCurEnd; // points to end of current header |
michael@0 | 196 | |
michael@0 | 197 | // Hold a ref to our channel so that it can't go away and take the |
michael@0 | 198 | // header with it. |
michael@0 | 199 | nsCOMPtr<nsIHttpChannel> mChannel; |
michael@0 | 200 | |
michael@0 | 201 | bool mReady; |
michael@0 | 202 | }; |
michael@0 | 203 | |
michael@0 | 204 | nsHttpResponseHead * GetResponseHead() const { return mResponseHead; } |
michael@0 | 205 | nsHttpRequestHead * GetRequestHead() { return &mRequestHead; } |
michael@0 | 206 | |
michael@0 | 207 | const NetAddr& GetSelfAddr() { return mSelfAddr; } |
michael@0 | 208 | const NetAddr& GetPeerAddr() { return mPeerAddr; } |
michael@0 | 209 | |
michael@0 | 210 | public: /* Necko internal use only... */ |
michael@0 | 211 | |
michael@0 | 212 | |
michael@0 | 213 | // Return whether upon a redirect code of httpStatus for method, the |
michael@0 | 214 | // request method should be rewritten to GET. |
michael@0 | 215 | static bool ShouldRewriteRedirectToGET(uint32_t httpStatus, |
michael@0 | 216 | nsHttpRequestHead::ParsedMethodType method); |
michael@0 | 217 | |
michael@0 | 218 | protected: |
michael@0 | 219 | nsCOMArray<nsISecurityConsoleMessage> mSecurityConsoleMessages; |
michael@0 | 220 | |
michael@0 | 221 | // Handle notifying listener, removing from loadgroup if request failed. |
michael@0 | 222 | void DoNotifyListener(); |
michael@0 | 223 | virtual void DoNotifyListenerCleanup() = 0; |
michael@0 | 224 | |
michael@0 | 225 | // drop reference to listener, its callbacks, and the progress sink |
michael@0 | 226 | void ReleaseListeners(); |
michael@0 | 227 | |
michael@0 | 228 | nsresult ApplyContentConversions(); |
michael@0 | 229 | |
michael@0 | 230 | void AddCookiesToRequest(); |
michael@0 | 231 | virtual nsresult SetupReplacementChannel(nsIURI *, |
michael@0 | 232 | nsIChannel *, |
michael@0 | 233 | bool preserveMethod); |
michael@0 | 234 | |
michael@0 | 235 | // bundle calling OMR observers and marking flag into one function |
michael@0 | 236 | inline void CallOnModifyRequestObservers() { |
michael@0 | 237 | gHttpHandler->OnModifyRequest(this); |
michael@0 | 238 | mRequestObserversCalled = true; |
michael@0 | 239 | } |
michael@0 | 240 | |
michael@0 | 241 | // Helper function to simplify getting notification callbacks. |
michael@0 | 242 | template <class T> |
michael@0 | 243 | void GetCallback(nsCOMPtr<T> &aResult) |
michael@0 | 244 | { |
michael@0 | 245 | NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, |
michael@0 | 246 | NS_GET_TEMPLATE_IID(T), |
michael@0 | 247 | getter_AddRefs(aResult)); |
michael@0 | 248 | } |
michael@0 | 249 | |
michael@0 | 250 | // Redirect tracking |
michael@0 | 251 | // Checks whether or not aURI and mOriginalURI share the same domain. |
michael@0 | 252 | bool SameOriginWithOriginalUri(nsIURI *aURI); |
michael@0 | 253 | |
michael@0 | 254 | friend class PrivateBrowsingChannel<HttpBaseChannel>; |
michael@0 | 255 | |
michael@0 | 256 | nsCOMPtr<nsIURI> mURI; |
michael@0 | 257 | nsCOMPtr<nsIURI> mOriginalURI; |
michael@0 | 258 | nsCOMPtr<nsIURI> mDocumentURI; |
michael@0 | 259 | nsCOMPtr<nsIStreamListener> mListener; |
michael@0 | 260 | nsCOMPtr<nsISupports> mListenerContext; |
michael@0 | 261 | nsCOMPtr<nsILoadGroup> mLoadGroup; |
michael@0 | 262 | nsCOMPtr<nsISupports> mOwner; |
michael@0 | 263 | nsCOMPtr<nsIInterfaceRequestor> mCallbacks; |
michael@0 | 264 | nsCOMPtr<nsIProgressEventSink> mProgressSink; |
michael@0 | 265 | nsCOMPtr<nsIURI> mReferrer; |
michael@0 | 266 | nsCOMPtr<nsIApplicationCache> mApplicationCache; |
michael@0 | 267 | |
michael@0 | 268 | nsHttpRequestHead mRequestHead; |
michael@0 | 269 | nsCOMPtr<nsIInputStream> mUploadStream; |
michael@0 | 270 | nsAutoPtr<nsHttpResponseHead> mResponseHead; |
michael@0 | 271 | nsRefPtr<nsHttpConnectionInfo> mConnectionInfo; |
michael@0 | 272 | nsCOMPtr<nsIProxyInfo> mProxyInfo; |
michael@0 | 273 | |
michael@0 | 274 | nsCString mSpec; // ASCII encoded URL spec |
michael@0 | 275 | nsCString mContentTypeHint; |
michael@0 | 276 | nsCString mContentCharsetHint; |
michael@0 | 277 | nsCString mUserSetCookieHeader; |
michael@0 | 278 | |
michael@0 | 279 | NetAddr mSelfAddr; |
michael@0 | 280 | NetAddr mPeerAddr; |
michael@0 | 281 | |
michael@0 | 282 | // HTTP Upgrade Data |
michael@0 | 283 | nsCString mUpgradeProtocol; |
michael@0 | 284 | nsCOMPtr<nsIHttpUpgradeListener> mUpgradeProtocolCallback; |
michael@0 | 285 | |
michael@0 | 286 | // Resumable channel specific data |
michael@0 | 287 | nsCString mEntityID; |
michael@0 | 288 | uint64_t mStartPos; |
michael@0 | 289 | |
michael@0 | 290 | nsresult mStatus; |
michael@0 | 291 | uint32_t mLoadFlags; |
michael@0 | 292 | uint32_t mCaps; |
michael@0 | 293 | int16_t mPriority; |
michael@0 | 294 | uint8_t mRedirectionLimit; |
michael@0 | 295 | |
michael@0 | 296 | uint32_t mApplyConversion : 1; |
michael@0 | 297 | uint32_t mCanceled : 1; |
michael@0 | 298 | uint32_t mIsPending : 1; |
michael@0 | 299 | uint32_t mWasOpened : 1; |
michael@0 | 300 | // if 1 all "http-on-{opening|modify|etc}-request" observers have been called |
michael@0 | 301 | uint32_t mRequestObserversCalled : 1; |
michael@0 | 302 | uint32_t mResponseHeadersModified : 1; |
michael@0 | 303 | uint32_t mAllowPipelining : 1; |
michael@0 | 304 | uint32_t mForceAllowThirdPartyCookie : 1; |
michael@0 | 305 | uint32_t mUploadStreamHasHeaders : 1; |
michael@0 | 306 | uint32_t mInheritApplicationCache : 1; |
michael@0 | 307 | uint32_t mChooseApplicationCache : 1; |
michael@0 | 308 | uint32_t mLoadedFromApplicationCache : 1; |
michael@0 | 309 | uint32_t mChannelIsForDownload : 1; |
michael@0 | 310 | uint32_t mTracingEnabled : 1; |
michael@0 | 311 | // True if timing collection is enabled |
michael@0 | 312 | uint32_t mTimingEnabled : 1; |
michael@0 | 313 | uint32_t mAllowSpdy : 1; |
michael@0 | 314 | uint32_t mLoadAsBlocking : 1; |
michael@0 | 315 | uint32_t mLoadUnblocked : 1; |
michael@0 | 316 | uint32_t mResponseTimeoutEnabled : 1; |
michael@0 | 317 | // A flag that should be false only if a cross-domain redirect occurred |
michael@0 | 318 | uint32_t mAllRedirectsSameOrigin : 1; |
michael@0 | 319 | |
michael@0 | 320 | // Current suspension depth for this channel object |
michael@0 | 321 | uint32_t mSuspendCount; |
michael@0 | 322 | |
michael@0 | 323 | nsCOMPtr<nsIURI> mAPIRedirectToURI; |
michael@0 | 324 | nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys; |
michael@0 | 325 | |
michael@0 | 326 | uint32_t mProxyResolveFlags; |
michael@0 | 327 | nsCOMPtr<nsIURI> mProxyURI; |
michael@0 | 328 | |
michael@0 | 329 | uint32_t mContentDispositionHint; |
michael@0 | 330 | nsAutoPtr<nsString> mContentDispositionFilename; |
michael@0 | 331 | |
michael@0 | 332 | nsRefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive |
michael@0 | 333 | |
michael@0 | 334 | // Performance tracking |
michael@0 | 335 | // The initiator type (for this resource) - how was the resource referenced in |
michael@0 | 336 | // the HTML file. |
michael@0 | 337 | nsString mInitiatorType; |
michael@0 | 338 | // Number of redirects that has occurred. |
michael@0 | 339 | int16_t mRedirectCount; |
michael@0 | 340 | // A time value equal to the starting time of the fetch that initiates the |
michael@0 | 341 | // redirect. |
michael@0 | 342 | mozilla::TimeStamp mRedirectStartTimeStamp; |
michael@0 | 343 | // A time value equal to the time immediately after receiving the last byte of |
michael@0 | 344 | // the response of the last redirect. |
michael@0 | 345 | mozilla::TimeStamp mRedirectEndTimeStamp; |
michael@0 | 346 | |
michael@0 | 347 | PRTime mChannelCreationTime; |
michael@0 | 348 | TimeStamp mChannelCreationTimestamp; |
michael@0 | 349 | TimeStamp mAsyncOpenTime; |
michael@0 | 350 | TimeStamp mCacheReadStart; |
michael@0 | 351 | TimeStamp mCacheReadEnd; |
michael@0 | 352 | // copied from the transaction before we null out mTransaction |
michael@0 | 353 | // so that the timing can still be queried from OnStopRequest |
michael@0 | 354 | TimingStruct mTransactionTimings; |
michael@0 | 355 | }; |
michael@0 | 356 | |
michael@0 | 357 | // Share some code while working around C++'s absurd inability to handle casting |
michael@0 | 358 | // of member functions between base/derived types. |
michael@0 | 359 | // - We want to store member function pointer to call at resume time, but one |
michael@0 | 360 | // such function--HandleAsyncAbort--we want to share between the |
michael@0 | 361 | // nsHttpChannel/HttpChannelChild. Can't define it in base class, because |
michael@0 | 362 | // then we'd have to cast member function ptr between base/derived class |
michael@0 | 363 | // types. Sigh... |
michael@0 | 364 | template <class T> |
michael@0 | 365 | class HttpAsyncAborter |
michael@0 | 366 | { |
michael@0 | 367 | public: |
michael@0 | 368 | HttpAsyncAborter(T *derived) : mThis(derived), mCallOnResume(0) {} |
michael@0 | 369 | |
michael@0 | 370 | // Aborts channel: calls OnStart/Stop with provided status, removes channel |
michael@0 | 371 | // from loadGroup. |
michael@0 | 372 | nsresult AsyncAbort(nsresult status); |
michael@0 | 373 | |
michael@0 | 374 | // Does most the actual work. |
michael@0 | 375 | void HandleAsyncAbort(); |
michael@0 | 376 | |
michael@0 | 377 | // AsyncCall calls a member function asynchronously (via an event). |
michael@0 | 378 | // retval isn't refcounted and is set only when event was successfully |
michael@0 | 379 | // posted, the event is returned for the purpose of cancelling when needed |
michael@0 | 380 | nsresult AsyncCall(void (T::*funcPtr)(), |
michael@0 | 381 | nsRunnableMethod<T> **retval = nullptr); |
michael@0 | 382 | private: |
michael@0 | 383 | T *mThis; |
michael@0 | 384 | |
michael@0 | 385 | protected: |
michael@0 | 386 | // Function to be called at resume time |
michael@0 | 387 | void (T::* mCallOnResume)(void); |
michael@0 | 388 | }; |
michael@0 | 389 | |
michael@0 | 390 | template <class T> |
michael@0 | 391 | nsresult HttpAsyncAborter<T>::AsyncAbort(nsresult status) |
michael@0 | 392 | { |
michael@0 | 393 | PR_LOG(gHttpLog, 4, |
michael@0 | 394 | ("HttpAsyncAborter::AsyncAbort [this=%p status=%x]\n", mThis, status)); |
michael@0 | 395 | |
michael@0 | 396 | mThis->mStatus = status; |
michael@0 | 397 | mThis->mIsPending = false; |
michael@0 | 398 | |
michael@0 | 399 | // if this fails? Callers ignore our return value anyway.... |
michael@0 | 400 | return AsyncCall(&T::HandleAsyncAbort); |
michael@0 | 401 | } |
michael@0 | 402 | |
michael@0 | 403 | // Each subclass needs to define its own version of this (which just calls this |
michael@0 | 404 | // base version), else we wind up casting base/derived member function ptrs |
michael@0 | 405 | template <class T> |
michael@0 | 406 | inline void HttpAsyncAborter<T>::HandleAsyncAbort() |
michael@0 | 407 | { |
michael@0 | 408 | NS_PRECONDITION(!mCallOnResume, "How did that happen?"); |
michael@0 | 409 | |
michael@0 | 410 | if (mThis->mSuspendCount) { |
michael@0 | 411 | PR_LOG(gHttpLog, 4, |
michael@0 | 412 | ("Waiting until resume to do async notification [this=%p]\n", mThis)); |
michael@0 | 413 | mCallOnResume = &T::HandleAsyncAbort; |
michael@0 | 414 | return; |
michael@0 | 415 | } |
michael@0 | 416 | |
michael@0 | 417 | mThis->DoNotifyListener(); |
michael@0 | 418 | |
michael@0 | 419 | // finally remove ourselves from the load group. |
michael@0 | 420 | if (mThis->mLoadGroup) |
michael@0 | 421 | mThis->mLoadGroup->RemoveRequest(mThis, nullptr, mThis->mStatus); |
michael@0 | 422 | } |
michael@0 | 423 | |
michael@0 | 424 | template <class T> |
michael@0 | 425 | nsresult HttpAsyncAborter<T>::AsyncCall(void (T::*funcPtr)(), |
michael@0 | 426 | nsRunnableMethod<T> **retval) |
michael@0 | 427 | { |
michael@0 | 428 | nsresult rv; |
michael@0 | 429 | |
michael@0 | 430 | nsRefPtr<nsRunnableMethod<T> > event = NS_NewRunnableMethod(mThis, funcPtr); |
michael@0 | 431 | rv = NS_DispatchToCurrentThread(event); |
michael@0 | 432 | if (NS_SUCCEEDED(rv) && retval) { |
michael@0 | 433 | *retval = event; |
michael@0 | 434 | } |
michael@0 | 435 | |
michael@0 | 436 | return rv; |
michael@0 | 437 | } |
michael@0 | 438 | |
michael@0 | 439 | } // namespace net |
michael@0 | 440 | } // namespace mozilla |
michael@0 | 441 | |
michael@0 | 442 | #endif // mozilla_net_HttpBaseChannel_h |