Bug 922671 - nsHttpChannel must bypass concurrent read when request is not resumable, r=michal

This commit is contained in:
Honza Bambas 2013-11-20 23:20:19 +01:00
parent c7787bb201
commit 0ea2cf8530
2 changed files with 51 additions and 23 deletions

View File

@ -2008,33 +2008,39 @@ nsHttpChannel::EnsureAssocReq()
// nsHttpChannel <byte-range>
//-----------------------------------------------------------------------------
nsresult
nsHttpChannel::MaybeSetupByteRangeRequest(int64_t partialLen, int64_t contentLength)
bool
nsHttpChannel::IsResumable(int64_t partialLen, int64_t contentLength,
bool ignoreMissingPartialLen) const
{
nsresult rv = NS_OK;
bool hasContentEncoding =
mCachedResponseHead->PeekHeader(nsHttp::Content_Encoding)
!= nullptr;
// Be pesimistic
mIsPartialRequest = false;
if ((partialLen < contentLength) &&
partialLen > 0 &&
return (partialLen < contentLength) &&
(partialLen > 0 || ignoreMissingPartialLen) &&
!hasContentEncoding &&
mCachedResponseHead->IsResumable() &&
!mCustomConditionalRequest &&
!mCachedResponseHead->NoStore()) {
!mCachedResponseHead->NoStore();
}
nsresult
nsHttpChannel::MaybeSetupByteRangeRequest(int64_t partialLen, int64_t contentLength)
{
// Be pesimistic
mIsPartialRequest = false;
if (!IsResumable(partialLen, contentLength))
return NS_OK;
// looks like a partial entry we can reuse; add If-Range
// and Range headers.
rv = SetupByteRangeRequest(partialLen);
nsresult rv = SetupByteRangeRequest(partialLen);
if (NS_FAILED(rv)) {
// Make the request unconditional again.
mRequestHead.ClearHeader(nsHttp::Range);
mRequestHead.ClearHeader(nsHttp::If_Range);
}
}
return rv;
}
@ -2723,6 +2729,8 @@ nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, nsIApplicationCache* appC
return rv;
}
bool wantCompleteEntry = false;
if (method != nsHttp::Head && !isCachedRedirect) {
// If the cached content-length is set and it does not match the data
// size of the cached content, then the cached response is partial...
@ -2741,12 +2749,22 @@ nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, nsIApplicationCache* appC
if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
LOG((" not interested in the entry, "
"LOAD_BYPASS_LOCAL_CACHE_IF_BUSY specified"));
*aResult = ENTRY_NOT_WANTED;
return NS_OK;
}
// Ignore !(size > 0) from the resumability condition
if (!IsResumable(size, contentLength, true)) {
LOG((" wait for entry completion, "
"response is not resumable"));
wantCompleteEntry = true;
}
else {
mConcurentCacheAccess = 1;
}
}
else if (contentLength != int64_t(-1) && contentLength != size) {
LOG(("Cached data size does not match the Content-Length header "
"[content-length=%lld size=%lld]\n", contentLength, size));
@ -2952,6 +2970,8 @@ nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, nsIApplicationCache* appC
if (mDidReval)
*aResult = ENTRY_NEEDS_REVALIDATION;
else if (wantCompleteEntry)
*aResult = RECHECK_AFTER_WRITE_FINISHED;
else
*aResult = ENTRY_WANTED;
@ -3047,11 +3067,17 @@ nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntry *aEntry,
{
mCacheEntriesToWaitFor &= ~WAIT_FOR_CACHE_ENTRY;
if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && (NS_FAILED(aEntryStatus) || aNew)) {
if (NS_FAILED(aEntryStatus) || aNew) {
// Make sure this flag is dropped. It may happen the entry is doomed
// between OnCacheEntryCheck and OnCacheEntryAvailable.
mCachedContentIsValid = false;
if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
// if this channel is only allowed to pull from the cache, then
// we must fail if we were unable to open a cache entry for read.
return NS_ERROR_DOCUMENT_NOT_CACHED;
}
}
if (NS_SUCCEEDED(aEntryStatus)) {
mCacheEntry = aEntry;

View File

@ -314,6 +314,8 @@ private:
static bool HasQueryString(nsHttpAtom method, nsIURI * uri);
bool ResponseWouldVary(nsICacheEntry* entry) const;
bool MustValidateBasedOnQueryUrl() const;
bool IsResumable(int64_t partialLen, int64_t contentLength,
bool ignoreMissingPartialLen = false) const;
nsresult MaybeSetupByteRangeRequest(int64_t partialLen, int64_t contentLength);
nsresult SetupByteRangeRequest(int64_t partialLen);
nsresult OpenCacheInputStream(nsICacheEntry* cacheEntry, bool startBuffering);