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: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set et cin ts=4 sw=4 sts=4: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef nsHttpChannel_h__
8 #define nsHttpChannel_h__
10 #include "HttpBaseChannel.h"
11 #include "nsTArray.h"
12 #include "nsICachingChannel.h"
13 #include "nsICacheEntry.h"
14 #include "nsICacheEntryOpenCallback.h"
15 #include "nsIDNSListener.h"
16 #include "nsIApplicationCacheChannel.h"
17 #include "nsIProtocolProxyCallback.h"
18 #include "nsIHttpAuthenticableChannel.h"
19 #include "nsIAsyncVerifyRedirectCallback.h"
20 #include "nsIThreadRetargetableRequest.h"
21 #include "nsIThreadRetargetableStreamListener.h"
22 #include "nsWeakReference.h"
23 #include "TimingStruct.h"
24 #include "AutoClose.h"
26 class nsIPrincipal;
27 class nsDNSPrefetch;
28 class nsICacheEntryDescriptor;
29 class nsICancelable;
30 class nsIHttpChannelAuthProvider;
31 class nsInputStreamPump;
32 class nsPerformance;
34 namespace mozilla { namespace net {
36 //-----------------------------------------------------------------------------
37 // nsHttpChannel
38 //-----------------------------------------------------------------------------
40 class nsHttpChannel : public HttpBaseChannel
41 , public HttpAsyncAborter<nsHttpChannel>
42 , public nsIStreamListener
43 , public nsICachingChannel
44 , public nsICacheEntryOpenCallback
45 , public nsITransportEventSink
46 , public nsIProtocolProxyCallback
47 , public nsIHttpAuthenticableChannel
48 , public nsIApplicationCacheChannel
49 , public nsIAsyncVerifyRedirectCallback
50 , public nsIThreadRetargetableRequest
51 , public nsIThreadRetargetableStreamListener
52 , public nsIDNSListener
53 , public nsSupportsWeakReference
54 {
55 public:
56 NS_DECL_ISUPPORTS_INHERITED
57 NS_DECL_NSIREQUESTOBSERVER
58 NS_DECL_NSISTREAMLISTENER
59 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
60 NS_DECL_NSICACHEINFOCHANNEL
61 NS_DECL_NSICACHINGCHANNEL
62 NS_DECL_NSICACHEENTRYOPENCALLBACK
63 NS_DECL_NSITRANSPORTEVENTSINK
64 NS_DECL_NSIPROTOCOLPROXYCALLBACK
65 NS_DECL_NSIPROXIEDCHANNEL
66 NS_DECL_NSIAPPLICATIONCACHECONTAINER
67 NS_DECL_NSIAPPLICATIONCACHECHANNEL
68 NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
69 NS_DECL_NSITHREADRETARGETABLEREQUEST
70 NS_DECL_NSIDNSLISTENER
72 // nsIHttpAuthenticableChannel. We can't use
73 // NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and
74 // others.
75 NS_IMETHOD GetIsSSL(bool *aIsSSL);
76 NS_IMETHOD GetProxyMethodIsConnect(bool *aProxyMethodIsConnect);
77 NS_IMETHOD GetServerResponseHeader(nsACString & aServerResponseHeader);
78 NS_IMETHOD GetProxyChallenges(nsACString & aChallenges);
79 NS_IMETHOD GetWWWChallenges(nsACString & aChallenges);
80 NS_IMETHOD SetProxyCredentials(const nsACString & aCredentials);
81 NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials);
82 NS_IMETHOD OnAuthAvailable();
83 NS_IMETHOD OnAuthCancelled(bool userCancel);
84 // Functions we implement from nsIHttpAuthenticableChannel but are
85 // declared in HttpBaseChannel must be implemented in this class. We
86 // just call the HttpBaseChannel:: impls.
87 NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags);
88 NS_IMETHOD GetURI(nsIURI **aURI);
89 NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks);
90 NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
91 NS_IMETHOD GetRequestMethod(nsACString& aMethod);
93 nsHttpChannel();
94 virtual ~nsHttpChannel();
96 virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
97 uint32_t aProxyResolveFlags,
98 nsIURI *aProxyURI);
100 // Methods HttpBaseChannel didn't implement for us or that we override.
101 //
102 // nsIRequest
103 NS_IMETHOD Cancel(nsresult status);
104 NS_IMETHOD Suspend();
105 NS_IMETHOD Resume();
106 NS_IMETHOD IsPending(bool *aIsPending);
107 // nsIChannel
108 NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
109 NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext);
110 // nsIHttpChannelInternal
111 NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey);
112 // nsISupportsPriority
113 NS_IMETHOD SetPriority(int32_t value);
114 // nsIResumableChannel
115 NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID);
117 NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks);
118 NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup);
119 // nsITimedChannel
120 NS_IMETHOD GetDomainLookupStart(mozilla::TimeStamp *aDomainLookupStart);
121 NS_IMETHOD GetDomainLookupEnd(mozilla::TimeStamp *aDomainLookupEnd);
122 NS_IMETHOD GetConnectStart(mozilla::TimeStamp *aConnectStart);
123 NS_IMETHOD GetConnectEnd(mozilla::TimeStamp *aConnectEnd);
124 NS_IMETHOD GetRequestStart(mozilla::TimeStamp *aRequestStart);
125 NS_IMETHOD GetResponseStart(mozilla::TimeStamp *aResponseStart);
126 NS_IMETHOD GetResponseEnd(mozilla::TimeStamp *aResponseEnd);
128 public: /* internal necko use only */
130 void InternalSetUploadStream(nsIInputStream *uploadStream)
131 { mUploadStream = uploadStream; }
132 void SetUploadStreamHasHeaders(bool hasHeaders)
133 { mUploadStreamHasHeaders = hasHeaders; }
135 nsresult SetReferrerInternal(nsIURI *referrer) {
136 nsAutoCString spec;
137 nsresult rv = referrer->GetAsciiSpec(spec);
138 if (NS_FAILED(rv)) return rv;
139 mReferrer = referrer;
140 mRequestHead.SetHeader(nsHttp::Referer, spec);
141 return NS_OK;
142 }
144 // This allows cache entry to be marked as foreign even after channel itself
145 // is gone. Needed for e10s (see HttpChannelParent::RecvDocumentChannelCleanup)
146 class OfflineCacheEntryAsForeignMarker {
147 nsCOMPtr<nsIApplicationCache> mApplicationCache;
148 nsCOMPtr<nsIURI> mCacheURI;
149 public:
150 OfflineCacheEntryAsForeignMarker(nsIApplicationCache* appCache,
151 nsIURI* aURI)
152 : mApplicationCache(appCache)
153 , mCacheURI(aURI)
154 {}
156 nsresult MarkAsForeign();
157 };
159 OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker();
161 // Helper to keep cache callbacks wait flags consistent
162 class AutoCacheWaitFlags
163 {
164 public:
165 AutoCacheWaitFlags(nsHttpChannel* channel)
166 : mChannel(channel)
167 , mKeep(0)
168 {
169 // Flags must be set before entering any AsyncOpenCacheEntry call.
170 mChannel->mCacheEntriesToWaitFor =
171 nsHttpChannel::WAIT_FOR_CACHE_ENTRY |
172 nsHttpChannel::WAIT_FOR_OFFLINE_CACHE_ENTRY;
173 }
175 void Keep(uint32_t flags)
176 {
177 // Called after successful call to appropriate AsyncOpenCacheEntry call.
178 mKeep |= flags;
179 }
181 ~AutoCacheWaitFlags()
182 {
183 // Keep only flags those are left to be wait for.
184 mChannel->mCacheEntriesToWaitFor &= mKeep;
185 }
187 private:
188 nsHttpChannel* mChannel;
189 uint32_t mKeep : 2;
190 };
192 void ForcePending(bool aForcePending);
194 private:
195 typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
197 bool RequestIsConditional();
198 nsresult BeginConnect();
199 nsresult Connect();
200 nsresult ContinueConnect();
201 void SpeculativeConnect();
202 nsresult SetupTransaction();
203 void SetupTransactionLoadGroupInfo();
204 nsresult CallOnStartRequest();
205 nsresult ProcessResponse();
206 nsresult ContinueProcessResponse(nsresult);
207 nsresult ProcessNormal();
208 nsresult ContinueProcessNormal(nsresult);
209 nsresult ProcessNotModified();
210 nsresult AsyncProcessRedirection(uint32_t httpStatus);
211 nsresult ContinueProcessRedirection(nsresult);
212 nsresult ContinueProcessRedirectionAfterFallback(nsresult);
213 nsresult ProcessFailedProxyConnect(uint32_t httpStatus);
214 nsresult ProcessFallback(bool *waitingForRedirectCallback);
215 nsresult ContinueProcessFallback(nsresult);
216 void HandleAsyncAbort();
217 nsresult EnsureAssocReq();
218 void ProcessSSLInformation();
219 bool IsHTTPS();
220 void RetrieveSSLOptions();
222 nsresult ContinueOnStartRequest1(nsresult);
223 nsresult ContinueOnStartRequest2(nsresult);
224 nsresult ContinueOnStartRequest3(nsresult);
226 // redirection specific methods
227 void HandleAsyncRedirect();
228 void HandleAsyncAPIRedirect();
229 nsresult ContinueHandleAsyncRedirect(nsresult);
230 void HandleAsyncNotModified();
231 void HandleAsyncFallback();
232 nsresult ContinueHandleAsyncFallback(nsresult);
233 nsresult PromptTempRedirect();
234 nsresult StartRedirectChannelToURI(nsIURI *, uint32_t);
235 virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, bool preserveMethod);
237 // proxy specific methods
238 nsresult ProxyFailover();
239 nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *);
240 nsresult ContinueDoReplaceWithProxy(nsresult);
241 nsresult ResolveProxy();
243 // cache specific methods
244 nsresult OpenCacheEntry(bool usingSSL);
245 nsresult OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry,
246 bool aNew,
247 nsIApplicationCache* aAppCache,
248 nsresult aResult);
249 nsresult OnNormalCacheEntryAvailable(nsICacheEntry *aEntry,
250 bool aNew,
251 nsresult aResult);
252 nsresult OpenOfflineCacheEntryForWriting();
253 nsresult OnOfflineCacheEntryForWritingAvailable(nsICacheEntry *aEntry,
254 nsIApplicationCache* aAppCache,
255 nsresult aResult);
256 nsresult OnCacheEntryAvailableInternal(nsICacheEntry *entry,
257 bool aNew,
258 nsIApplicationCache* aAppCache,
259 nsresult status);
260 nsresult GenerateCacheKey(uint32_t postID, nsACString &key);
261 nsresult UpdateExpirationTime();
262 nsresult CheckPartial(nsICacheEntry* aEntry, int64_t *aSize, int64_t *aContentLength);
263 bool ShouldUpdateOfflineCacheEntry();
264 nsresult ReadFromCache(bool alreadyMarkedValid);
265 void CloseCacheEntry(bool doomOnFailure);
266 void CloseOfflineCacheEntry();
267 nsresult InitCacheEntry();
268 void UpdateInhibitPersistentCachingFlag();
269 nsresult InitOfflineCacheEntry();
270 nsresult AddCacheEntryHeaders(nsICacheEntry *entry);
271 nsresult StoreAuthorizationMetaData(nsICacheEntry *entry);
272 nsresult FinalizeCacheEntry();
273 nsresult InstallCacheListener(int64_t offset = 0);
274 nsresult InstallOfflineCacheListener(int64_t offset = 0);
275 void MaybeInvalidateCacheEntryForSubsequentGet();
276 void AsyncOnExamineCachedResponse();
278 // Handle the bogus Content-Encoding Apache sometimes sends
279 void ClearBogusContentEncodingIfNeeded();
281 // byte range request specific methods
282 nsresult ProcessPartialContent();
283 nsresult OnDoneReadingPartialCacheEntry(bool *streamDone);
285 nsresult DoAuthRetry(nsAHttpConnection *);
287 void HandleAsyncRedirectChannelToHttps();
288 nsresult StartRedirectChannelToHttps();
289 nsresult ContinueAsyncRedirectChannelToURI(nsresult rv);
290 nsresult OpenRedirectChannel(nsresult rv);
292 /**
293 * A function that takes care of reading STS headers and enforcing STS
294 * load rules. After a secure channel is erected, STS requires the channel
295 * to be trusted or any STS header data on the channel is ignored.
296 * This is called from ProcessResponse.
297 */
298 nsresult ProcessSTSHeader();
300 void InvalidateCacheEntryForLocation(const char *location);
301 void AssembleCacheKey(const char *spec, uint32_t postID, nsACString &key);
302 nsresult CreateNewURI(const char *loc, nsIURI **newURI);
303 void DoInvalidateCacheEntry(nsIURI* aURI);
305 // Ref RFC2616 13.10: "invalidation... MUST only be performed if
306 // the host part is the same as in the Request-URI"
307 inline bool HostPartIsTheSame(nsIURI *uri) {
308 nsAutoCString tmpHost1, tmpHost2;
309 return (NS_SUCCEEDED(mURI->GetAsciiHost(tmpHost1)) &&
310 NS_SUCCEEDED(uri->GetAsciiHost(tmpHost2)) &&
311 (tmpHost1 == tmpHost2));
312 }
314 inline static bool DoNotRender3xxBody(nsresult rv) {
315 return rv == NS_ERROR_REDIRECT_LOOP ||
316 rv == NS_ERROR_CORRUPTED_CONTENT ||
317 rv == NS_ERROR_UNKNOWN_PROTOCOL ||
318 rv == NS_ERROR_MALFORMED_URI;
319 }
321 // Create a aggregate set of the current notification callbacks
322 // and ensure the transaction is updated to use it.
323 void UpdateAggregateCallbacks();
325 static bool HasQueryString(nsHttpRequestHead::ParsedMethodType method, nsIURI * uri);
326 bool ResponseWouldVary(nsICacheEntry* entry) const;
327 bool MustValidateBasedOnQueryUrl() const;
328 bool IsResumable(int64_t partialLen, int64_t contentLength,
329 bool ignoreMissingPartialLen = false) const;
330 nsresult MaybeSetupByteRangeRequest(int64_t partialLen, int64_t contentLength);
331 nsresult SetupByteRangeRequest(int64_t partialLen);
332 nsresult OpenCacheInputStream(nsICacheEntry* cacheEntry, bool startBuffering);
334 private:
335 nsCOMPtr<nsISupports> mSecurityInfo;
336 nsCOMPtr<nsICancelable> mProxyRequest;
338 nsRefPtr<nsInputStreamPump> mTransactionPump;
339 nsRefPtr<nsHttpTransaction> mTransaction;
341 uint64_t mLogicalOffset;
343 // cache specific data
344 nsCOMPtr<nsICacheEntry> mCacheEntry;
345 // We must close mCacheInputStream explicitly to avoid leaks.
346 AutoClose<nsIInputStream> mCacheInputStream;
347 nsRefPtr<nsInputStreamPump> mCachePump;
348 nsAutoPtr<nsHttpResponseHead> mCachedResponseHead;
349 nsCOMPtr<nsISupports> mCachedSecurityInfo;
350 uint32_t mPostID;
351 uint32_t mRequestTime;
353 nsCOMPtr<nsICacheEntry> mOfflineCacheEntry;
354 uint32_t mOfflineCacheLastModifiedTime;
355 nsCOMPtr<nsIApplicationCache> mApplicationCacheForWrite;
356 nsCString mCacheDomain;
358 // auth specific data
359 nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
361 // If the channel is associated with a cache, and the URI matched
362 // a fallback namespace, this will hold the key for the fallback
363 // cache entry.
364 nsCString mFallbackKey;
366 friend class AutoRedirectVetoNotifier;
367 friend class HttpAsyncAborter<nsHttpChannel>;
369 nsCOMPtr<nsIURI> mRedirectURI;
370 nsCOMPtr<nsIChannel> mRedirectChannel;
371 uint32_t mRedirectType;
373 static const uint32_t WAIT_FOR_CACHE_ENTRY = 1;
374 static const uint32_t WAIT_FOR_OFFLINE_CACHE_ENTRY = 2;
376 // state flags
377 uint32_t mCachedContentIsValid : 1;
378 uint32_t mCachedContentIsPartial : 1;
379 uint32_t mTransactionReplaced : 1;
380 uint32_t mAuthRetryPending : 1;
381 uint32_t mProxyAuthPending : 1;
382 uint32_t mResuming : 1;
383 uint32_t mInitedCacheEntry : 1;
384 // True if we are loading a fallback cache entry from the
385 // application cache.
386 uint32_t mFallbackChannel : 1;
387 // True if consumer added its own If-None-Match or If-Modified-Since
388 // headers. In such a case we must not override them in the cache code
389 // and also we want to pass possible 304 code response through.
390 uint32_t mCustomConditionalRequest : 1;
391 uint32_t mFallingBack : 1;
392 uint32_t mWaitingForRedirectCallback : 1;
393 // True if mRequestTime has been set. In such a case it is safe to update
394 // the cache entry's expiration time. Otherwise, it is not(see bug 567360).
395 uint32_t mRequestTimeInitialized : 1;
396 uint32_t mCacheEntryIsReadOnly : 1;
397 uint32_t mCacheEntryIsWriteOnly : 1;
398 // see WAIT_FOR_* constants above
399 uint32_t mCacheEntriesToWaitFor : 2;
400 uint32_t mHasQueryString : 1;
401 // whether cache entry data write was in progress during cache entry check
402 // when true, after we finish read from cache we must check all data
403 // had been loaded from cache. If not, then an error has to be propagated
404 // to the consumer.
405 uint32_t mConcurentCacheAccess : 1;
406 // whether the request is setup be byte-range
407 uint32_t mIsPartialRequest : 1;
408 // true iff there is AutoRedirectVetoNotifier on the stack
409 uint32_t mHasAutoRedirectVetoNotifier : 1;
411 nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
413 // Needed for accurate DNS timing
414 nsRefPtr<nsDNSPrefetch> mDNSPrefetch;
416 nsresult WaitForRedirectCallback();
417 void PushRedirectAsyncFunc(nsContinueRedirectionFunc func);
418 void PopRedirectAsyncFunc(nsContinueRedirectionFunc func);
420 protected:
421 virtual void DoNotifyListenerCleanup();
422 nsPerformance* GetPerformance();
424 private: // cache telemetry
425 bool mDidReval;
427 private:
428 nsIPrincipal *GetPrincipal();
429 nsCOMPtr<nsIPrincipal> mPrincipal;
430 bool mForcePending;
431 };
433 } } // namespace mozilla::net
435 #endif // nsHttpChannel_h__