зеркало из https://github.com/mozilla/gecko-dev.git
[not part of the build] Fixed up HTTP cache validation for use with new cache.
This commit is contained in:
Родитель
1f60ff29b4
Коммит
3bbad52377
|
@ -73,7 +73,6 @@ static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID);
|
||||||
#include "nsIAuthenticator.h"
|
#include "nsIAuthenticator.h"
|
||||||
|
|
||||||
static NS_DEFINE_CID(kNetModuleMgrCID, NS_NETMODULEMGR_CID);
|
static NS_DEFINE_CID(kNetModuleMgrCID, NS_NETMODULEMGR_CID);
|
||||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
|
||||||
static NS_DEFINE_CID(kWalletServiceCID, NS_WALLETSERVICE_CID);
|
static NS_DEFINE_CID(kWalletServiceCID, NS_WALLETSERVICE_CID);
|
||||||
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
||||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||||
|
@ -105,7 +104,9 @@ nsHTTPChannel::nsHTTPChannel(nsIURI *aURL, nsHTTPHandler *aHandler)
|
||||||
, mConnected(PR_FALSE)
|
, mConnected(PR_FALSE)
|
||||||
, mApplyConversion(PR_TRUE)
|
, mApplyConversion(PR_TRUE)
|
||||||
, mOpenHasEventQueue(PR_TRUE)
|
, mOpenHasEventQueue(PR_TRUE)
|
||||||
|
#ifndef MOZ_NEW_CACHE
|
||||||
, mCachedContentIsAvailable(PR_FALSE)
|
, mCachedContentIsAvailable(PR_FALSE)
|
||||||
|
#endif
|
||||||
, mCachedContentIsValid(PR_FALSE)
|
, mCachedContentIsValid(PR_FALSE)
|
||||||
, mFiredOnHeadersAvailable(PR_FALSE)
|
, mFiredOnHeadersAvailable(PR_FALSE)
|
||||||
, mAuthTriedWithPrehost(PR_FALSE)
|
, mAuthTriedWithPrehost(PR_FALSE)
|
||||||
|
@ -779,24 +780,589 @@ nsresult nsHTTPChannel::Init()
|
||||||
nsresult
|
nsresult
|
||||||
nsHTTPChannel::OpenCacheEntry()
|
nsHTTPChannel::OpenCacheEntry()
|
||||||
{
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
LOG(("nsHTTPChannel::OpenCacheEntry [this=%x]", this));
|
LOG(("nsHTTPChannel::OpenCacheEntry [this=%x]", this));
|
||||||
|
|
||||||
// make sure we're not abusing this function
|
// make sure we're not abusing this function
|
||||||
NS_ENSURE_TRUE(mHandler, NS_ERROR_NOT_INITIALIZED);
|
NS_ENSURE_TRUE(mHandler, NS_ERROR_NOT_INITIALIZED);
|
||||||
NS_ENSURE_TRUE(!mCacheEntry, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(!mCacheEntry, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsCacheStoragePolicy storagePolicy;
|
||||||
|
if (mLoadAttributes & INHIBIT_PERSISTENT_CACHING)
|
||||||
|
storagePolicy = nsICache::STORE_IN_MEMORY;
|
||||||
|
else
|
||||||
|
storagePolicy = nsICache::STORE_ANYWHERE; // allow on disk
|
||||||
|
|
||||||
nsCOMPtr<nsICacheSession> session;
|
nsCOMPtr<nsICacheSession> session;
|
||||||
nsresult rv = mHandler->GetCacheSession(getter_AddRefs(session));
|
rv = mHandler->GetCacheSession(storagePolicy, getter_AddRefs(session));
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// Find out if we're offline
|
||||||
|
PRBool offline = PR_FALSE;
|
||||||
|
nsCOMPtr<nsIIOService> ioService = do_GetIOService();
|
||||||
|
if (ioService)
|
||||||
|
ioService->GetOffline(&offline);
|
||||||
|
|
||||||
|
// Set the requested cache access...
|
||||||
|
nsCacheAccessMode accessRequested;
|
||||||
|
if (offline)
|
||||||
|
accessRequested = nsICache::ACCESS_READ; // read from cache
|
||||||
|
else if (mLoadAttributes & FORCE_RELOAD)
|
||||||
|
accessRequested = nsICache::ACCESS_WRITE; // replace cache entry
|
||||||
|
else
|
||||||
|
accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open a cache entry with key = "http-method url"
|
||||||
|
//
|
||||||
|
|
||||||
|
nsAutoString method;
|
||||||
|
mRequest->Method()->ToString(method);
|
||||||
|
char *methodStr = method.ToNewCString();
|
||||||
|
|
||||||
|
nsCAutoString key;
|
||||||
|
key += methodStr;
|
||||||
|
key += NS_LITERAL_CSTRING(" ");
|
||||||
|
key += mRequest->Spec();
|
||||||
|
|
||||||
|
nsMemory::Free(methodStr);
|
||||||
|
|
||||||
return session->AsyncOpenCacheEntry(mRequest->Spec(),
|
return session->AsyncOpenCacheEntry(mRequest->Spec(),
|
||||||
nsICache::ACCESS_READ_WRITE,
|
accessRequested,
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
// The request-time is the time at which we sent the request.
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::GetRequestTime(PRTime *result)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
nsXPIDLCString str;
|
||||||
|
nsresult rv = mCacheEntry->GetMetaDataElement("request-time", getter_Copies(str));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
*result = LL_Zero();
|
||||||
|
|
||||||
|
if (str)
|
||||||
|
PR_ParseTimeString((const char *) str, PR_TRUE, result);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::SetRequestTime(PRTime t)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
char buf[256];
|
||||||
|
PRExplodedTime et;
|
||||||
|
|
||||||
|
PR_ExplodeTime(t, PR_LocalTimeParameters, &et);
|
||||||
|
PR_FormatTime(buf, sizeof(buf), "%c", &et);
|
||||||
|
|
||||||
|
return mCacheEntry->SetMetaDataElement("request-time", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The response-time is the time at which we received the response.
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::GetResponseTime(PRTime *result)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
nsXPIDLCString str;
|
||||||
|
nsresult rv = mCacheEntry->GetMetaDataElement("response-time", getter_Copies(str));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
*result = LL_Zero();
|
||||||
|
|
||||||
|
if (str)
|
||||||
|
PR_ParseTimeString((const char *) str, PR_TRUE, result);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::SetResponseTime(PRTime t)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
char buf[256];
|
||||||
|
PRExplodedTime et;
|
||||||
|
|
||||||
|
PR_ExplodeTime(t, PR_LocalTimeParameters, &et);
|
||||||
|
PR_FormatTime(buf, sizeof(buf), "%c", &et);
|
||||||
|
|
||||||
|
return mCacheEntry->SetMetaDataElement("response-time", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// From section 13.2.3 of RFC2616, we compute the current age of a cached
|
||||||
|
// response as follows:
|
||||||
|
//
|
||||||
|
// currentAge = max(max(0, responseTime - dateValue), ageValue)
|
||||||
|
// + now - requestTime
|
||||||
|
//
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::ComputeCurrentAge(PRTime now,
|
||||||
|
PRUint32 *result)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(mResponse, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
PRTime requestTime, responseTime, dateValue, diff;
|
||||||
|
PRUint32 ageValue;
|
||||||
|
PRBool avail = PR_FALSE;
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
*result = 0;
|
||||||
|
|
||||||
|
rv = mResponse->GetDateValue(&dateValue, &avail);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
if (!avail) {
|
||||||
|
LOG(("nsHTTPChannel::ComputeAge [this=%x] Date response header not set!\n", this));
|
||||||
|
// Assume we have a very fast connection !!
|
||||||
|
dateValue = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = mResponse->GetAgeValue(&ageValue, &avail);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = GetRequestTime(&requestTime);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = GetResponseTime(&responseTime);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// Compute apparent age
|
||||||
|
LL_SUB(diff, responseTime, dateValue);
|
||||||
|
LL_L2UI(*result, diff);
|
||||||
|
*result = PR_MAX(0, *result);
|
||||||
|
|
||||||
|
// Compute corrected received age
|
||||||
|
if (ageValue)
|
||||||
|
*result = PR_MAX(*result, ageValue);
|
||||||
|
|
||||||
|
// Compute resident time
|
||||||
|
LL_SUB(diff, now, requestTime);
|
||||||
|
|
||||||
|
// Compute current age
|
||||||
|
PRUint32 temp;
|
||||||
|
LL_L2UI(temp, diff);
|
||||||
|
*result += temp;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// From section 13.2.4 of RFC2616, we compute the freshness lifetime of a cached
|
||||||
|
// response as follows:
|
||||||
|
//
|
||||||
|
// freshnessLifetime = max_age_value
|
||||||
|
// <or>
|
||||||
|
// freshnessLifetime = expires_value - date_value
|
||||||
|
// <or>
|
||||||
|
// freshnessLifetime = (date - lastModified) * 0.10
|
||||||
|
//
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::ComputeFreshnessLifetime(PRUint32 *result)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(mResponse, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
PRBool avail = PR_FALSE;
|
||||||
|
|
||||||
|
// Try HTTP/1.1 style max-age directive...
|
||||||
|
rv = mResponse->GetMaxAge(result, &avail);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
if (avail)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
PRTime date, date2, diff;
|
||||||
|
|
||||||
|
rv = mResponse->GetDateValue(&date, &avail);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
if (avail) {
|
||||||
|
// Try HTTP/1.0 style expires header...
|
||||||
|
rv = mResponse->GetExpiresValue(&date2, &avail);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
if (avail) {
|
||||||
|
LL_SUB(diff, date2, date);
|
||||||
|
LL_L2UI(*result, diff);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback on heuristic using last modified header...
|
||||||
|
rv = mResponse->GetLastModifiedValue(&date2, &avail);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
if (avail) {
|
||||||
|
LL_SUB(diff, date, date2);
|
||||||
|
LL_L2UI(*result, diff);
|
||||||
|
*result = (PRUint32) (*result * 0.1);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("nsHTTPChannel::ComputeFreshnessLifetime [this = %x] "
|
||||||
|
"Insufficient information to compute a non-zero freshness "
|
||||||
|
"lifetime!\n", this));
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateExpirationTime is called when a new response comes in from the server.
|
||||||
|
// It updates the stored response-time and sets the expiration time on the
|
||||||
|
// cache entry.
|
||||||
|
//
|
||||||
|
// From section 13.2.4 of RFC2616, we compute expiration time as follows:
|
||||||
|
//
|
||||||
|
// timeRemaining = freshnessLifetime - currentAge
|
||||||
|
// expirationTime = now + timeRemaining
|
||||||
|
//
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::UpdateExpirationTime()
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
PRTime expirationTime, now = PR_Now();
|
||||||
|
PRUint32 freshnessLifetime, currentAge, timeRemaining;
|
||||||
|
|
||||||
|
rv = SetResponseTime(now);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = ComputeCurrentAge(now, ¤tAge);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = ComputeFreshnessLifetime(&freshnessLifetime);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
timeRemaining = freshnessLifetime - currentAge;
|
||||||
|
timeRemaining = PR_MIN(0, timeRemaining);
|
||||||
|
|
||||||
|
LL_UI2L(expirationTime, timeRemaining);
|
||||||
|
LL_ADD(expirationTime, now, expirationTime);
|
||||||
|
|
||||||
|
return mCacheEntry->SetExpirationTime(expirationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckCache is called from Connect after a cache entry has been opened for
|
||||||
|
// this URL but before going out to net. It's purpose is to set or clear the
|
||||||
|
// mCachedContentIsValid flag, and to configure an If-Modified-Since request
|
||||||
|
// if validation is required.
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::CheckCache()
|
||||||
|
{
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
nsXPIDLCString str;
|
||||||
|
|
||||||
|
LOG(("nsHTTPChannel::CheckCache [this=%x entry=%x]",
|
||||||
|
this, mCacheEntry.get()));
|
||||||
|
|
||||||
|
// Be pessimistic: assume the cache entry has no useful data.
|
||||||
|
mCachedContentIsValid = PR_FALSE;
|
||||||
|
|
||||||
|
// Don't proceed unless we have opened a cache entry for reading.
|
||||||
|
if (!mCacheEntry || !(mCacheAccess & nsICache::ACCESS_READ))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
// Get the cached HTTP response headers
|
||||||
|
rv = mCacheEntry->GetMetaDataElement("headers", getter_Copies(str));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// Parse the cached HTTP response headers
|
||||||
|
NS_IF_RELEASE(mCachedResponse); // XXX this should already be cleared !!
|
||||||
|
mCachedResponse = new nsHTTPResponse();
|
||||||
|
if (!mCachedResponse)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
NS_ADDREF(mCachedResponse);
|
||||||
|
nsSubsumeCStr headers((char *) (const char *) str, PR_FALSE);
|
||||||
|
rv = mCachedResponse->ParseHeaders(headers);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// If we were only granted read access, then assume the entry is valid.
|
||||||
|
if (mCacheAccess == nsICache::ACCESS_READ) {
|
||||||
|
mCachedContentIsValid = PR_TRUE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If validation is inhibited, we'll just use whatever data is in
|
||||||
|
// the cache, regardless of whether or not it has expired.
|
||||||
|
if (mLoadAttributes & nsIChannel::VALIDATE_NEVER) {
|
||||||
|
mCachedContentIsValid = PR_TRUE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool doIfModifiedSince = PR_FALSE;
|
||||||
|
|
||||||
|
// Be optimistic: assume that we won't need to send If-Modified-Since
|
||||||
|
mCachedContentIsValid = PR_TRUE;
|
||||||
|
SetRequestHeader(nsHTTPAtoms::If_Modified_Since, nsnull);
|
||||||
|
|
||||||
|
// If there is no Last-Modified response header, then we cannot send an
|
||||||
|
// If-Modified-Since request header.
|
||||||
|
nsXPIDLCString lastModified;
|
||||||
|
mCachedResponse->GetHeader(nsHTTPAtoms::Last_Modified,
|
||||||
|
getter_Copies(lastModified));
|
||||||
|
if (!lastModified) {
|
||||||
|
doIfModifiedSince = PR_FALSE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the FORCE_VALIDATION flag is set, any cached data won't be used until
|
||||||
|
// it's revalidated with the server.
|
||||||
|
if (mLoadAttributes & nsIChannel::FORCE_VALIDATION) {
|
||||||
|
doIfModifiedSince = PR_TRUE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the Vary header. Per comments on bug 37609, most of the request
|
||||||
|
// headers that we generate do not vary with the exception of Accept-Charset
|
||||||
|
// and Accept-Language, so we force validation only if these headers or "*"
|
||||||
|
// are listed with the Vary response header.
|
||||||
|
//
|
||||||
|
// XXX this may not be sufficient if embedders start tweaking or adding HTTP
|
||||||
|
// request headers.
|
||||||
|
//
|
||||||
|
// XXX will need to add the Accept header to this list if we start sending
|
||||||
|
// a full Accept header, since the addition of plugins could change this
|
||||||
|
// header (see bug 58040).
|
||||||
|
//
|
||||||
|
mCachedResponse->GetHeader(nsHTTPAtoms::Vary, getter_Copies(str));
|
||||||
|
if (str) {
|
||||||
|
nsSubsumeCStr haystack((char *) (const char *) str, PR_FALSE);
|
||||||
|
if ((haystack.Find("*", PR_TRUE) != kNotFound) ||
|
||||||
|
(haystack.Find("accept-charset", PR_TRUE) != kNotFound) ||
|
||||||
|
(haystack.Find("accept-language", PR_TRUE) != kNotFound)) {
|
||||||
|
doIfModifiedSince = PR_TRUE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if this is the first time that this cache entry has been
|
||||||
|
// accessed in this session.
|
||||||
|
{
|
||||||
|
PRBool firstAccessThisSession;
|
||||||
|
PRTime sessionStartTime, lastWritten, expirationTime, now = PR_Now();
|
||||||
|
|
||||||
|
rv = mCacheEntry->GetLastModified(&lastWritten);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = mCacheEntry->GetExpirationTime(&expirationTime);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
sessionStartTime = mHandler->GetSessionStartTime();
|
||||||
|
if (LL_UCMP(sessionStartTime, > ,lastWritten))
|
||||||
|
firstAccessThisSession = PR_TRUE;
|
||||||
|
|
||||||
|
// Check to see if we can use the cache data without revalidating
|
||||||
|
// it with the server.
|
||||||
|
//PRBool useHeuristicExpiration =
|
||||||
|
// mLoadAttributes & nsIChannel::VALIDATE_HEURISTICALLY;
|
||||||
|
|
||||||
|
// If the content is stale, issue an if-modified-since request
|
||||||
|
if (LL_UCMP(now, >, expirationTime)) {
|
||||||
|
if (mLoadAttributes & nsIChannel::VALIDATE_ONCE_PER_SESSION)
|
||||||
|
doIfModifiedSince = firstAccessThisSession;
|
||||||
|
else
|
||||||
|
// VALIDATE_ALWAYS || VALIDATE_HEURISTICALLY || default
|
||||||
|
doIfModifiedSince = PR_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (doIfModifiedSince) {
|
||||||
|
SetRequestHeader(nsHTTPAtoms::If_Modified_Since, lastModified);
|
||||||
|
|
||||||
|
// Add If-None-Match header if an ETag was given in the response
|
||||||
|
mCachedResponse->GetHeader(nsHTTPAtoms::ETag, getter_Copies(str));
|
||||||
|
if (str)
|
||||||
|
SetRequestHeader(nsHTTPAtoms::If_None_Match, str);
|
||||||
|
|
||||||
|
// Specify the need to validate this cache entry with the server.
|
||||||
|
mCachedContentIsValid = PR_FALSE;
|
||||||
|
}
|
||||||
|
else if (mCacheAccess & nsICache::ACCESS_WRITE)
|
||||||
|
// We have write access to the cache, but we don't need to go to the
|
||||||
|
// server to validate at this time, so just mark the cache entry as
|
||||||
|
// valid to allow others access to this cache entry.
|
||||||
|
mCacheEntry->MarkValid();
|
||||||
|
|
||||||
|
LOG(("nsHTTPChannel::CheckCache [this=%x if-modified-since=%d"
|
||||||
|
" cache-entry-is-valid=%d]\n",
|
||||||
|
this, doIfModifiedSince, mCachedContentIsValid));
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the data in the cache hasn't expired, then there's no need to
|
||||||
|
// talk with the server, not even to do an if-modified-since. This
|
||||||
|
// method creates a stream from the cache, synthesizing all the various
|
||||||
|
// channel-related events.
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::ReadFromCache()
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_FAILURE);
|
||||||
|
NS_ENSURE_TRUE(mCachedContentIsValid, NS_ERROR_FAILURE);
|
||||||
|
NS_ENSURE_TRUE(mCachedResponse, NS_ERROR_FAILURE);
|
||||||
|
NS_ENSURE_TRUE(mResponseDataListener, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
LOG(("nsHTTPChannel::ReadFromCache [this=%x] "
|
||||||
|
"Using cache copy for: %s\n", this, mRequest->Spec()));
|
||||||
|
|
||||||
|
// Get a transport to the cached data...
|
||||||
|
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
|
||||||
|
|
||||||
|
// Fake it so that HTTP headers come from cached versions
|
||||||
|
SetResponse(mCachedResponse);
|
||||||
|
|
||||||
|
// Create a listener that intercepts cache reads and fires off
|
||||||
|
// the appropriate events such as OnHeadersAvailable
|
||||||
|
nsHTTPResponseListener *listener
|
||||||
|
= new nsHTTPCacheListener(this, mHandler);
|
||||||
|
if (!listener)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
NS_ADDREF(listener);
|
||||||
|
|
||||||
|
listener->SetListener(mResponseDataListener);
|
||||||
|
mConnected = PR_TRUE;
|
||||||
|
|
||||||
|
// Fire all the normal events for header arrival
|
||||||
|
FinishedResponseHeaders();
|
||||||
|
|
||||||
|
// Pump the cache data downstream
|
||||||
|
LOG(("\n>>>> Reading from Cache <<<<\n"));
|
||||||
|
rv = mCacheTransport->AsyncRead(listener, mResponseContext,
|
||||||
|
0, ULONG_MAX, 0,
|
||||||
|
getter_AddRefs(mCacheReadRequest));
|
||||||
|
|
||||||
|
NS_RELEASE(listener);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
ResponseCompleted(nsnull, rv, nsnull);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::CacheAbort(PRUint32 statusCode)
|
||||||
|
{
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (mCacheEntry) {
|
||||||
|
LOG(("nsHTTPChannel::CacheAbort [this=%x status=%d] "
|
||||||
|
"Dooming cache entry!\n", this, statusCode));
|
||||||
|
|
||||||
|
rv = mCacheEntry->Doom();
|
||||||
|
|
||||||
|
mCacheReadRequest = 0;
|
||||||
|
mCacheTransport = 0;
|
||||||
|
mCacheEntry = 0;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the network response from the server, including both the content and
|
||||||
|
// the HTTP headers.
|
||||||
|
nsresult
|
||||||
|
nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
|
nsIStreamListener **aResult)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
nsXPIDLCString str;
|
||||||
|
|
||||||
|
NS_ENSURE_ARG_POINTER(aListener);
|
||||||
|
|
||||||
|
// Don't cache the response again if already cached... FinishResponseHeaders
|
||||||
|
// calls ProcessStatusCode for handling cached redirects.
|
||||||
|
if (mCachedContentIsValid)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
// If caching is disabled, there will be no cache entry
|
||||||
|
if (!mCacheEntry)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
LOG(("nsHTTPChannel::CacheReceivedResponse [this=%x entry=%x]\n",
|
||||||
|
this, mCacheEntry.get()));
|
||||||
|
|
||||||
|
// Store secure data in memory only
|
||||||
|
nsCOMPtr<nsISupports> securityInfo;
|
||||||
|
rv = GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||||
|
if (NS_SUCCEEDED(rv) && securityInfo)
|
||||||
|
mCacheEntry->SetSecurityInfo(securityInfo);
|
||||||
|
|
||||||
|
// The no-store directive within the 'Cache-Control:' header indicates
|
||||||
|
// that we should not store the response in the cache
|
||||||
|
rv = GetResponseHeader(nsHTTPAtoms::Cache_Control, getter_Copies(str));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
if (str) {
|
||||||
|
nsSubsumeCStr ss((char *) (const char *) str, PR_FALSE);
|
||||||
|
if (ss.Find("no-store", PR_TRUE) != kNotFound) {
|
||||||
|
LOG(("Not caching since response has \"Cache-Control: no-store\"\n"));
|
||||||
|
goto dont_cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Although 'Pragma:no-cache' is not a standard HTTP response header (it's
|
||||||
|
// a request header), caching is inhibited when this header is present so
|
||||||
|
// as to match existing Navigator behavior.
|
||||||
|
rv = GetResponseHeader(nsHTTPAtoms::Pragma, getter_Copies(str));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
if (str) {
|
||||||
|
nsSubsumeCStr ss((char *) (const char *) str, PR_FALSE);
|
||||||
|
if (ss.Find("no-cache", PR_TRUE) != kNotFound) {
|
||||||
|
LOG(("Not caching since response has \"Pragma: no-cache\"\n"));
|
||||||
|
goto dont_cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the expiration time for this cache entry
|
||||||
|
rv = UpdateExpirationTime();
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// Store the received HTTP headers with the cache entry as an element of
|
||||||
|
// the meta data.
|
||||||
|
{
|
||||||
|
nsCString allHeaders;
|
||||||
|
rv = mResponse->EmitHeaders(allHeaders);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = mCacheEntry->SetMetaDataElement("headers", allHeaders.get());
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open an output stream to the cache entry and insert a listener tee into
|
||||||
|
// the chain of response listeners.
|
||||||
|
{
|
||||||
|
LOG(("Preparing to write data into the cache [url=%s]\n", mRequest->Spec()));
|
||||||
|
|
||||||
|
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIOutputStream> out;
|
||||||
|
rv = mCacheTransport->OpenOutputStream(0, ULONG_MAX, 0, getter_AddRefs(out));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// Mark entry valid inorder to allow simultaneous reading...
|
||||||
|
rv = mCacheEntry->MarkValid();
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIStreamListenerTee> tee =
|
||||||
|
do_CreateInstance(kStreamListenerTeeCID, &rv);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = tee->Init(aListener, out);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
return CallQueryInterface(tee, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
dont_cache:
|
||||||
|
CacheAbort(0);
|
||||||
|
*aResult = nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
//
|
||||||
// Create a cache entry for the channel's URL or retrieve an existing one. If
|
// Create a cache entry for the channel's URL or retrieve an existing one. If
|
||||||
// there's an existing cache entry for the current URL, confirm that it doesn't
|
// there's an existing cache entry for the current URL, confirm that it doesn't
|
||||||
// contain partially downloaded content. Finally, check to see if the cache
|
// contain partially downloaded content. Finally, check to see if the cache
|
||||||
|
@ -825,19 +1391,6 @@ nsHTTPChannel::CheckCache()
|
||||||
if ((mP != nsHTTPAtoms::Get) && (mP != nsHTTPAtoms::Head))
|
if ((mP != nsHTTPAtoms::Get) && (mP != nsHTTPAtoms::Head))
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
if (!mCacheEntry)
|
|
||||||
return NS_OK; // failed to open a cache entry
|
|
||||||
|
|
||||||
if (!(mCacheAccess & nsICache::ACCESS_READ))
|
|
||||||
return NS_OK; // no data to read... must go to net
|
|
||||||
|
|
||||||
// consider load attributes that effect storage policy
|
|
||||||
//if (mLoadAttributes & nsIChannel::CACHE_AS_FILE)
|
|
||||||
// mCacheEntry->SetStoragePolicy(nsICache::STORE_ON_DISK_AS_FILE);
|
|
||||||
//else if (mLoadAttributes & nsIChannel::INHIBIT_PERSISTENT_CACHING)
|
|
||||||
// mCacheEntry->SetStoragePolicy(nsICache::STORE_IN_MEMORY);
|
|
||||||
#else
|
|
||||||
// If this is the first time we've been called for this channel,
|
// If this is the first time we've been called for this channel,
|
||||||
// retrieve an existing cache entry or create a new one.
|
// retrieve an existing cache entry or create a new one.
|
||||||
if (!mCacheEntry) {
|
if (!mCacheEntry) {
|
||||||
|
@ -904,7 +1457,6 @@ nsHTTPChannel::CheckCache()
|
||||||
streamAsFile->AddObserver(observer);
|
streamAsFile->AddObserver(observer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Be pessimistic: Clear If-Modified-Since request header
|
// Be pessimistic: Clear If-Modified-Since request header
|
||||||
SetRequestHeader(nsHTTPAtoms::If_Modified_Since, 0);
|
SetRequestHeader(nsHTTPAtoms::If_Modified_Since, 0);
|
||||||
|
@ -915,11 +1467,6 @@ nsHTTPChannel::CheckCache()
|
||||||
if (mLoadAttributes & nsIChannel::FORCE_RELOAD)
|
if (mLoadAttributes & nsIChannel::FORCE_RELOAD)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
nsXPIDLCString cachedHeaders;
|
|
||||||
rv = mCacheEntry->GetMetaDataElement("headers", getter_Copies(cachedHeaders));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
#else
|
|
||||||
// Due to architectural limitations in the cache manager, a cache entry can
|
// Due to architectural limitations in the cache manager, a cache entry can
|
||||||
// not be accessed if it is currently being updated by another HTTP
|
// not be accessed if it is currently being updated by another HTTP
|
||||||
// request. If that's the case, we ignore the cache entry for purposes of
|
// request. If that's the case, we ignore the cache entry for purposes of
|
||||||
|
@ -948,7 +1495,6 @@ nsHTTPChannel::CheckCache()
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
if (!cachedHeadersLength)
|
if (!cachedHeadersLength)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
#endif
|
|
||||||
|
|
||||||
// Parse the cached HTTP headers
|
// Parse the cached HTTP headers
|
||||||
NS_IF_RELEASE(mCachedResponse);
|
NS_IF_RELEASE(mCachedResponse);
|
||||||
|
@ -1019,23 +1565,16 @@ nsHTTPChannel::CheckCache()
|
||||||
// accessed in this session.
|
// accessed in this session.
|
||||||
PRBool firstAccessThisSession;
|
PRBool firstAccessThisSession;
|
||||||
PRTime sessionStartTime, lastAccessTime;
|
PRTime sessionStartTime, lastAccessTime;
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
mCacheEntry->GetLastFetched(&lastAccessTime);
|
|
||||||
#else
|
|
||||||
PRTime lastUpdateTime;
|
PRTime lastUpdateTime;
|
||||||
mCacheEntry->GetLastAccessTime(&lastAccessTime);
|
mCacheEntry->GetLastAccessTime(&lastAccessTime);
|
||||||
mCacheEntry->GetLastUpdateTime(&lastUpdateTime);
|
mCacheEntry->GetLastUpdateTime(&lastUpdateTime);
|
||||||
#endif
|
|
||||||
|
|
||||||
sessionStartTime = mHandler->GetSessionStartTime();
|
sessionStartTime = mHandler->GetSessionStartTime();
|
||||||
if (LL_UCMP(sessionStartTime, > ,lastAccessTime))
|
if (LL_UCMP(sessionStartTime, > ,lastAccessTime))
|
||||||
firstAccessThisSession = PR_TRUE;
|
firstAccessThisSession = PR_TRUE;
|
||||||
|
|
||||||
#ifndef MOZ_NEW_CACHE // XXX what is the logic here?
|
|
||||||
else
|
else
|
||||||
firstAccessThisSession = LL_UCMP(lastUpdateTime, >= ,lastAccessTime);
|
firstAccessThisSession = LL_UCMP(lastUpdateTime, >= ,lastAccessTime);
|
||||||
//-dp- this should be > as == means that this is the second access for this session.
|
//-dp- this should be > as == means that this is the second access for this session.
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check to see if we can use the cache data without revalidating
|
// Check to see if we can use the cache data without revalidating
|
||||||
// it with the server.
|
// it with the server.
|
||||||
|
@ -1084,6 +1623,7 @@ nsHTTPChannel::CheckCache()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// If the data in the cache hasn't expired, then there's no need to
|
// If the data in the cache hasn't expired, then there's no need to
|
||||||
// talk with the server, not even to do an if-modified-since. This
|
// talk with the server, not even to do an if-modified-since. This
|
||||||
// method creates a stream from the cache, synthesizing all the various
|
// method creates a stream from the cache, synthesizing all the various
|
||||||
|
@ -1106,10 +1646,6 @@ nsHTTPChannel::ReadFromCache()
|
||||||
LOG(("nsHTTPChannel::ReadFromCache [this=%x].\tUsing cache copy for: %s\n",
|
LOG(("nsHTTPChannel::ReadFromCache [this=%x].\tUsing cache copy for: %s\n",
|
||||||
this, mRequest->Spec()));
|
this, mRequest->Spec()));
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
// Get a transport to the cached data...
|
|
||||||
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
|
|
||||||
#else
|
|
||||||
// Create a cache transport to read the cached response...
|
// Create a cache transport to read the cached response...
|
||||||
rv = mCacheEntry->NewChannel(mLoadGroup, getter_AddRefs(mCacheChannel));
|
rv = mCacheEntry->NewChannel(mLoadGroup, getter_AddRefs(mCacheChannel));
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
@ -1118,7 +1654,6 @@ nsHTTPChannel::ReadFromCache()
|
||||||
// This will ensure that notifications are suppressed if necessary.
|
// This will ensure that notifications are suppressed if necessary.
|
||||||
rv = mCacheChannel->SetLoadAttributes(mLoadAttributes);
|
rv = mCacheChannel->SetLoadAttributes(mLoadAttributes);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fake it so that HTTP headers come from cached versions
|
// Fake it so that HTTP headers come from cached versions
|
||||||
SetResponse(mCachedResponse);
|
SetResponse(mCachedResponse);
|
||||||
|
@ -1138,14 +1673,7 @@ nsHTTPChannel::ReadFromCache()
|
||||||
FinishedResponseHeaders();
|
FinishedResponseHeaders();
|
||||||
|
|
||||||
// Pump the cache data downstream
|
// Pump the cache data downstream
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
LOG(("\n>>>> Reading from Cache <<<<\n"));
|
|
||||||
rv = mCacheTransport->AsyncRead(listener, mResponseContext,
|
|
||||||
0, ULONG_MAX, 0,
|
|
||||||
getter_AddRefs(mCacheReadRequest));
|
|
||||||
#else
|
|
||||||
rv = mCacheChannel->AsyncOpen(listener, mResponseContext);
|
rv = mCacheChannel->AsyncOpen(listener, mResponseContext);
|
||||||
#endif
|
|
||||||
|
|
||||||
NS_RELEASE(listener);
|
NS_RELEASE(listener);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
|
@ -1158,14 +1686,8 @@ nsHTTPChannel::CacheAbort(PRUint32 statusCode)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
if (mCacheEntry) {
|
if (mCacheEntry) {
|
||||||
LOG(("nsHTTPChannel::CacheAbort [this=%x] Dooming cache entry!\n", this));
|
LOG(("nsHTTPChannel::CacheAbort [this=%x status=%d]", this, statusCode));
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
// Doom the cache entry.
|
|
||||||
rv = mCacheEntry->Doom();
|
|
||||||
|
|
||||||
mCacheTransport = 0;
|
|
||||||
mCacheReadRequest = 0;
|
|
||||||
#else
|
|
||||||
// Set the stored content length to zero
|
// Set the stored content length to zero
|
||||||
rv = mCacheEntry->SetStoredContentLength(0);
|
rv = mCacheEntry->SetStoredContentLength(0);
|
||||||
|
|
||||||
|
@ -1184,7 +1706,6 @@ nsHTTPChannel::CacheAbort(PRUint32 statusCode)
|
||||||
mCacheEntry->SetUpdateInProgress(PR_TRUE);
|
mCacheEntry->SetUpdateInProgress(PR_TRUE);
|
||||||
mCacheEntry->SetUpdateInProgress(PR_FALSE);
|
mCacheEntry->SetUpdateInProgress(PR_FALSE);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Release our reference to it.
|
// Release our reference to it.
|
||||||
mCacheEntry = nsnull;
|
mCacheEntry = nsnull;
|
||||||
|
@ -1192,7 +1713,6 @@ nsHTTPChannel::CacheAbort(PRUint32 statusCode)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Cache the network response from the server, including both the content and
|
// Cache the network response from the server, including both the content and
|
||||||
// the HTTP headers.
|
// the HTTP headers.
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -1211,12 +1731,6 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> securityInfo;
|
nsCOMPtr<nsISupports> securityInfo;
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
// Store secure data in memory only
|
|
||||||
rv = GetSecurityInfo(getter_AddRefs(securityInfo));
|
|
||||||
if (NS_SUCCEEDED(rv) && securityInfo)
|
|
||||||
mCacheEntry->SetStoragePolicy(nsICache::STORE_IN_MEMORY);
|
|
||||||
#else
|
|
||||||
// ruslan/hack: don't cache secure connections in case of the persistent cache
|
// ruslan/hack: don't cache secure connections in case of the persistent cache
|
||||||
PRBool dontCache = (mCacheEntry->GetSecurityInfo(getter_AddRefs(securityInfo))
|
PRBool dontCache = (mCacheEntry->GetSecurityInfo(getter_AddRefs(securityInfo))
|
||||||
== NS_ERROR_NOT_IMPLEMENTED);
|
== NS_ERROR_NOT_IMPLEMENTED);
|
||||||
|
@ -1224,15 +1738,7 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
if (NS_SUCCEEDED(GetSecurityInfo(getter_AddRefs(securityInfo))) &&
|
if (NS_SUCCEEDED(GetSecurityInfo(getter_AddRefs(securityInfo))) &&
|
||||||
securityInfo && dontCache)
|
securityInfo && dontCache)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
//NS_ENSURE_TRUE(mCachedContentIsValid == PR_FALSE, NS_OK);
|
|
||||||
if (mCachedContentIsValid)
|
|
||||||
return NS_OK;
|
|
||||||
#else
|
|
||||||
// XXX why is this check necessary?
|
|
||||||
//
|
|
||||||
// If the current response is itself from the cache rather than the network
|
// If the current response is itself from the cache rather than the network
|
||||||
// server, don't allow it to overwrite itself.
|
// server, don't allow it to overwrite itself.
|
||||||
if (mCachedContentIsValid)
|
if (mCachedContentIsValid)
|
||||||
|
@ -1250,7 +1756,6 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// The no-store directive within the 'Cache-Control:' header indicates
|
// The no-store directive within the 'Cache-Control:' header indicates
|
||||||
// that we should not store the response in the cache
|
// that we should not store the response in the cache
|
||||||
|
@ -1282,7 +1787,6 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MOZ_NEW_CACHE
|
|
||||||
// Inhibit any other HTTP requests from writing into this cache entry
|
// Inhibit any other HTTP requests from writing into this cache entry
|
||||||
rv = mCacheEntry->SetUpdateInProgress(PR_TRUE);
|
rv = mCacheEntry->SetUpdateInProgress(PR_TRUE);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
@ -1291,7 +1795,6 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
// TODO - Set to true if server indicates that it supports byte ranges
|
// TODO - Set to true if server indicates that it supports byte ranges
|
||||||
rv = mCacheEntry->SetAllowPartial(PR_FALSE);
|
rv = mCacheEntry->SetAllowPartial(PR_FALSE);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (securityInfo)
|
if (securityInfo)
|
||||||
mCacheEntry->SetSecurityInfo(securityInfo);
|
mCacheEntry->SetSecurityInfo(securityInfo);
|
||||||
|
@ -1302,7 +1805,6 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
rv = mResponse->ParseDateHeader(nsHTTPAtoms::Last_Modified, &lastModified,
|
rv = mResponse->ParseDateHeader(nsHTTPAtoms::Last_Modified, &lastModified,
|
||||||
&lastModifiedHeaderIsPresent);
|
&lastModifiedHeaderIsPresent);
|
||||||
|
|
||||||
#ifndef MOZ_NEW_CACHE
|
|
||||||
// Check for corrupted, missing or malformed 'LastModified:' header
|
// Check for corrupted, missing or malformed 'LastModified:' header
|
||||||
if (NS_SUCCEEDED(rv) && lastModifiedHeaderIsPresent &&
|
if (NS_SUCCEEDED(rv) && lastModifiedHeaderIsPresent &&
|
||||||
!LL_IS_ZERO(lastModified)) {
|
!LL_IS_ZERO(lastModified)) {
|
||||||
|
@ -1310,7 +1812,6 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
// used for cache replacement policy decisions
|
// used for cache replacement policy decisions
|
||||||
mCacheEntry->SetLastModifiedTime(lastModified);
|
mCacheEntry->SetLastModifiedTime(lastModified);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Retrieve the value of the 'Expires:' header, if present
|
// Retrieve the value of the 'Expires:' header, if present
|
||||||
PRTime expires;
|
PRTime expires;
|
||||||
|
@ -1350,12 +1851,7 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
LL_SUB(heuristicStaleTime, date, lastModified);
|
LL_SUB(heuristicStaleTime, date, lastModified);
|
||||||
LL_USHR(heuristicStaleTime, heuristicStaleTime, 1);
|
LL_USHR(heuristicStaleTime, heuristicStaleTime, 1);
|
||||||
LL_ADD(heuristicStaleTime, heuristicStaleTime, date);
|
LL_ADD(heuristicStaleTime, heuristicStaleTime, date);
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
// XXX treat this as an estimate of the expiration time (for now)
|
|
||||||
mCacheEntry->SetExpirationTime(heuristicStaleTime);
|
|
||||||
#else
|
|
||||||
mCacheEntry->SetStaleTime(heuristicStaleTime);
|
mCacheEntry->SetStaleTime(heuristicStaleTime);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1363,37 +1859,7 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
nsCString allHeaders;
|
nsCString allHeaders;
|
||||||
rv = mResponse->EmitHeaders(allHeaders);
|
rv = mResponse->EmitHeaders(allHeaders);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
// Store all HTTP headers as a single meta data element
|
|
||||||
rv = mCacheEntry->SetMetaDataElement("headers", allHeaders.get());
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIOutputStream> out;
|
|
||||||
rv = mCacheTransport->OpenOutputStream(0, ULONG_MAX, 0, getter_AddRefs(out));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
// Mark entry valid inorder to allow simultaneous reading...
|
|
||||||
rv = mCacheEntry->MarkValid();
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Insert a listener tee into the chain that copies data into the
|
|
||||||
// transport's output stream.
|
|
||||||
//
|
|
||||||
nsCOMPtr<nsIStreamListenerTee> tee =
|
|
||||||
do_CreateInstance(kStreamListenerTeeCID, &rv);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
rv = tee->Init(aListener, out);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
LOG(("Preparing to write data into the cache [url=%s]\n", mRequest->Spec()));
|
|
||||||
|
|
||||||
return CallQueryInterface(tee, aResult);
|
|
||||||
#else
|
|
||||||
rv = mCacheEntry->SetAnnotation("HTTP headers",
|
rv = mCacheEntry->SetAnnotation("HTTP headers",
|
||||||
allHeaders.Length() + 1,
|
allHeaders.Length() + 1,
|
||||||
allHeaders.get());
|
allHeaders.get());
|
||||||
|
@ -1402,9 +1868,10 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||||
mCacheEntry->SetUpdateInProgress(PR_TRUE);
|
mCacheEntry->SetUpdateInProgress(PR_TRUE);
|
||||||
// Store the HTTP content data in the cache too
|
// Store the HTTP content data in the cache too
|
||||||
return mCacheEntry->InterceptAsyncRead(aListener, 0, aResult);
|
return mCacheEntry->InterceptAsyncRead(aListener, 0, aResult);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_NEW_CACHE
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHTTPChannel::Connect()
|
nsHTTPChannel::Connect()
|
||||||
{
|
{
|
||||||
|
@ -1588,6 +2055,10 @@ nsHTTPChannel::Connect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_NEW_CACHE
|
||||||
|
SetRequestTime(PR_Now());
|
||||||
|
#endif
|
||||||
|
|
||||||
mState = HS_WAITING_FOR_RESPONSE;
|
mState = HS_WAITING_FOR_RESPONSE;
|
||||||
mConnected = PR_TRUE;
|
mConnected = PR_TRUE;
|
||||||
|
|
||||||
|
@ -1628,7 +2099,7 @@ nsresult nsHTTPChannel::Redirect(const char *aNewLocation,
|
||||||
// Create a new URI using the Location header and the current URL
|
// Create a new URI using the Location header and the current URL
|
||||||
// as a base ...
|
// as a base ...
|
||||||
//
|
//
|
||||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
nsCOMPtr<nsIIOService> serv = do_GetIOService(&rv);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
if (aStatusCode == 305) { // Use-Proxy
|
if (aStatusCode == 305) { // Use-Proxy
|
||||||
|
@ -1649,27 +2120,6 @@ nsresult nsHTTPChannel::Redirect(const char *aNewLocation,
|
||||||
else {
|
else {
|
||||||
rv = serv->NewURI(aNewLocation, mURI, getter_AddRefs(newURI));
|
rv = serv->NewURI(aNewLocation, mURI, getter_AddRefs(newURI));
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
|
||||||
// removing redirect.xul for loop. bugs 44153, 56523, 58658
|
|
||||||
// XXX This is broken
|
|
||||||
#if 0
|
|
||||||
nsXPIDLCString spec1;
|
|
||||||
nsXPIDLCString spec2;
|
|
||||||
|
|
||||||
mURI -> GetSpec (getter_Copies (spec1));
|
|
||||||
newURI -> GetSpec (getter_Copies (spec2));
|
|
||||||
|
|
||||||
if (!PL_strcmp (spec1, spec2))
|
|
||||||
{
|
|
||||||
// loop detected
|
|
||||||
// ruslan/24884
|
|
||||||
rv = serv->NewURI(LOOPING_REDIRECT_ERROR_URI, mURI, getter_AddRefs(newURI));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
|
|
||||||
checkSecurity = PR_FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1832,6 +2282,8 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIStreamListener *aListener,
|
||||||
// We have covered the server errors elsewhere. On DNS error, do CacheAbort().
|
// We have covered the server errors elsewhere. On DNS error, do CacheAbort().
|
||||||
CacheAbort(aStatus);
|
CacheAbort(aStatus);
|
||||||
}
|
}
|
||||||
|
#ifndef MOZ_NEW_CACHE
|
||||||
|
// XXX this is a redundant check
|
||||||
else {
|
else {
|
||||||
// The no-store directive within the 'Cache-Control:' header indicates
|
// The no-store directive within the 'Cache-Control:' header indicates
|
||||||
// that we should not store the response in the cache
|
// that we should not store the response in the cache
|
||||||
|
@ -1863,14 +2315,10 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIStreamListener *aListener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
|
||||||
if (dontCache)
|
|
||||||
mCacheEntry->Doom();
|
|
||||||
#else
|
|
||||||
if (dontCache)
|
if (dontCache)
|
||||||
mCacheEntry->SetStoredContentLength(0);
|
mCacheEntry->SetStoredContentLength(0);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1881,8 +2329,8 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIStreamListener *aListener,
|
||||||
rv = aListener->OnStopRequest(this, mResponseContext, aStatus, aStatusArg);
|
rv = aListener->OnStopRequest(this, mResponseContext, aStatus, aStatusArg);
|
||||||
|
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
LOG(("nsHTTPChannel::OnStopRequest(...) [this=%x]."
|
LOG(("nsHTTPChannel::OnStopRequest(...) [this=%x] "
|
||||||
"\tOnStopRequest to consumer failed! Status:%x\n", this, rv));
|
"OnStopRequest to consumer failed! Status:%x\n", this, rv));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
#ifdef MOZ_NEW_CACHE
|
||||||
|
@ -2005,7 +2453,7 @@ nsHTTPChannel::Authenticate(const char *aChallenge, PRBool aProxyAuth)
|
||||||
if (!aChallenge)
|
if (!aChallenge)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
nsCOMPtr<nsIIOService> serv = do_GetIOService(&rv);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
// Flush out existing records of this URI in authengine-
|
// Flush out existing records of this URI in authengine-
|
||||||
|
@ -2495,6 +2943,12 @@ nsHTTPChannel::ProcessNotModifiedResponse(nsIStreamListener *aListener)
|
||||||
#ifdef MOZ_NEW_CACHE
|
#ifdef MOZ_NEW_CACHE
|
||||||
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
|
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = UpdateExpirationTime();
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = mCacheEntry->MarkValid();
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
#else
|
#else
|
||||||
// Create a cache transport to read the cached response...
|
// Create a cache transport to read the cached response...
|
||||||
rv = mCacheEntry->NewChannel(mLoadGroup, getter_AddRefs(mCacheChannel));
|
rv = mCacheEntry->NewChannel(mLoadGroup, getter_AddRefs(mCacheChannel));
|
||||||
|
|
|
@ -139,6 +139,15 @@ protected:
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
#ifdef MOZ_NEW_CACHE
|
||||||
nsresult OpenCacheEntry();
|
nsresult OpenCacheEntry();
|
||||||
|
|
||||||
|
nsresult GetRequestTime(PRTime *);
|
||||||
|
nsresult SetRequestTime(PRTime);
|
||||||
|
nsresult GetResponseTime(PRTime *);
|
||||||
|
nsresult SetResponseTime(PRTime);
|
||||||
|
|
||||||
|
nsresult ComputeCurrentAge(PRTime now, PRUint32 *);
|
||||||
|
nsresult ComputeFreshnessLifetime(PRUint32 *);
|
||||||
|
nsresult UpdateExpirationTime();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsresult CheckCache();
|
nsresult CheckCache();
|
||||||
|
@ -238,7 +247,9 @@ protected:
|
||||||
PRPackedBool mOpenHasEventQueue;
|
PRPackedBool mOpenHasEventQueue;
|
||||||
|
|
||||||
// Cache-related flags
|
// Cache-related flags
|
||||||
|
#ifndef MOZ_NEW_CACHE
|
||||||
PRPackedBool mCachedContentIsAvailable;
|
PRPackedBool mCachedContentIsAvailable;
|
||||||
|
#endif
|
||||||
PRPackedBool mCachedContentIsValid;
|
PRPackedBool mCachedContentIsValid;
|
||||||
|
|
||||||
// Called OnHeadersAvailable()
|
// Called OnHeadersAvailable()
|
||||||
|
|
|
@ -1038,13 +1038,13 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
|
||||||
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
nsLoadFlags flags = nsIChannel::LOAD_NORMAL;
|
nsLoadFlags loadFlags = nsIChannel::LOAD_NORMAL;
|
||||||
i_Channel->GetLoadAttributes(&flags);
|
i_Channel->GetLoadAttributes(&loadFlags);
|
||||||
|
|
||||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||||
i_Channel->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
i_Channel->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||||
trans->SetNotificationCallbacks(callbacks,
|
trans->SetNotificationCallbacks(callbacks,
|
||||||
(flags & nsIChannel::LOAD_BACKGROUND));
|
(loadFlags & nsIChannel::LOAD_BACKGROUND));
|
||||||
|
|
||||||
nsCOMPtr<nsISocketTransport> socketTrans = do_QueryInterface(trans, &rv);
|
nsCOMPtr<nsISocketTransport> socketTrans = do_QueryInterface(trans, &rv);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
@ -1747,30 +1747,54 @@ nsHTTPHandler::GetProxySSLConnectAllowed (PRBool *a_Allowed)
|
||||||
#ifdef MOZ_NEW_CACHE
|
#ifdef MOZ_NEW_CACHE
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHTTPHandler::GetCacheSession(nsICacheSession **result)
|
nsHTTPHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy, nsICacheSession **result)
|
||||||
{
|
{
|
||||||
if (!mCacheSession) {
|
static PRBool checkedPref = PR_FALSE;
|
||||||
|
static PRBool useCache = PR_TRUE;
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
if (!checkedPref) {
|
||||||
|
// XXX should register a prefs changed callback for this
|
||||||
nsCOMPtr<nsIPref> prefs = do_GetService(kPrefServiceCID, &rv);
|
nsCOMPtr<nsIPref> prefs = do_GetService(kPrefServiceCID, &rv);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
// Skip cache if disabled in preferences
|
|
||||||
PRBool useCache = PR_FALSE;
|
|
||||||
prefs->GetBoolPref("browser.cache.enable", &useCache);
|
prefs->GetBoolPref("browser.cache.enable", &useCache);
|
||||||
|
|
||||||
|
checkedPref = PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip cache if disabled in preferences
|
||||||
if (!useCache)
|
if (!useCache)
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
if (!mCacheSession_ANY) {
|
||||||
nsCOMPtr<nsICacheService> serv = do_GetService(kCacheServiceCID, &rv);
|
nsCOMPtr<nsICacheService> serv = do_GetService(kCacheServiceCID, &rv);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
rv = serv->CreateSession("HTTP",
|
rv = serv->CreateSession("HTTP",
|
||||||
nsICache::STORE_ANYWHERE,
|
nsICache::STORE_ANYWHERE,
|
||||||
nsICache::STREAM_BASED,
|
nsICache::STREAM_BASED,
|
||||||
getter_AddRefs(mCacheSession));
|
getter_AddRefs(mCacheSession_ANY));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = mCacheSession_ANY->SetDoomEntriesIfExpired(PR_FALSE);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = serv->CreateSession("HTTP-memory-only",
|
||||||
|
nsICache::STORE_IN_MEMORY,
|
||||||
|
nsICache::STREAM_BASED,
|
||||||
|
getter_AddRefs(mCacheSession_MEM));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = mCacheSession_MEM->SetDoomEntriesIfExpired(PR_FALSE);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
}
|
}
|
||||||
NS_ADDREF(*result = mCacheSession);
|
|
||||||
|
if (storagePolicy == nsICache::STORE_IN_MEMORY)
|
||||||
|
NS_ADDREF(*result = mCacheSession_MEM);
|
||||||
|
else
|
||||||
|
NS_ADDREF(*result = mCacheSession_ANY);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,7 @@ public:
|
||||||
nsresult GetProxySSLConnectAllowed (PRBool *a_Allowed);
|
nsresult GetProxySSLConnectAllowed (PRBool *a_Allowed);
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
#ifdef MOZ_NEW_CACHE
|
||||||
nsresult GetCacheSession(nsICacheSession **);
|
nsresult GetCacheSession(nsCacheStoragePolicy, nsICacheSession **);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -163,7 +163,8 @@ protected:
|
||||||
nsCOMPtr<nsISupportsArray> mIdleTransports;
|
nsCOMPtr<nsISupportsArray> mIdleTransports;
|
||||||
|
|
||||||
#ifdef MOZ_NEW_CACHE
|
#ifdef MOZ_NEW_CACHE
|
||||||
nsCOMPtr<nsICacheSession> mCacheSession;
|
nsCOMPtr<nsICacheSession> mCacheSession_ANY;
|
||||||
|
nsCOMPtr<nsICacheSession> mCacheSession_MEM;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* mAcceptLanguages;
|
char* mAcceptLanguages;
|
||||||
|
|
|
@ -137,27 +137,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual ~nsHTTPRequest();
|
virtual ~nsHTTPRequest();
|
||||||
|
|
||||||
// Use a method string corresponding to the method.
|
|
||||||
const char* MethodToString(HTTPMethod i_Method=HM_GET)
|
|
||||||
{
|
|
||||||
static const char methods[][TOTAL_NUMBER_OF_METHODS] =
|
|
||||||
{
|
|
||||||
"DELETE ",
|
|
||||||
"GET ",
|
|
||||||
"HEAD ",
|
|
||||||
"INDEX ",
|
|
||||||
"LINK ",
|
|
||||||
"OPTIONS ",
|
|
||||||
"POST ",
|
|
||||||
"PUT ",
|
|
||||||
"PATCH ",
|
|
||||||
"TRACE ",
|
|
||||||
"UNLINK "
|
|
||||||
};
|
|
||||||
|
|
||||||
return methods[i_Method];
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIAtom> mMethod;
|
nsCOMPtr<nsIAtom> mMethod;
|
||||||
PRUint32 mVersion;
|
PRUint32 mVersion;
|
||||||
PRUint32 mKeepAliveTimeout;
|
PRUint32 mKeepAliveTimeout;
|
||||||
|
|
|
@ -506,6 +506,7 @@ nsresult nsHTTPResponse::ParseDateHeader(nsIAtom *aAtom,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Return the value of the (HTTP 1.1) max-age directive, which itself is a
|
// Return the value of the (HTTP 1.1) max-age directive, which itself is a
|
||||||
// component of the Cache-Control response header
|
// component of the Cache-Control response header
|
||||||
nsresult nsHTTPResponse::GetMaxAge(PRUint32* aMaxAge, PRBool* aMaxAgeIsPresent)
|
nsresult nsHTTPResponse::GetMaxAge(PRUint32* aMaxAge, PRBool* aMaxAgeIsPresent)
|
||||||
|
@ -558,6 +559,13 @@ PRBool nsHTTPResponse::IsStale(PRBool aUseHeuristicExpiration)
|
||||||
nsMemory::Free(cacheControlHeader);
|
nsMemory::Free(cacheControlHeader);
|
||||||
if (header.Find("no-cache", PR_TRUE) != kNotFound)
|
if (header.Find("no-cache", PR_TRUE) != kNotFound)
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
|
#ifdef MOZ_NEW_CACHE
|
||||||
|
// If the must-revalidate directive is present in the cached response,
|
||||||
|
// data must always be revalidated with the server, even if the user
|
||||||
|
// has configured validation to be turned off.
|
||||||
|
if (header.Find("must-revalidate", PR_TRUE) != kNotFound)
|
||||||
|
return PR_TRUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value of the 'Date:' header
|
// Get the value of the 'Date:' header
|
||||||
|
@ -615,8 +623,13 @@ PRBool nsHTTPResponse::IsStale(PRBool aUseHeuristicExpiration)
|
||||||
if (expiresHeaderIsPresent) {
|
if (expiresHeaderIsPresent) {
|
||||||
// Otherwise, if Expires is present in the response,
|
// Otherwise, if Expires is present in the response,
|
||||||
// the calculation is:
|
// the calculation is:
|
||||||
if ( ( now > date ? now : date ) < expires )
|
#ifdef MOZ_NEW_CACHE
|
||||||
|
if (currentAge < expires - date)
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
#else
|
||||||
|
if ( ( now > date ? now : date ) < expires )
|
||||||
|
return PR_FALSE; // XXX "date" should always be less than "expires"
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,3 +890,43 @@ nsresult nsHTTPResponse::UpdateHeaders(nsISimpleEnumerator *aEnumerator)
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_NEW_CACHE
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHTTPResponse::GetAgeValue(PRUint32 *result, PRBool *isAvail)
|
||||||
|
{
|
||||||
|
nsXPIDLCString str;
|
||||||
|
nsresult rv = GetHeader(nsHTTPAtoms::Age, getter_Copies(str));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
*isAvail = PR_FALSE;
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*isAvail = PR_TRUE;
|
||||||
|
*result = (PRUint32) atol(str.get());
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHTTPResponse::GetDateValue(PRTime *result, PRBool *isAvail)
|
||||||
|
{
|
||||||
|
return ParseDateHeader(nsHTTPAtoms::Date, result, isAvail);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHTTPResponse::GetLastModifiedValue(PRTime *result, PRBool *isAvail)
|
||||||
|
{
|
||||||
|
return ParseDateHeader(nsHTTPAtoms::Last_Modified, result, isAvail);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHTTPResponse::GetExpiresValue(PRTime *result, PRBool *isAvail)
|
||||||
|
{
|
||||||
|
return ParseDateHeader(nsHTTPAtoms::Expires, result, isAvail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -17,13 +17,12 @@
|
||||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Original Author: Gagan Saksena <gagan@netscape.com>
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Gagan Saksena <gagan@netscape.com> (original author)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _nsHTTPResponse_h_
|
#ifndef nsHTTPResponse_h__
|
||||||
#define _nsHTTPResponse_h_
|
#define nsHTTPResponse_h__
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIAtom.h"
|
#include "nsIAtom.h"
|
||||||
|
@ -86,10 +85,17 @@ public:
|
||||||
|
|
||||||
nsresult ParseDateHeader(nsIAtom *aAtom, PRTime *aResultTime, PRBool *aHeaderIsPresent);
|
nsresult ParseDateHeader(nsIAtom *aAtom, PRTime *aResultTime, PRBool *aHeaderIsPresent);
|
||||||
|
|
||||||
|
#ifdef MOZ_NEW_CACHE
|
||||||
|
nsresult GetAgeValue(PRUint32 *, PRBool *isAvail);
|
||||||
|
nsresult GetDateValue(PRTime *, PRBool *isAvail);
|
||||||
|
nsresult GetLastModifiedValue(PRTime *, PRBool *isAvail);
|
||||||
|
nsresult GetExpiresValue(PRTime *, PRBool *isAvail);
|
||||||
|
#endif
|
||||||
|
nsresult GetMaxAge(PRUint32 *, PRBool *isAvail);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~nsHTTPResponse();
|
virtual ~nsHTTPResponse();
|
||||||
nsresult ParseDateHeader(nsIAtom *aAtom, PRUint32 *aResultTime, PRBool *aHeaderIsPresent);
|
nsresult ParseDateHeader(nsIAtom *aAtom, PRUint32 *aResultTime, PRBool *aHeaderIsPresent);
|
||||||
nsresult GetMaxAge(PRUint32* aMaxAge, PRBool* aMaxAgeIsPresent);
|
|
||||||
|
|
||||||
HTTPVersion mServerVersion;
|
HTTPVersion mServerVersion;
|
||||||
nsCString mStatusString;
|
nsCString mStatusString;
|
||||||
|
@ -100,4 +106,4 @@ protected:
|
||||||
nsHTTPHeaderArray mHeaders;
|
nsHTTPHeaderArray mHeaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _nsHTTPResponse_h_ */
|
#endif /* nsHTTPResponse_h__ */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче