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 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications.
20 : * Portions created by the Initial Developer are Copyright (C) 2001
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Darin Fisher <darin@netscape.com> (original author)
25 : * Christian Biesinger <cbiesinger@web.de>
26 : * Daniel Witte <dwitte@mozilla.com>
27 : * Jason Duell <jduell.mcbugs@gmail.com>
28 : *
29 : * Alternatively, the contents of this file may be used under the terms of
30 : * either the GNU General Public License Version 2 or later (the "GPL"), or
31 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 : * in which case the provisions of the GPL or the LGPL are applicable instead
33 : * of those above. If you wish to allow use of your version of this file only
34 : * under the terms of either the GPL or the LGPL, and not to allow others to
35 : * use your version of this file under the terms of the MPL, indicate your
36 : * decision by deleting the provisions above and replace them with the notice
37 : * and other provisions required by the GPL or the LGPL. If you do not delete
38 : * the provisions above, a recipient may use your version of this file under
39 : * the terms of any one of the MPL, the GPL or the LGPL.
40 : *
41 : * ***** END LICENSE BLOCK ***** */
42 :
43 : #ifndef nsHttpChannel_h__
44 : #define nsHttpChannel_h__
45 :
46 : #include "HttpBaseChannel.h"
47 :
48 : #include "nsHttpTransaction.h"
49 : #include "nsInputStreamPump.h"
50 : #include "nsThreadUtils.h"
51 : #include "nsTArray.h"
52 :
53 : #include "nsIHttpEventSink.h"
54 : #include "nsICachingChannel.h"
55 : #include "nsICacheEntryDescriptor.h"
56 : #include "nsICacheListener.h"
57 : #include "nsIApplicationCacheChannel.h"
58 : #include "nsIPrompt.h"
59 : #include "nsIResumableChannel.h"
60 : #include "nsIProtocolProxyCallback.h"
61 : #include "nsICancelable.h"
62 : #include "nsIHttpAuthenticableChannel.h"
63 : #include "nsIHttpChannelAuthProvider.h"
64 : #include "nsIAsyncVerifyRedirectCallback.h"
65 : #include "nsICryptoHash.h"
66 : #include "nsITimedChannel.h"
67 : #include "nsDNSPrefetch.h"
68 : #include "TimingStruct.h"
69 :
70 : class nsAHttpConnection;
71 : class AutoRedirectVetoNotifier;
72 :
73 : using namespace mozilla::net;
74 :
75 : //-----------------------------------------------------------------------------
76 : // nsHttpChannel
77 : //-----------------------------------------------------------------------------
78 :
79 : class nsHttpChannel : public HttpBaseChannel
80 : , public HttpAsyncAborter<nsHttpChannel>
81 : , public nsIStreamListener
82 : , public nsICachingChannel
83 : , public nsICacheListener
84 : , public nsITransportEventSink
85 : , public nsIProtocolProxyCallback
86 : , public nsIHttpAuthenticableChannel
87 : , public nsIApplicationCacheChannel
88 : , public nsIAsyncVerifyRedirectCallback
89 : , public nsITimedChannel
90 : {
91 : public:
92 : NS_DECL_ISUPPORTS_INHERITED
93 : NS_DECL_NSIREQUESTOBSERVER
94 : NS_DECL_NSISTREAMLISTENER
95 : NS_DECL_NSICACHEINFOCHANNEL
96 : NS_DECL_NSICACHINGCHANNEL
97 : NS_DECL_NSICACHELISTENER
98 : NS_DECL_NSITRANSPORTEVENTSINK
99 : NS_DECL_NSIPROTOCOLPROXYCALLBACK
100 : NS_DECL_NSIPROXIEDCHANNEL
101 : NS_DECL_NSIAPPLICATIONCACHECONTAINER
102 : NS_DECL_NSIAPPLICATIONCACHECHANNEL
103 : NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
104 : NS_DECL_NSITIMEDCHANNEL
105 :
106 : // nsIHttpAuthenticableChannel. We can't use
107 : // NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and
108 : // others.
109 : NS_IMETHOD GetIsSSL(bool *aIsSSL);
110 : NS_IMETHOD GetProxyMethodIsConnect(bool *aProxyMethodIsConnect);
111 : NS_IMETHOD GetServerResponseHeader(nsACString & aServerResponseHeader);
112 : NS_IMETHOD GetProxyChallenges(nsACString & aChallenges);
113 : NS_IMETHOD GetWWWChallenges(nsACString & aChallenges);
114 : NS_IMETHOD SetProxyCredentials(const nsACString & aCredentials);
115 : NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials);
116 : NS_IMETHOD OnAuthAvailable();
117 : NS_IMETHOD OnAuthCancelled(bool userCancel);
118 : // Functions we implement from nsIHttpAuthenticableChannel but are
119 : // declared in HttpBaseChannel must be implemented in this class. We
120 : // just call the HttpBaseChannel:: impls.
121 : NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags);
122 : NS_IMETHOD GetURI(nsIURI **aURI);
123 : NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks);
124 : NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
125 : NS_IMETHOD GetRequestMethod(nsACString& aMethod);
126 :
127 : nsHttpChannel();
128 : virtual ~nsHttpChannel();
129 :
130 : virtual nsresult Init(nsIURI *aURI, PRUint8 aCaps, nsProxyInfo *aProxyInfo);
131 :
132 : // Methods HttpBaseChannel didn't implement for us or that we override.
133 : //
134 : // nsIRequest
135 : NS_IMETHOD Cancel(nsresult status);
136 : NS_IMETHOD Suspend();
137 : NS_IMETHOD Resume();
138 : // nsIChannel
139 : NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
140 : NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext);
141 : // nsIHttpChannelInternal
142 : NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey);
143 : // nsISupportsPriority
144 : NS_IMETHOD SetPriority(PRInt32 value);
145 : // nsIResumableChannel
146 : NS_IMETHOD ResumeAt(PRUint64 startPos, const nsACString& entityID);
147 :
148 : public: /* internal necko use only */
149 :
150 0 : void InternalSetUploadStream(nsIInputStream *uploadStream)
151 0 : { mUploadStream = uploadStream; }
152 0 : void SetUploadStreamHasHeaders(bool hasHeaders)
153 0 : { mUploadStreamHasHeaders = hasHeaders; }
154 :
155 0 : nsresult SetReferrerInternal(nsIURI *referrer) {
156 0 : nsCAutoString spec;
157 0 : nsresult rv = referrer->GetAsciiSpec(spec);
158 0 : if (NS_FAILED(rv)) return rv;
159 0 : mReferrer = referrer;
160 0 : mRequestHead.SetHeader(nsHttp::Referer, spec);
161 0 : return NS_OK;
162 : }
163 :
164 : private:
165 : typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
166 :
167 : bool RequestIsConditional();
168 : nsresult Connect(bool firstTime = true);
169 : nsresult SetupTransaction();
170 : nsresult CallOnStartRequest();
171 : nsresult ProcessResponse();
172 : nsresult ContinueProcessResponse(nsresult);
173 : nsresult ProcessNormal();
174 : nsresult ContinueProcessNormal(nsresult);
175 : nsresult ProcessNotModified();
176 : nsresult AsyncProcessRedirection(PRUint32 httpStatus);
177 : nsresult ContinueProcessRedirection(nsresult);
178 : nsresult ContinueProcessRedirectionAfterFallback(nsresult);
179 : bool ShouldSSLProxyResponseContinue(PRUint32 httpStatus);
180 : nsresult ProcessFailedSSLConnect(PRUint32 httpStatus);
181 : nsresult ProcessFallback(bool *waitingForRedirectCallback);
182 : nsresult ContinueProcessFallback(nsresult);
183 : bool ResponseWouldVary();
184 : void HandleAsyncAbort();
185 :
186 : nsresult ContinueOnStartRequest1(nsresult);
187 : nsresult ContinueOnStartRequest2(nsresult);
188 : nsresult ContinueOnStartRequest3(nsresult);
189 :
190 : // redirection specific methods
191 : void HandleAsyncRedirect();
192 : nsresult ContinueHandleAsyncRedirect(nsresult);
193 : void HandleAsyncNotModified();
194 : void HandleAsyncFallback();
195 : nsresult ContinueHandleAsyncFallback(nsresult);
196 : nsresult PromptTempRedirect();
197 : virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *,
198 : bool preserveMethod,
199 : bool forProxy);
200 :
201 : // proxy specific methods
202 : nsresult ProxyFailover();
203 : nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *);
204 : nsresult ContinueDoReplaceWithProxy(nsresult);
205 : void HandleAsyncReplaceWithProxy();
206 : nsresult ContinueHandleAsyncReplaceWithProxy(nsresult);
207 : nsresult ResolveProxy();
208 :
209 : // cache specific methods
210 : nsresult OpenCacheEntry();
211 : nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
212 : nsCacheAccessMode aAccess,
213 : nsresult aResult,
214 : bool aSync);
215 : nsresult OpenNormalCacheEntry(bool aSync);
216 : nsresult OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
217 : nsCacheAccessMode aAccess,
218 : nsresult aResult,
219 : bool aSync);
220 : nsresult OpenOfflineCacheEntryForWriting();
221 : nsresult GenerateCacheKey(PRUint32 postID, nsACString &key);
222 : nsresult UpdateExpirationTime();
223 : nsresult CheckCache();
224 : nsresult ShouldUpdateOfflineCacheEntry(bool *shouldCacheForOfflineUse);
225 : nsresult ReadFromCache();
226 : void CloseCacheEntry(bool doomOnFailure);
227 : void CloseOfflineCacheEntry();
228 : nsresult InitCacheEntry();
229 : void UpdateInhibitPersistentCachingFlag();
230 : nsresult InitOfflineCacheEntry();
231 : nsresult AddCacheEntryHeaders(nsICacheEntryDescriptor *entry);
232 : nsresult StoreAuthorizationMetaData(nsICacheEntryDescriptor *entry);
233 : nsresult FinalizeCacheEntry();
234 : nsresult InstallCacheListener(PRUint32 offset = 0);
235 : nsresult InstallOfflineCacheListener();
236 : void MaybeInvalidateCacheEntryForSubsequentGet();
237 : nsCacheStoragePolicy DetermineStoragePolicy();
238 : nsresult DetermineCacheAccess(nsCacheAccessMode *_retval);
239 : void AsyncOnExamineCachedResponse();
240 :
241 : // Handle the bogus Content-Encoding Apache sometimes sends
242 : void ClearBogusContentEncodingIfNeeded();
243 :
244 : // byte range request specific methods
245 : nsresult SetupByteRangeRequest(PRUint32 partialLen);
246 : nsresult ProcessPartialContent();
247 : nsresult OnDoneReadingPartialCacheEntry(bool *streamDone);
248 :
249 : nsresult DoAuthRetry(nsAHttpConnection *);
250 : bool MustValidateBasedOnQueryUrl();
251 :
252 : void HandleAsyncRedirectChannelToHttps();
253 : nsresult AsyncRedirectChannelToHttps();
254 : nsresult ContinueAsyncRedirectChannelToHttps(nsresult rv);
255 :
256 : /**
257 : * A function that takes care of reading STS headers and enforcing STS
258 : * load rules. After a secure channel is erected, STS requires the channel
259 : * to be trusted or any STS header data on the channel is ignored.
260 : * This is called from ProcessResponse.
261 : */
262 : nsresult ProcessSTSHeader();
263 :
264 : /**
265 : * Computes and returns a 64 bit encoded string holding a hash of the
266 : * input buffer. Input buffer must be a null-terminated string.
267 : */
268 : nsresult Hash(const char *buf, nsACString &hash);
269 :
270 : void InvalidateCacheEntryForLocation(const char *location);
271 : void AssembleCacheKey(const char *spec, PRUint32 postID, nsACString &key);
272 : nsresult CreateNewURI(const char *loc, nsIURI **newURI);
273 : void DoInvalidateCacheEntry(nsACString &key);
274 :
275 : // Ref RFC2616 13.10: "invalidation... MUST only be performed if
276 : // the host part is the same as in the Request-URI"
277 38 : inline bool HostPartIsTheSame(nsIURI *uri) {
278 76 : nsCAutoString tmpHost1, tmpHost2;
279 38 : return (NS_SUCCEEDED(mURI->GetAsciiHost(tmpHost1)) &&
280 38 : NS_SUCCEEDED(uri->GetAsciiHost(tmpHost2)) &&
281 76 : (tmpHost1 == tmpHost2));
282 : }
283 :
284 : private:
285 : nsCOMPtr<nsISupports> mSecurityInfo;
286 : nsCOMPtr<nsICancelable> mProxyRequest;
287 :
288 : nsRefPtr<nsInputStreamPump> mTransactionPump;
289 : nsRefPtr<nsHttpTransaction> mTransaction;
290 :
291 : PRUint64 mLogicalOffset;
292 :
293 : // cache specific data
294 : nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
295 : nsRefPtr<nsInputStreamPump> mCachePump;
296 : nsAutoPtr<nsHttpResponseHead> mCachedResponseHead;
297 : nsCacheAccessMode mCacheAccess;
298 : PRUint32 mPostID;
299 : PRUint32 mRequestTime;
300 :
301 : typedef nsresult (nsHttpChannel:: *nsOnCacheEntryAvailableCallback)(
302 : nsICacheEntryDescriptor *, nsCacheAccessMode, nsresult, bool);
303 : nsOnCacheEntryAvailableCallback mOnCacheEntryAvailableCallback;
304 : bool mAsyncCacheOpen;
305 :
306 : nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
307 : nsCacheAccessMode mOfflineCacheAccess;
308 : nsCString mOfflineCacheClientID;
309 :
310 : // auth specific data
311 : nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
312 :
313 : // Proxy info to replace with
314 : nsCOMPtr<nsIProxyInfo> mTargetProxyInfo;
315 :
316 : // If the channel is associated with a cache, and the URI matched
317 : // a fallback namespace, this will hold the key for the fallback
318 : // cache entry.
319 : nsCString mFallbackKey;
320 :
321 : friend class AutoRedirectVetoNotifier;
322 : friend class HttpAsyncAborter<nsHttpChannel>;
323 : nsCOMPtr<nsIURI> mRedirectURI;
324 : nsCOMPtr<nsIChannel> mRedirectChannel;
325 : PRUint32 mRedirectType;
326 :
327 : // state flags
328 : PRUint32 mCachedContentIsValid : 1;
329 : PRUint32 mCachedContentIsPartial : 1;
330 : PRUint32 mTransactionReplaced : 1;
331 : PRUint32 mAuthRetryPending : 1;
332 : PRUint32 mResuming : 1;
333 : PRUint32 mInitedCacheEntry : 1;
334 : PRUint32 mCacheForOfflineUse : 1;
335 : // True if mCacheForOfflineUse was set because we were caching
336 : // opportunistically.
337 : PRUint32 mCachingOpportunistically : 1;
338 : // True if we are loading a fallback cache entry from the
339 : // application cache.
340 : PRUint32 mFallbackChannel : 1;
341 : // True if consumer added its own If-None-Match or If-Modified-Since
342 : // headers. In such a case we must not override them in the cache code
343 : // and also we want to pass possible 304 code response through.
344 : PRUint32 mCustomConditionalRequest : 1;
345 : PRUint32 mFallingBack : 1;
346 : PRUint32 mWaitingForRedirectCallback : 1;
347 : // True if mRequestTime has been set. In such a case it is safe to update
348 : // the cache entry's expiration time. Otherwise, it is not(see bug 567360).
349 : PRUint32 mRequestTimeInitialized : 1;
350 :
351 : nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
352 :
353 : nsCOMPtr<nsICryptoHash> mHasher;
354 :
355 : PRTime mChannelCreationTime;
356 : mozilla::TimeStamp mChannelCreationTimestamp;
357 : mozilla::TimeStamp mAsyncOpenTime;
358 : mozilla::TimeStamp mCacheReadStart;
359 : mozilla::TimeStamp mCacheReadEnd;
360 : // copied from the transaction before we null out mTransaction
361 : // so that the timing can still be queried from OnStopRequest
362 : TimingStruct mTransactionTimings;
363 : // Needed for accurate DNS timing
364 : nsRefPtr<nsDNSPrefetch> mDNSPrefetch;
365 :
366 : nsresult WaitForRedirectCallback();
367 : void PushRedirectAsyncFunc(nsContinueRedirectionFunc func);
368 : void PopRedirectAsyncFunc(nsContinueRedirectionFunc func);
369 :
370 : protected:
371 : virtual void DoNotifyListenerCleanup();
372 :
373 : private: // cache telemetry
374 : enum {
375 : kCacheHit = 1,
376 : kCacheHitViaReval = 2,
377 : kCacheMissedViaReval = 3,
378 : kCacheMissed = 4
379 : };
380 : bool mDidReval;
381 : };
382 :
383 : #endif // nsHttpChannel_h__
|