1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/http/nsHttpChannel.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,435 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim:set et cin ts=4 sw=4 sts=4: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef nsHttpChannel_h__ 1.11 +#define nsHttpChannel_h__ 1.12 + 1.13 +#include "HttpBaseChannel.h" 1.14 +#include "nsTArray.h" 1.15 +#include "nsICachingChannel.h" 1.16 +#include "nsICacheEntry.h" 1.17 +#include "nsICacheEntryOpenCallback.h" 1.18 +#include "nsIDNSListener.h" 1.19 +#include "nsIApplicationCacheChannel.h" 1.20 +#include "nsIProtocolProxyCallback.h" 1.21 +#include "nsIHttpAuthenticableChannel.h" 1.22 +#include "nsIAsyncVerifyRedirectCallback.h" 1.23 +#include "nsIThreadRetargetableRequest.h" 1.24 +#include "nsIThreadRetargetableStreamListener.h" 1.25 +#include "nsWeakReference.h" 1.26 +#include "TimingStruct.h" 1.27 +#include "AutoClose.h" 1.28 + 1.29 +class nsIPrincipal; 1.30 +class nsDNSPrefetch; 1.31 +class nsICacheEntryDescriptor; 1.32 +class nsICancelable; 1.33 +class nsIHttpChannelAuthProvider; 1.34 +class nsInputStreamPump; 1.35 +class nsPerformance; 1.36 + 1.37 +namespace mozilla { namespace net { 1.38 + 1.39 +//----------------------------------------------------------------------------- 1.40 +// nsHttpChannel 1.41 +//----------------------------------------------------------------------------- 1.42 + 1.43 +class nsHttpChannel : public HttpBaseChannel 1.44 + , public HttpAsyncAborter<nsHttpChannel> 1.45 + , public nsIStreamListener 1.46 + , public nsICachingChannel 1.47 + , public nsICacheEntryOpenCallback 1.48 + , public nsITransportEventSink 1.49 + , public nsIProtocolProxyCallback 1.50 + , public nsIHttpAuthenticableChannel 1.51 + , public nsIApplicationCacheChannel 1.52 + , public nsIAsyncVerifyRedirectCallback 1.53 + , public nsIThreadRetargetableRequest 1.54 + , public nsIThreadRetargetableStreamListener 1.55 + , public nsIDNSListener 1.56 + , public nsSupportsWeakReference 1.57 +{ 1.58 +public: 1.59 + NS_DECL_ISUPPORTS_INHERITED 1.60 + NS_DECL_NSIREQUESTOBSERVER 1.61 + NS_DECL_NSISTREAMLISTENER 1.62 + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER 1.63 + NS_DECL_NSICACHEINFOCHANNEL 1.64 + NS_DECL_NSICACHINGCHANNEL 1.65 + NS_DECL_NSICACHEENTRYOPENCALLBACK 1.66 + NS_DECL_NSITRANSPORTEVENTSINK 1.67 + NS_DECL_NSIPROTOCOLPROXYCALLBACK 1.68 + NS_DECL_NSIPROXIEDCHANNEL 1.69 + NS_DECL_NSIAPPLICATIONCACHECONTAINER 1.70 + NS_DECL_NSIAPPLICATIONCACHECHANNEL 1.71 + NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK 1.72 + NS_DECL_NSITHREADRETARGETABLEREQUEST 1.73 + NS_DECL_NSIDNSLISTENER 1.74 + 1.75 + // nsIHttpAuthenticableChannel. We can't use 1.76 + // NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and 1.77 + // others. 1.78 + NS_IMETHOD GetIsSSL(bool *aIsSSL); 1.79 + NS_IMETHOD GetProxyMethodIsConnect(bool *aProxyMethodIsConnect); 1.80 + NS_IMETHOD GetServerResponseHeader(nsACString & aServerResponseHeader); 1.81 + NS_IMETHOD GetProxyChallenges(nsACString & aChallenges); 1.82 + NS_IMETHOD GetWWWChallenges(nsACString & aChallenges); 1.83 + NS_IMETHOD SetProxyCredentials(const nsACString & aCredentials); 1.84 + NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials); 1.85 + NS_IMETHOD OnAuthAvailable(); 1.86 + NS_IMETHOD OnAuthCancelled(bool userCancel); 1.87 + // Functions we implement from nsIHttpAuthenticableChannel but are 1.88 + // declared in HttpBaseChannel must be implemented in this class. We 1.89 + // just call the HttpBaseChannel:: impls. 1.90 + NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags); 1.91 + NS_IMETHOD GetURI(nsIURI **aURI); 1.92 + NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks); 1.93 + NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup); 1.94 + NS_IMETHOD GetRequestMethod(nsACString& aMethod); 1.95 + 1.96 + nsHttpChannel(); 1.97 + virtual ~nsHttpChannel(); 1.98 + 1.99 + virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo, 1.100 + uint32_t aProxyResolveFlags, 1.101 + nsIURI *aProxyURI); 1.102 + 1.103 + // Methods HttpBaseChannel didn't implement for us or that we override. 1.104 + // 1.105 + // nsIRequest 1.106 + NS_IMETHOD Cancel(nsresult status); 1.107 + NS_IMETHOD Suspend(); 1.108 + NS_IMETHOD Resume(); 1.109 + NS_IMETHOD IsPending(bool *aIsPending); 1.110 + // nsIChannel 1.111 + NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo); 1.112 + NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext); 1.113 + // nsIHttpChannelInternal 1.114 + NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey); 1.115 + // nsISupportsPriority 1.116 + NS_IMETHOD SetPriority(int32_t value); 1.117 + // nsIResumableChannel 1.118 + NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID); 1.119 + 1.120 + NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks); 1.121 + NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup); 1.122 + // nsITimedChannel 1.123 + NS_IMETHOD GetDomainLookupStart(mozilla::TimeStamp *aDomainLookupStart); 1.124 + NS_IMETHOD GetDomainLookupEnd(mozilla::TimeStamp *aDomainLookupEnd); 1.125 + NS_IMETHOD GetConnectStart(mozilla::TimeStamp *aConnectStart); 1.126 + NS_IMETHOD GetConnectEnd(mozilla::TimeStamp *aConnectEnd); 1.127 + NS_IMETHOD GetRequestStart(mozilla::TimeStamp *aRequestStart); 1.128 + NS_IMETHOD GetResponseStart(mozilla::TimeStamp *aResponseStart); 1.129 + NS_IMETHOD GetResponseEnd(mozilla::TimeStamp *aResponseEnd); 1.130 + 1.131 +public: /* internal necko use only */ 1.132 + 1.133 + void InternalSetUploadStream(nsIInputStream *uploadStream) 1.134 + { mUploadStream = uploadStream; } 1.135 + void SetUploadStreamHasHeaders(bool hasHeaders) 1.136 + { mUploadStreamHasHeaders = hasHeaders; } 1.137 + 1.138 + nsresult SetReferrerInternal(nsIURI *referrer) { 1.139 + nsAutoCString spec; 1.140 + nsresult rv = referrer->GetAsciiSpec(spec); 1.141 + if (NS_FAILED(rv)) return rv; 1.142 + mReferrer = referrer; 1.143 + mRequestHead.SetHeader(nsHttp::Referer, spec); 1.144 + return NS_OK; 1.145 + } 1.146 + 1.147 + // This allows cache entry to be marked as foreign even after channel itself 1.148 + // is gone. Needed for e10s (see HttpChannelParent::RecvDocumentChannelCleanup) 1.149 + class OfflineCacheEntryAsForeignMarker { 1.150 + nsCOMPtr<nsIApplicationCache> mApplicationCache; 1.151 + nsCOMPtr<nsIURI> mCacheURI; 1.152 + public: 1.153 + OfflineCacheEntryAsForeignMarker(nsIApplicationCache* appCache, 1.154 + nsIURI* aURI) 1.155 + : mApplicationCache(appCache) 1.156 + , mCacheURI(aURI) 1.157 + {} 1.158 + 1.159 + nsresult MarkAsForeign(); 1.160 + }; 1.161 + 1.162 + OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker(); 1.163 + 1.164 + // Helper to keep cache callbacks wait flags consistent 1.165 + class AutoCacheWaitFlags 1.166 + { 1.167 + public: 1.168 + AutoCacheWaitFlags(nsHttpChannel* channel) 1.169 + : mChannel(channel) 1.170 + , mKeep(0) 1.171 + { 1.172 + // Flags must be set before entering any AsyncOpenCacheEntry call. 1.173 + mChannel->mCacheEntriesToWaitFor = 1.174 + nsHttpChannel::WAIT_FOR_CACHE_ENTRY | 1.175 + nsHttpChannel::WAIT_FOR_OFFLINE_CACHE_ENTRY; 1.176 + } 1.177 + 1.178 + void Keep(uint32_t flags) 1.179 + { 1.180 + // Called after successful call to appropriate AsyncOpenCacheEntry call. 1.181 + mKeep |= flags; 1.182 + } 1.183 + 1.184 + ~AutoCacheWaitFlags() 1.185 + { 1.186 + // Keep only flags those are left to be wait for. 1.187 + mChannel->mCacheEntriesToWaitFor &= mKeep; 1.188 + } 1.189 + 1.190 + private: 1.191 + nsHttpChannel* mChannel; 1.192 + uint32_t mKeep : 2; 1.193 + }; 1.194 + 1.195 + void ForcePending(bool aForcePending); 1.196 + 1.197 +private: 1.198 + typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result); 1.199 + 1.200 + bool RequestIsConditional(); 1.201 + nsresult BeginConnect(); 1.202 + nsresult Connect(); 1.203 + nsresult ContinueConnect(); 1.204 + void SpeculativeConnect(); 1.205 + nsresult SetupTransaction(); 1.206 + void SetupTransactionLoadGroupInfo(); 1.207 + nsresult CallOnStartRequest(); 1.208 + nsresult ProcessResponse(); 1.209 + nsresult ContinueProcessResponse(nsresult); 1.210 + nsresult ProcessNormal(); 1.211 + nsresult ContinueProcessNormal(nsresult); 1.212 + nsresult ProcessNotModified(); 1.213 + nsresult AsyncProcessRedirection(uint32_t httpStatus); 1.214 + nsresult ContinueProcessRedirection(nsresult); 1.215 + nsresult ContinueProcessRedirectionAfterFallback(nsresult); 1.216 + nsresult ProcessFailedProxyConnect(uint32_t httpStatus); 1.217 + nsresult ProcessFallback(bool *waitingForRedirectCallback); 1.218 + nsresult ContinueProcessFallback(nsresult); 1.219 + void HandleAsyncAbort(); 1.220 + nsresult EnsureAssocReq(); 1.221 + void ProcessSSLInformation(); 1.222 + bool IsHTTPS(); 1.223 + void RetrieveSSLOptions(); 1.224 + 1.225 + nsresult ContinueOnStartRequest1(nsresult); 1.226 + nsresult ContinueOnStartRequest2(nsresult); 1.227 + nsresult ContinueOnStartRequest3(nsresult); 1.228 + 1.229 + // redirection specific methods 1.230 + void HandleAsyncRedirect(); 1.231 + void HandleAsyncAPIRedirect(); 1.232 + nsresult ContinueHandleAsyncRedirect(nsresult); 1.233 + void HandleAsyncNotModified(); 1.234 + void HandleAsyncFallback(); 1.235 + nsresult ContinueHandleAsyncFallback(nsresult); 1.236 + nsresult PromptTempRedirect(); 1.237 + nsresult StartRedirectChannelToURI(nsIURI *, uint32_t); 1.238 + virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, bool preserveMethod); 1.239 + 1.240 + // proxy specific methods 1.241 + nsresult ProxyFailover(); 1.242 + nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *); 1.243 + nsresult ContinueDoReplaceWithProxy(nsresult); 1.244 + nsresult ResolveProxy(); 1.245 + 1.246 + // cache specific methods 1.247 + nsresult OpenCacheEntry(bool usingSSL); 1.248 + nsresult OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry, 1.249 + bool aNew, 1.250 + nsIApplicationCache* aAppCache, 1.251 + nsresult aResult); 1.252 + nsresult OnNormalCacheEntryAvailable(nsICacheEntry *aEntry, 1.253 + bool aNew, 1.254 + nsresult aResult); 1.255 + nsresult OpenOfflineCacheEntryForWriting(); 1.256 + nsresult OnOfflineCacheEntryForWritingAvailable(nsICacheEntry *aEntry, 1.257 + nsIApplicationCache* aAppCache, 1.258 + nsresult aResult); 1.259 + nsresult OnCacheEntryAvailableInternal(nsICacheEntry *entry, 1.260 + bool aNew, 1.261 + nsIApplicationCache* aAppCache, 1.262 + nsresult status); 1.263 + nsresult GenerateCacheKey(uint32_t postID, nsACString &key); 1.264 + nsresult UpdateExpirationTime(); 1.265 + nsresult CheckPartial(nsICacheEntry* aEntry, int64_t *aSize, int64_t *aContentLength); 1.266 + bool ShouldUpdateOfflineCacheEntry(); 1.267 + nsresult ReadFromCache(bool alreadyMarkedValid); 1.268 + void CloseCacheEntry(bool doomOnFailure); 1.269 + void CloseOfflineCacheEntry(); 1.270 + nsresult InitCacheEntry(); 1.271 + void UpdateInhibitPersistentCachingFlag(); 1.272 + nsresult InitOfflineCacheEntry(); 1.273 + nsresult AddCacheEntryHeaders(nsICacheEntry *entry); 1.274 + nsresult StoreAuthorizationMetaData(nsICacheEntry *entry); 1.275 + nsresult FinalizeCacheEntry(); 1.276 + nsresult InstallCacheListener(int64_t offset = 0); 1.277 + nsresult InstallOfflineCacheListener(int64_t offset = 0); 1.278 + void MaybeInvalidateCacheEntryForSubsequentGet(); 1.279 + void AsyncOnExamineCachedResponse(); 1.280 + 1.281 + // Handle the bogus Content-Encoding Apache sometimes sends 1.282 + void ClearBogusContentEncodingIfNeeded(); 1.283 + 1.284 + // byte range request specific methods 1.285 + nsresult ProcessPartialContent(); 1.286 + nsresult OnDoneReadingPartialCacheEntry(bool *streamDone); 1.287 + 1.288 + nsresult DoAuthRetry(nsAHttpConnection *); 1.289 + 1.290 + void HandleAsyncRedirectChannelToHttps(); 1.291 + nsresult StartRedirectChannelToHttps(); 1.292 + nsresult ContinueAsyncRedirectChannelToURI(nsresult rv); 1.293 + nsresult OpenRedirectChannel(nsresult rv); 1.294 + 1.295 + /** 1.296 + * A function that takes care of reading STS headers and enforcing STS 1.297 + * load rules. After a secure channel is erected, STS requires the channel 1.298 + * to be trusted or any STS header data on the channel is ignored. 1.299 + * This is called from ProcessResponse. 1.300 + */ 1.301 + nsresult ProcessSTSHeader(); 1.302 + 1.303 + void InvalidateCacheEntryForLocation(const char *location); 1.304 + void AssembleCacheKey(const char *spec, uint32_t postID, nsACString &key); 1.305 + nsresult CreateNewURI(const char *loc, nsIURI **newURI); 1.306 + void DoInvalidateCacheEntry(nsIURI* aURI); 1.307 + 1.308 + // Ref RFC2616 13.10: "invalidation... MUST only be performed if 1.309 + // the host part is the same as in the Request-URI" 1.310 + inline bool HostPartIsTheSame(nsIURI *uri) { 1.311 + nsAutoCString tmpHost1, tmpHost2; 1.312 + return (NS_SUCCEEDED(mURI->GetAsciiHost(tmpHost1)) && 1.313 + NS_SUCCEEDED(uri->GetAsciiHost(tmpHost2)) && 1.314 + (tmpHost1 == tmpHost2)); 1.315 + } 1.316 + 1.317 + inline static bool DoNotRender3xxBody(nsresult rv) { 1.318 + return rv == NS_ERROR_REDIRECT_LOOP || 1.319 + rv == NS_ERROR_CORRUPTED_CONTENT || 1.320 + rv == NS_ERROR_UNKNOWN_PROTOCOL || 1.321 + rv == NS_ERROR_MALFORMED_URI; 1.322 + } 1.323 + 1.324 + // Create a aggregate set of the current notification callbacks 1.325 + // and ensure the transaction is updated to use it. 1.326 + void UpdateAggregateCallbacks(); 1.327 + 1.328 + static bool HasQueryString(nsHttpRequestHead::ParsedMethodType method, nsIURI * uri); 1.329 + bool ResponseWouldVary(nsICacheEntry* entry) const; 1.330 + bool MustValidateBasedOnQueryUrl() const; 1.331 + bool IsResumable(int64_t partialLen, int64_t contentLength, 1.332 + bool ignoreMissingPartialLen = false) const; 1.333 + nsresult MaybeSetupByteRangeRequest(int64_t partialLen, int64_t contentLength); 1.334 + nsresult SetupByteRangeRequest(int64_t partialLen); 1.335 + nsresult OpenCacheInputStream(nsICacheEntry* cacheEntry, bool startBuffering); 1.336 + 1.337 +private: 1.338 + nsCOMPtr<nsISupports> mSecurityInfo; 1.339 + nsCOMPtr<nsICancelable> mProxyRequest; 1.340 + 1.341 + nsRefPtr<nsInputStreamPump> mTransactionPump; 1.342 + nsRefPtr<nsHttpTransaction> mTransaction; 1.343 + 1.344 + uint64_t mLogicalOffset; 1.345 + 1.346 + // cache specific data 1.347 + nsCOMPtr<nsICacheEntry> mCacheEntry; 1.348 + // We must close mCacheInputStream explicitly to avoid leaks. 1.349 + AutoClose<nsIInputStream> mCacheInputStream; 1.350 + nsRefPtr<nsInputStreamPump> mCachePump; 1.351 + nsAutoPtr<nsHttpResponseHead> mCachedResponseHead; 1.352 + nsCOMPtr<nsISupports> mCachedSecurityInfo; 1.353 + uint32_t mPostID; 1.354 + uint32_t mRequestTime; 1.355 + 1.356 + nsCOMPtr<nsICacheEntry> mOfflineCacheEntry; 1.357 + uint32_t mOfflineCacheLastModifiedTime; 1.358 + nsCOMPtr<nsIApplicationCache> mApplicationCacheForWrite; 1.359 + nsCString mCacheDomain; 1.360 + 1.361 + // auth specific data 1.362 + nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider; 1.363 + 1.364 + // If the channel is associated with a cache, and the URI matched 1.365 + // a fallback namespace, this will hold the key for the fallback 1.366 + // cache entry. 1.367 + nsCString mFallbackKey; 1.368 + 1.369 + friend class AutoRedirectVetoNotifier; 1.370 + friend class HttpAsyncAborter<nsHttpChannel>; 1.371 + 1.372 + nsCOMPtr<nsIURI> mRedirectURI; 1.373 + nsCOMPtr<nsIChannel> mRedirectChannel; 1.374 + uint32_t mRedirectType; 1.375 + 1.376 + static const uint32_t WAIT_FOR_CACHE_ENTRY = 1; 1.377 + static const uint32_t WAIT_FOR_OFFLINE_CACHE_ENTRY = 2; 1.378 + 1.379 + // state flags 1.380 + uint32_t mCachedContentIsValid : 1; 1.381 + uint32_t mCachedContentIsPartial : 1; 1.382 + uint32_t mTransactionReplaced : 1; 1.383 + uint32_t mAuthRetryPending : 1; 1.384 + uint32_t mProxyAuthPending : 1; 1.385 + uint32_t mResuming : 1; 1.386 + uint32_t mInitedCacheEntry : 1; 1.387 + // True if we are loading a fallback cache entry from the 1.388 + // application cache. 1.389 + uint32_t mFallbackChannel : 1; 1.390 + // True if consumer added its own If-None-Match or If-Modified-Since 1.391 + // headers. In such a case we must not override them in the cache code 1.392 + // and also we want to pass possible 304 code response through. 1.393 + uint32_t mCustomConditionalRequest : 1; 1.394 + uint32_t mFallingBack : 1; 1.395 + uint32_t mWaitingForRedirectCallback : 1; 1.396 + // True if mRequestTime has been set. In such a case it is safe to update 1.397 + // the cache entry's expiration time. Otherwise, it is not(see bug 567360). 1.398 + uint32_t mRequestTimeInitialized : 1; 1.399 + uint32_t mCacheEntryIsReadOnly : 1; 1.400 + uint32_t mCacheEntryIsWriteOnly : 1; 1.401 + // see WAIT_FOR_* constants above 1.402 + uint32_t mCacheEntriesToWaitFor : 2; 1.403 + uint32_t mHasQueryString : 1; 1.404 + // whether cache entry data write was in progress during cache entry check 1.405 + // when true, after we finish read from cache we must check all data 1.406 + // had been loaded from cache. If not, then an error has to be propagated 1.407 + // to the consumer. 1.408 + uint32_t mConcurentCacheAccess : 1; 1.409 + // whether the request is setup be byte-range 1.410 + uint32_t mIsPartialRequest : 1; 1.411 + // true iff there is AutoRedirectVetoNotifier on the stack 1.412 + uint32_t mHasAutoRedirectVetoNotifier : 1; 1.413 + 1.414 + nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack; 1.415 + 1.416 + // Needed for accurate DNS timing 1.417 + nsRefPtr<nsDNSPrefetch> mDNSPrefetch; 1.418 + 1.419 + nsresult WaitForRedirectCallback(); 1.420 + void PushRedirectAsyncFunc(nsContinueRedirectionFunc func); 1.421 + void PopRedirectAsyncFunc(nsContinueRedirectionFunc func); 1.422 + 1.423 +protected: 1.424 + virtual void DoNotifyListenerCleanup(); 1.425 + nsPerformance* GetPerformance(); 1.426 + 1.427 +private: // cache telemetry 1.428 + bool mDidReval; 1.429 + 1.430 +private: 1.431 + nsIPrincipal *GetPrincipal(); 1.432 + nsCOMPtr<nsIPrincipal> mPrincipal; 1.433 + bool mForcePending; 1.434 +}; 1.435 + 1.436 +} } // namespace mozilla::net 1.437 + 1.438 +#endif // nsHttpChannel_h__