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