From 493bf27f79e6f66593e9d65a5b730a92c4304e72 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Thu, 2 Sep 2010 19:11:11 +0200 Subject: [PATCH] Backout nsHttpChannel part of bug 513008, r=michal a=bsmedberg --- netwerk/cache/nsCacheService.cpp | 5 +- netwerk/protocol/http/nsHttpChannel.cpp | 374 ++++++++---------------- netwerk/protocol/http/nsHttpChannel.h | 17 +- 3 files changed, 132 insertions(+), 264 deletions(-) diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index d9cdd31f29e..6eae5546400 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -1298,6 +1298,7 @@ nsCacheService::OpenCacheEntry(nsCacheSession * session, CACHE_LOG_DEBUG(("Created request %p\n", request)); +#if 0 // Disabled because of bug 589296 // Process the request on the background thread if we are on the main thread // and the the request is asynchronous if (NS_IsMainThread() && listener && gService->mCacheIOThread) { @@ -1313,7 +1314,9 @@ nsCacheService::OpenCacheEntry(nsCacheSession * session, if (NS_FAILED(rv)) delete request; } - else { + else +#endif + { rv = gService->ProcessRequest(request, PR_TRUE, result); // delete requests that have completed diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index bc154299361..ffb12f9e743 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -117,8 +117,6 @@ nsHttpChannel::nsHttpChannel() , mCacheAccess(0) , mPostID(0) , mRequestTime(0) - , mOnCacheEntryAvailableCallback(nsnull) - , mAsyncCacheOpen(PR_FALSE) , mPendingAsyncCallOnResume(nsnull) , mSuspendCount(0) , mApplyConversion(PR_TRUE) @@ -225,6 +223,8 @@ nsHttpChannel::Connect(PRBool firstTime) // true when called from AsyncOpen if (firstTime) { + PRBool delayed = PR_FALSE; + // are we offline? PRBool offline = gIOService->IsOffline(); if (offline) @@ -239,7 +239,7 @@ nsHttpChannel::Connect(PRBool firstTime) } // open a cache entry for this channel... - rv = OpenCacheEntry(); + rv = OpenCacheEntry(offline, &delayed); if (NS_FAILED(rv)) { LOG(("OpenCacheEntry failed [rv=%x]\n", rv)); @@ -263,7 +263,7 @@ nsHttpChannel::Connect(PRBool firstTime) if (NS_FAILED(rv)) return rv; } - if (NS_SUCCEEDED(rv) && mAsyncCacheOpen) + if (NS_SUCCEEDED(rv) && delayed) return NS_OK; } @@ -296,14 +296,6 @@ nsHttpChannel::Connect(PRBool firstTime) return NS_ERROR_DOCUMENT_NOT_CACHED; } } - else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) { - // If we have a fallback URI (and we're not already - // falling back), process the fallback asynchronously. - if (!mFallbackChannel && !mFallbackKey.IsEmpty()) { - return AsyncCall(&nsHttpChannel::HandleAsyncFallback); - } - return NS_ERROR_DOCUMENT_NOT_CACHED; - } // check to see if authorization headers should be included mAuthProvider->AddAuthorizationHeaders(); @@ -1942,11 +1934,11 @@ IsSubRangeRequest(nsHttpRequestHead &aRequestHead) } nsresult -nsHttpChannel::OpenCacheEntry() +nsHttpChannel::OpenCacheEntry(PRBool offline, PRBool *delayed) { nsresult rv; - mAsyncCacheOpen = PR_FALSE; + *delayed = PR_FALSE; mLoadedFromApplicationCache = PR_FALSE; LOG(("nsHttpChannel::OpenCacheEntry [this=%p]", this)); @@ -1982,10 +1974,23 @@ nsHttpChannel::OpenCacheEntry() GenerateCacheKey(mPostID, cacheKey); + // Get a cache session with appropriate storage policy + nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy(); + // Set the desired cache access mode accordingly... nsCacheAccessMode accessRequested; - rv = DetermineCacheAccess(&accessRequested); - if (NS_FAILED(rv)) return rv; + if (offline || (mLoadFlags & INHIBIT_CACHING)) { + // If we have been asked to bypass the cache and not write to the + // cache, then don't use the cache at all. Unless we're actually + // offline, which takes precedence over BYPASS_LOCAL_CACHE. + if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline) + return NS_ERROR_NOT_AVAILABLE; + accessRequested = nsICache::ACCESS_READ; + } + else if (BYPASS_LOCAL_CACHE(mLoadFlags)) + accessRequested = nsICache::ACCESS_WRITE; // replace cache entry + else + accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing if (!mApplicationCache && mInheritApplicationCache) { // Pick up an application cache from the notification @@ -2014,6 +2019,10 @@ nsHttpChannel::OpenCacheEntry() nsCOMPtr session; + // Will be set to true if we've found the right session, but need + // to open the cache entry asynchronously. + PRBool waitingForValidation = PR_FALSE; + // If we have an application cache, we check it first. if (mApplicationCache) { nsCAutoString appCacheClientID; @@ -2029,217 +2038,107 @@ nsHttpChannel::OpenCacheEntry() getter_AddRefs(session)); NS_ENSURE_SUCCESS(rv, rv); - if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) { - // must use synchronous open for LOAD_BYPASS_LOCAL_CACHE_IF_BUSY - rv = session->OpenCacheEntry(cacheKey, - nsICache::ACCESS_READ, PR_FALSE, - getter_AddRefs(mCacheEntry)); - if (NS_SUCCEEDED(rv)) { - mCacheEntry->GetAccessGranted(&mCacheAccess); - LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", - this, mCacheAccess)); - mLoadedFromApplicationCache = PR_TRUE; - return NS_OK; - } else if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { - LOG(("bypassing local cache since it is busy\n")); - // Don't try to load normal cache entry - return NS_ERROR_NOT_AVAILABLE; - } - } else { - mOnCacheEntryAvailableCallback = - &nsHttpChannel::OnOfflineCacheEntryAvailable; - // We open with ACCESS_READ only, because we don't want to - // overwrite the offline cache entry non-atomically. - // ACCESS_READ will prevent us from writing to the offline - // cache as a normal cache entry. - rv = session->AsyncOpenCacheEntry(cacheKey, - nsICache::ACCESS_READ, - this); - - if (NS_SUCCEEDED(rv)) { - mAsyncCacheOpen = PR_TRUE; - return NS_OK; - } + // we'll try to synchronously open the cache entry... however, + // it may be in use and not yet validated, in which case we'll + // try asynchronously opening the cache entry. + // + // We open with ACCESS_READ only, because we don't want to + // overwrite the offline cache entry non-atomically. + // ACCESS_READ will prevent us from writing to the offline + // cache as a normal cache entry. + rv = session->OpenCacheEntry(cacheKey, + nsICache::ACCESS_READ, PR_FALSE, + getter_AddRefs(mCacheEntry)); + if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { + accessRequested = nsICache::ACCESS_READ; + waitingForValidation = PR_TRUE; + rv = NS_OK; } - // sync or async opening failed - return OnOfflineCacheEntryAvailable(nsnull, nsICache::ACCESS_NONE, - rv, PR_TRUE); - } - - return OpenNormalCacheEntry(PR_TRUE); -} - -nsresult -nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aEntryStatus, - PRBool aIsSync) -{ - nsresult rv; - - if (NS_SUCCEEDED(aEntryStatus)) { - // We successfully opened an offline cache session and the entry, - // so indicate we will load from the offline cache. - mLoadedFromApplicationCache = PR_TRUE; - mCacheEntry = aEntry; - mCacheAccess = aAccess; - } - - if (mCanceled && NS_FAILED(mStatus)) { - LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus)); - return mStatus; - } - - if (NS_SUCCEEDED(aEntryStatus)) - // Called from OnCacheEntryAvailable, advance to the next state - return Connect(PR_FALSE); - - if (!mCacheForOfflineUse && !mFallbackChannel) { - nsCAutoString cacheKey; - GenerateCacheKey(mPostID, cacheKey); - - // Check for namespace match. - nsCOMPtr namespaceEntry; - rv = mApplicationCache->GetMatchingNamespace - (cacheKey, getter_AddRefs(namespaceEntry)); - if (NS_FAILED(rv) && !aIsSync) - return Connect(PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - - PRUint32 namespaceType = 0; - if (!namespaceEntry || - NS_FAILED(namespaceEntry->GetItemType(&namespaceType)) || - (namespaceType & - (nsIApplicationCacheNamespace::NAMESPACE_FALLBACK | - nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC | - nsIApplicationCacheNamespace::NAMESPACE_BYPASS)) == 0) { - // When loading from an application cache, only items - // on the whitelist or matching a - // fallback/opportunistic namespace should hit the - // network... - mLoadFlags |= LOAD_ONLY_FROM_CACHE; - - // ... and if there were an application cache entry, - // we would have found it earlier. - return aIsSync ? NS_ERROR_CACHE_KEY_NOT_FOUND : Connect(PR_FALSE); - } - - if (namespaceType & - nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) { - rv = namespaceEntry->GetData(mFallbackKey); - if (NS_FAILED(rv) && !aIsSync) - return Connect(PR_FALSE); + if (NS_FAILED(rv) && !mCacheForOfflineUse && !mFallbackChannel) { + // Check for namespace match. + nsCOMPtr namespaceEntry; + rv = mApplicationCache->GetMatchingNamespace + (cacheKey, getter_AddRefs(namespaceEntry)); NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 namespaceType = 0; + if (!namespaceEntry || + NS_FAILED(namespaceEntry->GetItemType(&namespaceType)) || + (namespaceType & + (nsIApplicationCacheNamespace::NAMESPACE_FALLBACK | + nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC | + nsIApplicationCacheNamespace::NAMESPACE_BYPASS)) == 0) { + // When loading from an application cache, only items + // on the whitelist or matching a + // fallback/opportunistic namespace should hit the + // network... + mLoadFlags |= LOAD_ONLY_FROM_CACHE; + + // ... and if there were an application cache entry, + // we would have found it earlier. + return NS_ERROR_CACHE_KEY_NOT_FOUND; + } + + if (namespaceType & + nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) { + rv = namespaceEntry->GetData(mFallbackKey); + NS_ENSURE_SUCCESS(rv, rv); + } + + if ((namespaceType & + nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC) && + mLoadFlags & LOAD_DOCUMENT_URI) { + // Document loads for items in an opportunistic namespace + // should be placed in the offline cache. + nsCString clientID; + mApplicationCache->GetClientID(clientID); + + mCacheForOfflineUse = !clientID.IsEmpty(); + SetOfflineCacheClientID(clientID); + mCachingOpportunistically = PR_TRUE; + } } - - if ((namespaceType & - nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC) && - mLoadFlags & LOAD_DOCUMENT_URI) { - // Document loads for items in an opportunistic namespace - // should be placed in the offline cache. - nsCString clientID; - mApplicationCache->GetClientID(clientID); - - mCacheForOfflineUse = !clientID.IsEmpty(); - SetOfflineCacheClientID(clientID); - mCachingOpportunistically = PR_TRUE; + else if (NS_SUCCEEDED(rv)) { + // We successfully opened an offline cache session and the entry, + // now indiciate we load from the offline cache. + mLoadedFromApplicationCache = PR_TRUE; } } - return OpenNormalCacheEntry(aIsSync); -} + if (!mCacheEntry && !waitingForValidation) { + rv = gHttpHandler->GetCacheSession(storagePolicy, + getter_AddRefs(session)); + if (NS_FAILED(rv)) return rv; - -nsresult -nsHttpChannel::OpenNormalCacheEntry(PRBool aIsSync) -{ - NS_ASSERTION(!mCacheEntry, "We have already mCacheEntry"); - - nsresult rv; - - nsCAutoString cacheKey; - GenerateCacheKey(mPostID, cacheKey); - - nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy(); - - nsCOMPtr session; - rv = gHttpHandler->GetCacheSession(storagePolicy, - getter_AddRefs(session)); - if (NS_FAILED(rv)) return rv; - - nsCacheAccessMode accessRequested; - rv = DetermineCacheAccess(&accessRequested); - if (NS_FAILED(rv)) return rv; - - if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) { - if (!aIsSync) { - // Unexpected state: we were called from OnCacheEntryAvailable(), - // so LOAD_BYPASS_LOCAL_CACHE_IF_BUSY shouldn't be set. Unless - // somebody altered mLoadFlags between OpenCacheEntry() and - // OnCacheEntryAvailable()... - NS_WARNING( - "OpenNormalCacheEntry() called from OnCacheEntryAvailable() " - "when LOAD_BYPASS_LOCAL_CACHE_IF_BUSY was specified"); - } - - // must use synchronous open for LOAD_BYPASS_LOCAL_CACHE_IF_BUSY rv = session->OpenCacheEntry(cacheKey, accessRequested, PR_FALSE, getter_AddRefs(mCacheEntry)); - if (NS_SUCCEEDED(rv)) { - mCacheEntry->GetAccessGranted(&mCacheAccess); - LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", - this, mCacheAccess)); + if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { + waitingForValidation = PR_TRUE; + rv = NS_OK; } - else if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { + if (NS_FAILED(rv)) return rv; + } + + if (waitingForValidation) { + // access to the cache entry has been denied (because the + // cache entry is probably in use by another channel). + if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) { LOG(("bypassing local cache since it is busy\n")); - rv = NS_ERROR_NOT_AVAILABLE; + return NS_ERROR_NOT_AVAILABLE; } - } - else { - mOnCacheEntryAvailableCallback = - &nsHttpChannel::OnNormalCacheEntryAvailable; rv = session->AsyncOpenCacheEntry(cacheKey, accessRequested, this); - if (NS_SUCCEEDED(rv)) { - mAsyncCacheOpen = PR_TRUE; - return NS_OK; - } + if (NS_FAILED(rv)) return rv; + // we'll have to wait for the cache entry + *delayed = PR_TRUE; + } + else if (NS_SUCCEEDED(rv)) { + mCacheEntry->GetAccessGranted(&mCacheAccess); + LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", this, mCacheAccess)); } - - if (!aIsSync) - // Called from OnCacheEntryAvailable, advance to the next state - rv = Connect(PR_FALSE); - return rv; } -nsresult -nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aEntryStatus, - PRBool aIsSync) -{ - NS_ASSERTION(!aIsSync, "aIsSync should be false"); - - if (NS_SUCCEEDED(aEntryStatus)) { - mCacheEntry = aEntry; - mCacheAccess = aAccess; - } - - if (mCanceled && NS_FAILED(mStatus)) { - LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus)); - return mStatus; - } - - if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && NS_FAILED(aEntryStatus)) - // if this channel is only allowed to pull from the cache, then - // we must fail if we were unable to open a cache entry. - return NS_ERROR_DOCUMENT_NOT_CACHED; - - // advance to the next state... - return Connect(PR_FALSE); -} - nsresult nsHttpChannel::OpenOfflineCacheEntryForWriting() @@ -4436,8 +4335,6 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, nsCacheAccessMode access, nsresult status) { - nsresult rv; - LOG(("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p " "access=%x status=%x]\n", this, entry, access, status)); @@ -4446,24 +4343,28 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, if (!mIsPending) return NS_OK; - nsOnCacheEntryAvailableCallback callback = mOnCacheEntryAvailableCallback; - mOnCacheEntryAvailableCallback = nsnull; + // otherwise, we have to handle this event. + if (NS_SUCCEEDED(status)) { + mCacheEntry = entry; + mCacheAccess = access; + } - NS_ASSERTION(callback, - "nsHttpChannel::OnCacheEntryAvailable called without callback"); - rv = ((*this).*callback)(entry, access, status, PR_FALSE); + nsresult rv; + if (mCanceled && NS_FAILED(mStatus)) { + LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus)); + rv = mStatus; + } + else if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && NS_FAILED(status)) + // if this channel is only allowed to pull from the cache, then + // we must fail if we were unable to open a cache entry. + rv = NS_ERROR_DOCUMENT_NOT_CACHED; + else + // advance to the next state... + rv = Connect(PR_FALSE); + + // a failure from Connect means that we have to abort the channel. if (NS_FAILED(rv)) { - LOG(("AsyncOpenCacheEntry failed [rv=%x]\n", rv)); - if (mLoadFlags & LOAD_ONLY_FROM_CACHE) { - // If we have a fallback URI (and we're not already - // falling back), process the fallback asynchronously. - if (!mFallbackChannel && !mFallbackKey.IsEmpty()) { - rv = AsyncCall(&nsHttpChannel::HandleAsyncFallback); - if (NS_SUCCEEDED(rv)) - return rv; - } - } CloseCacheEntry(PR_TRUE); AsyncAbort(rv); } @@ -4930,27 +4831,6 @@ nsHttpChannel::DetermineStoragePolicy() return policy; } -nsresult -nsHttpChannel::DetermineCacheAccess(nsCacheAccessMode *_retval) -{ - PRBool offline = gIOService->IsOffline(); - - if (offline || (mLoadFlags & INHIBIT_CACHING)) { - // If we have been asked to bypass the cache and not write to the - // cache, then don't use the cache at all. Unless we're actually - // offline, which takes precedence over BYPASS_LOCAL_CACHE. - if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline) - return NS_ERROR_NOT_AVAILABLE; - *_retval = nsICache::ACCESS_READ; - } - else if (BYPASS_LOCAL_CACHE(mLoadFlags)) - *_retval = nsICache::ACCESS_WRITE; // replace cache entry - else - *_retval = nsICache::ACCESS_READ_WRITE; // normal browsing - - return NS_OK; -} - void nsHttpChannel::AsyncOnExamineCachedResponse() { diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index ca77de3bf79..fa8539fc20b 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -217,16 +217,7 @@ private: nsresult ResolveProxy(); // cache specific methods - nsresult OpenCacheEntry(); - nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aResult, - PRBool aSync); - nsresult OpenNormalCacheEntry(PRBool aSync); - nsresult OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry, - nsCacheAccessMode aAccess, - nsresult aResult, - PRBool aSync); + nsresult OpenCacheEntry(PRBool offline, PRBool *delayed); nsresult OpenOfflineCacheEntryForWriting(); nsresult GenerateCacheKey(PRUint32 postID, nsACString &key); nsresult UpdateExpirationTime(); @@ -244,7 +235,6 @@ private: nsresult InstallOfflineCacheListener(); void MaybeInvalidateCacheEntryForSubsequentGet(); nsCacheStoragePolicy DetermineStoragePolicy(); - nsresult DetermineCacheAccess(nsCacheAccessMode *_retval); void AsyncOnExamineCachedResponse(); // Handle the bogus Content-Encoding Apache sometimes sends @@ -287,11 +277,6 @@ private: PRUint32 mPostID; PRUint32 mRequestTime; - typedef nsresult (nsHttpChannel:: *nsOnCacheEntryAvailableCallback)( - nsICacheEntryDescriptor *, nsCacheAccessMode, nsresult, PRBool); - nsOnCacheEntryAvailableCallback mOnCacheEntryAvailableCallback; - PRBool mAsyncCacheOpen; - nsCOMPtr mOfflineCacheEntry; nsCacheAccessMode mOfflineCacheAccess; nsCString mOfflineCacheClientID;