|
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/. */ |
|
6 |
|
7 #ifndef nsHttpChannel_h__ |
|
8 #define nsHttpChannel_h__ |
|
9 |
|
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" |
|
25 |
|
26 class nsIPrincipal; |
|
27 class nsDNSPrefetch; |
|
28 class nsICacheEntryDescriptor; |
|
29 class nsICancelable; |
|
30 class nsIHttpChannelAuthProvider; |
|
31 class nsInputStreamPump; |
|
32 class nsPerformance; |
|
33 |
|
34 namespace mozilla { namespace net { |
|
35 |
|
36 //----------------------------------------------------------------------------- |
|
37 // nsHttpChannel |
|
38 //----------------------------------------------------------------------------- |
|
39 |
|
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 |
|
71 |
|
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); |
|
92 |
|
93 nsHttpChannel(); |
|
94 virtual ~nsHttpChannel(); |
|
95 |
|
96 virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo, |
|
97 uint32_t aProxyResolveFlags, |
|
98 nsIURI *aProxyURI); |
|
99 |
|
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); |
|
116 |
|
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); |
|
127 |
|
128 public: /* internal necko use only */ |
|
129 |
|
130 void InternalSetUploadStream(nsIInputStream *uploadStream) |
|
131 { mUploadStream = uploadStream; } |
|
132 void SetUploadStreamHasHeaders(bool hasHeaders) |
|
133 { mUploadStreamHasHeaders = hasHeaders; } |
|
134 |
|
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 } |
|
143 |
|
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 {} |
|
155 |
|
156 nsresult MarkAsForeign(); |
|
157 }; |
|
158 |
|
159 OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker(); |
|
160 |
|
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 } |
|
174 |
|
175 void Keep(uint32_t flags) |
|
176 { |
|
177 // Called after successful call to appropriate AsyncOpenCacheEntry call. |
|
178 mKeep |= flags; |
|
179 } |
|
180 |
|
181 ~AutoCacheWaitFlags() |
|
182 { |
|
183 // Keep only flags those are left to be wait for. |
|
184 mChannel->mCacheEntriesToWaitFor &= mKeep; |
|
185 } |
|
186 |
|
187 private: |
|
188 nsHttpChannel* mChannel; |
|
189 uint32_t mKeep : 2; |
|
190 }; |
|
191 |
|
192 void ForcePending(bool aForcePending); |
|
193 |
|
194 private: |
|
195 typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result); |
|
196 |
|
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(); |
|
221 |
|
222 nsresult ContinueOnStartRequest1(nsresult); |
|
223 nsresult ContinueOnStartRequest2(nsresult); |
|
224 nsresult ContinueOnStartRequest3(nsresult); |
|
225 |
|
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); |
|
236 |
|
237 // proxy specific methods |
|
238 nsresult ProxyFailover(); |
|
239 nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *); |
|
240 nsresult ContinueDoReplaceWithProxy(nsresult); |
|
241 nsresult ResolveProxy(); |
|
242 |
|
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(); |
|
277 |
|
278 // Handle the bogus Content-Encoding Apache sometimes sends |
|
279 void ClearBogusContentEncodingIfNeeded(); |
|
280 |
|
281 // byte range request specific methods |
|
282 nsresult ProcessPartialContent(); |
|
283 nsresult OnDoneReadingPartialCacheEntry(bool *streamDone); |
|
284 |
|
285 nsresult DoAuthRetry(nsAHttpConnection *); |
|
286 |
|
287 void HandleAsyncRedirectChannelToHttps(); |
|
288 nsresult StartRedirectChannelToHttps(); |
|
289 nsresult ContinueAsyncRedirectChannelToURI(nsresult rv); |
|
290 nsresult OpenRedirectChannel(nsresult rv); |
|
291 |
|
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(); |
|
299 |
|
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); |
|
304 |
|
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 } |
|
313 |
|
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 } |
|
320 |
|
321 // Create a aggregate set of the current notification callbacks |
|
322 // and ensure the transaction is updated to use it. |
|
323 void UpdateAggregateCallbacks(); |
|
324 |
|
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); |
|
333 |
|
334 private: |
|
335 nsCOMPtr<nsISupports> mSecurityInfo; |
|
336 nsCOMPtr<nsICancelable> mProxyRequest; |
|
337 |
|
338 nsRefPtr<nsInputStreamPump> mTransactionPump; |
|
339 nsRefPtr<nsHttpTransaction> mTransaction; |
|
340 |
|
341 uint64_t mLogicalOffset; |
|
342 |
|
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; |
|
352 |
|
353 nsCOMPtr<nsICacheEntry> mOfflineCacheEntry; |
|
354 uint32_t mOfflineCacheLastModifiedTime; |
|
355 nsCOMPtr<nsIApplicationCache> mApplicationCacheForWrite; |
|
356 nsCString mCacheDomain; |
|
357 |
|
358 // auth specific data |
|
359 nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider; |
|
360 |
|
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; |
|
365 |
|
366 friend class AutoRedirectVetoNotifier; |
|
367 friend class HttpAsyncAborter<nsHttpChannel>; |
|
368 |
|
369 nsCOMPtr<nsIURI> mRedirectURI; |
|
370 nsCOMPtr<nsIChannel> mRedirectChannel; |
|
371 uint32_t mRedirectType; |
|
372 |
|
373 static const uint32_t WAIT_FOR_CACHE_ENTRY = 1; |
|
374 static const uint32_t WAIT_FOR_OFFLINE_CACHE_ENTRY = 2; |
|
375 |
|
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; |
|
410 |
|
411 nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack; |
|
412 |
|
413 // Needed for accurate DNS timing |
|
414 nsRefPtr<nsDNSPrefetch> mDNSPrefetch; |
|
415 |
|
416 nsresult WaitForRedirectCallback(); |
|
417 void PushRedirectAsyncFunc(nsContinueRedirectionFunc func); |
|
418 void PopRedirectAsyncFunc(nsContinueRedirectionFunc func); |
|
419 |
|
420 protected: |
|
421 virtual void DoNotifyListenerCleanup(); |
|
422 nsPerformance* GetPerformance(); |
|
423 |
|
424 private: // cache telemetry |
|
425 bool mDidReval; |
|
426 |
|
427 private: |
|
428 nsIPrincipal *GetPrincipal(); |
|
429 nsCOMPtr<nsIPrincipal> mPrincipal; |
|
430 bool mForcePending; |
|
431 }; |
|
432 |
|
433 } } // namespace mozilla::net |
|
434 |
|
435 #endif // nsHttpChannel_h__ |