зеркало из https://github.com/mozilla/gecko-dev.git
Patch to finalize necko loadFlags and fix HTTP validation correctness w.r.t.
cache validation preferences and browsing via history. r=gagan,gordon. Fixes several bugs that I would mention here if bugzilla weren't down ;-)
This commit is contained in:
Родитель
48b4fc668c
Коммит
9deb4986e3
|
@ -98,7 +98,7 @@ NS_IMETHODIMP nsDSURIContentListener::DoContent(const char* aContentType,
|
|||
PRUint32 loadType = mDocShell->ConvertDocShellLoadInfoToLoadType((nsDocShellInfoLoadType) aCommand);
|
||||
mDocShell->SetLoadType(loadType);
|
||||
|
||||
if(loadFlags & nsIRequest::LOAD_RETARGETED_DOCUMENT_URI)
|
||||
if(loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
|
||||
{
|
||||
mDocShell->StopLoad();
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ NS_IMETHODIMP nsDSURIContentListener::DoContent(const char* aContentType,
|
|||
request, aContentHandler);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE; // it's okay if we don't know how to handle the content
|
||||
|
||||
if(loadFlags & nsIRequest::LOAD_RETARGETED_DOCUMENT_URI)
|
||||
if(loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
|
||||
mDocShell->SetFocus();
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -2847,7 +2847,7 @@ NS_IMETHODIMP nsDocShell::CreateContentViewer(const char* aContentType,
|
|||
|
||||
// Mark the channel as being a document URI...
|
||||
aOpenedChannel->GetLoadFlags(&loadFlags);
|
||||
loadFlags |= nsIRequest::LOAD_DOCUMENT_URI;
|
||||
loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
|
||||
|
||||
aOpenedChannel->SetLoadFlags(loadFlags);
|
||||
|
||||
|
@ -3592,34 +3592,32 @@ NS_IMETHODIMP nsDocShell::DoChannelLoad(nsIChannel *aChannel, nsURILoadCommand a
|
|||
// Mark the channel as being a document URI...
|
||||
nsLoadFlags loadFlags = 0;
|
||||
(void)aChannel->GetLoadFlags(&loadFlags);
|
||||
loadFlags |= nsIRequest::LOAD_DOCUMENT_URI;
|
||||
loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
|
||||
|
||||
// "View source" always wants VALIDATE_NEVER.
|
||||
// "View source" always wants the currently cached content.
|
||||
if ( mViewMode == viewSource ) {
|
||||
loadFlags |= nsIRequest::VALIDATE_NEVER;
|
||||
loadFlags |= nsIRequest::LOAD_FROM_CACHE;
|
||||
} else {
|
||||
// Load attributes depend on load type...
|
||||
switch ( mLoadType )
|
||||
{
|
||||
case LOAD_HISTORY:
|
||||
loadFlags |= nsIRequest::VALIDATE_NEVER;
|
||||
loadFlags |= nsIRequest::LOAD_FROM_CACHE;
|
||||
break;
|
||||
|
||||
case LOAD_RELOAD_NORMAL:
|
||||
loadFlags |= nsIRequest::FORCE_VALIDATION;
|
||||
loadFlags |= nsIRequest::VALIDATE_ALWAYS;
|
||||
break;
|
||||
|
||||
case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
|
||||
loadFlags |= nsIRequest::FORCE_RELOAD;
|
||||
break;
|
||||
case LOAD_REFRESH:
|
||||
loadFlags |= nsIRequest::FORCE_RELOAD;
|
||||
loadFlags |= nsIRequest::LOAD_BYPASS_CACHE;
|
||||
break;
|
||||
case LOAD_NORMAL:
|
||||
case LOAD_LINK:
|
||||
// Set cache checking flags
|
||||
if ( mPrefs )
|
||||
{
|
||||
// Set cache checking flags
|
||||
if ( mPrefs )
|
||||
{
|
||||
PRInt32 prefSetting;
|
||||
if ( NS_SUCCEEDED( mPrefs->GetIntPref( "browser.cache.check_doc_frequency" , &prefSetting) ) )
|
||||
{
|
||||
|
@ -3636,8 +3634,8 @@ NS_IMETHODIMP nsDocShell::DoChannelLoad(nsIChannel *aChannel, nsURILoadCommand a
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3974,7 +3972,7 @@ NS_IMETHODIMP nsDocShell::OnLoadingSite(nsIChannel* aChannel)
|
|||
// overrides it. Until OnRedirect() gets settles out, let us do this.
|
||||
nsLoadFlags loadFlags = 0;
|
||||
aChannel->GetLoadFlags(&loadFlags);
|
||||
if (loadFlags & nsIRequest::LOAD_REPLACE)
|
||||
if (loadFlags & nsIChannel::LOAD_REPLACE)
|
||||
aChannel->GetURI(getter_AddRefs(uri));
|
||||
else
|
||||
aChannel->GetOriginalURI(getter_AddRefs(uri));
|
||||
|
|
|
@ -763,7 +763,7 @@ ImageNetContextImpl::GetURL (ilIURL * aURL,
|
|||
|
||||
nsLoadFlags flags=0;
|
||||
if(IsAnimationLoop)
|
||||
flags |= nsIRequest::VALIDATE_NEVER;
|
||||
flags |= nsIRequest::LOAD_FROM_CACHE;
|
||||
|
||||
rv = NS_OpenURI(getter_AddRefs(channel), nsurl, nsnull, group, sink, flags);
|
||||
if (NS_FAILED(rv)) goto error;
|
||||
|
@ -885,9 +885,9 @@ Need code to check freshness of necko cache.
|
|||
image_net_context_async_log_module = PR_NewLogModule("IMAGENETCTXASYNC");
|
||||
}
|
||||
#endif
|
||||
if((nsIRequest::FORCE_VALIDATION & defchan_attribs)||
|
||||
if((nsIRequest::VALIDATE_ALWAYS & defchan_attribs)||
|
||||
(nsIRequest::INHIBIT_PERSISTENT_CACHING & defchan_attribs)||
|
||||
(nsIRequest::FORCE_RELOAD & defchan_attribs)) {
|
||||
(nsIRequest::LOAD_BYPASS_CACHE & defchan_attribs)) {
|
||||
imglib_attribs = DONT_USE_IMG_CACHE;
|
||||
#if defined( DEBUG )
|
||||
PR_LOG(image_net_context_async_log_module, 1, ("ImageNetContextAsync: NS_NewImageNetContext: DONT_USE_IMAGE_CACHE\n"));
|
||||
|
|
|
@ -85,14 +85,14 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgID
|
|||
PRUint32 flags = 0;
|
||||
PRBool doomRequest = PR_FALSE;
|
||||
aLoadGroup->GetLoadFlags(&flags);
|
||||
if (flags & nsIRequest::FORCE_RELOAD)
|
||||
if (flags & nsIRequest::LOAD_BYPASS_CACHE)
|
||||
doomRequest = PR_TRUE;
|
||||
else {
|
||||
nsCOMPtr<nsIRequest> r;
|
||||
aLoadGroup->GetDefaultLoadRequest(getter_AddRefs(r));
|
||||
if (r) {
|
||||
r->GetLoadFlags(&flags);
|
||||
if (flags & nsIRequest::FORCE_RELOAD)
|
||||
if (flags & nsIRequest::LOAD_BYPASS_CACHE)
|
||||
doomRequest = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -314,13 +314,12 @@ NS_IMETHODIMP imgRequest::SetLoadGroup(nsILoadGroup *loadGroup)
|
|||
/* attribute nsLoadFlags loadFlags */
|
||||
NS_IMETHODIMP imgRequest::GetLoadFlags(nsLoadFlags *flags)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("imgRequest::GetLoadFlags");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
*flags = LOAD_NORMAL;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP imgRequest::SetLoadFlags(nsLoadFlags flags)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("imgRequest::SetLoadFlags");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** imgIRequest methods **/
|
||||
|
|
|
@ -180,8 +180,7 @@ NS_IMETHODIMP imgRequestProxy::GetLoadFlags(nsLoadFlags *flags)
|
|||
}
|
||||
NS_IMETHODIMP imgRequestProxy::SetLoadFlags(nsLoadFlags flags)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("imgRequestProxy::SetLoadFlags");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** imgIRequest methods **/
|
||||
|
|
|
@ -112,10 +112,32 @@ interface nsIChannel : nsIRequest
|
|||
void asyncOpen(in nsIStreamListener listener, in nsISupports ctxt);
|
||||
|
||||
/**************************************************************************
|
||||
* These flags are OBSOLETE and will be removed once the old cache is
|
||||
* Channel specific load flags:
|
||||
*/
|
||||
|
||||
/**
|
||||
* Used exclusively by the uriloader and docshell to indicate whether or
|
||||
* not this request corresponds to the toplevel document.
|
||||
*/
|
||||
const unsigned long LOAD_DOCUMENT_URI = 1 << 16;
|
||||
|
||||
/**
|
||||
* If the end consumer for this load has been retargeted after discovering
|
||||
* it's content, this flag will be set:
|
||||
*/
|
||||
const unsigned long LOAD_RETARGETED_DOCUMENT_URI = 1 << 17;
|
||||
|
||||
/**
|
||||
* This flag is set to indicate that onStopRequest may be followed by
|
||||
* another onStartRequest/onStopRequest pair. This flag is, for example,
|
||||
* used by the multipart/replace stream converter.
|
||||
*/
|
||||
const unsigned long LOAD_REPLACE = 1 << 18;
|
||||
|
||||
/**************************************************************************
|
||||
* This flag is OBSOLETE and will be removed once the old cache is
|
||||
* removed from the code base. Support for CACHE_AS_FILE is now provided
|
||||
* via nsICachingChannel.
|
||||
*/
|
||||
const unsigned long CACHE_AS_FILE = 1 << 14;
|
||||
const unsigned long VALIDATE_HEURISTICALLY = 1 << 15;
|
||||
const unsigned long CACHE_AS_FILE = 1 << 19;
|
||||
};
|
||||
|
|
|
@ -81,12 +81,14 @@ interface nsIRequest : nsISupports
|
|||
attribute nsILoadGroup loadGroup;
|
||||
|
||||
/**
|
||||
* Accesses the load flags for this request.
|
||||
* Accesses the load flags for this request. Bits 0-15 are defined (or
|
||||
* reserved) by nsIRequest. When added to a load group, this request's
|
||||
* load flags are merged with the load flags of the load group.
|
||||
*/
|
||||
attribute nsLoadFlags loadFlags;
|
||||
|
||||
/**************************************************************************
|
||||
* Below are the various load flags which may be or'd together.
|
||||
* Listed below are the various load flags which may be or'd together.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -96,67 +98,70 @@ interface nsIRequest : nsISupports
|
|||
|
||||
/**
|
||||
* Don't deliver status notifications to the nsIProgressEventSink, or keep
|
||||
* this load from completing the nsILoadGroup it may belong to:
|
||||
* this load from completing the nsILoadGroup it may belong to.
|
||||
*/
|
||||
const unsigned long LOAD_BACKGROUND = 1 << 0;
|
||||
|
||||
/**************************************************************************
|
||||
* For requests that are channels, the following flags may apply.
|
||||
* The following flags control the flow of data into the cache.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Used exclusively by the uriloader and docshell to indicate whether or
|
||||
* not this request corresponds to the toplevel document.
|
||||
* This flag prevents caching of any kind. It does not, however, prevent
|
||||
* cached content from being used to satisfy this request.
|
||||
*/
|
||||
const unsigned long LOAD_DOCUMENT_URI = 1 << 1;
|
||||
const unsigned long INHIBIT_CACHING = 1 << 7;
|
||||
|
||||
/**
|
||||
* If the end consumer for this load has been retargeted after discovering
|
||||
* it's content, this flag will be set:
|
||||
*/
|
||||
const unsigned long LOAD_RETARGETED_DOCUMENT_URI = 1 << 2;
|
||||
|
||||
/**
|
||||
* This flag is used to tell the webshell not to cancel the load in cases
|
||||
* when the request is receiving multipart/replace document
|
||||
*/
|
||||
const unsigned long LOAD_REPLACE = 1 << 3;
|
||||
|
||||
/**************************************************************************
|
||||
* The following flags control caching behavior. With the exception of
|
||||
* INHIBIT_PERSISTENT_CACHING, they are all mutually exclusive.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Don't store data in the disk cache. This can be used to preserve
|
||||
* privacy, e.g. so that no https transactions are recorded, or to avoid
|
||||
* caching a stream to disk that is already stored in a local file,
|
||||
* e.g. the mailbox: protocol.
|
||||
/**
|
||||
* This flag prevents caching on disk (or other persistent media), which
|
||||
* may be needed to preserve privacy. For HTTPS, this flag is set auto-
|
||||
* matically.
|
||||
*/
|
||||
const unsigned long INHIBIT_PERSISTENT_CACHING = 1 << 8;
|
||||
|
||||
/**
|
||||
* Force an end-to-end download of content data from the origin server (and
|
||||
* any intervening proxies that sit between it and the client), e.g. this
|
||||
* flag is used for a shift-reload.
|
||||
/**************************************************************************
|
||||
* The following flags control what happens when the cache contains data
|
||||
* that could perhaps satisfy this request. They are listed in descending
|
||||
* order of precidence.
|
||||
*/
|
||||
const unsigned long FORCE_RELOAD = 1 << 9;
|
||||
|
||||
/**
|
||||
* Force revalidation with server (or proxy) to verify that cached content
|
||||
* is up-to-date, e.g. by comparing last-modified date on server with that
|
||||
* of the cached version. This flag is used when the reload button is
|
||||
* pressed.
|
||||
* Force an end-to-end download of content data from the origin server.
|
||||
* This flag is used for a shift-reload.
|
||||
*/
|
||||
const unsigned long FORCE_VALIDATION = 1 << 10;
|
||||
const unsigned long LOAD_BYPASS_CACHE = 1 << 9;
|
||||
|
||||
/**
|
||||
* When cache data is potentially out of date, it can be revalidated with
|
||||
* the origin server to see if the content needs to be reloaded. The
|
||||
* following three flags control how often this validation occurs.
|
||||
* These flags are commonly used for "normal" loading.
|
||||
* Load from the cache, bypassing protocol specific validation logic. This
|
||||
* flag is used when browsing via history. It is not recommended for normal
|
||||
* browsing as it may likely violate reasonable assumptions made by the
|
||||
* server and confuse users.
|
||||
*/
|
||||
const unsigned long VALIDATE_NEVER = 1 << 11;
|
||||
const unsigned long VALIDATE_ALWAYS = 1 << 12;
|
||||
const unsigned long VALIDATE_ONCE_PER_SESSION = 1 << 13;
|
||||
const unsigned long LOAD_FROM_CACHE = 1 << 10;
|
||||
|
||||
/**
|
||||
* The following flags control the frequency of cached content validation
|
||||
* when neither LOAD_BYPASS_CACHE or LOAD_FROM_CACHE are set. By default,
|
||||
* cached content is automatically validated if necessary before reuse.
|
||||
*
|
||||
* VALIDATE_ALWAYS forces validation of any cached content independent of
|
||||
* its expiration time.
|
||||
*
|
||||
* VALIDATE_NEVER disables validation of expired content.
|
||||
*
|
||||
* VALIDATE_ONCE_PER_SESSION disables validation of expired content,
|
||||
* provided it has already been validated (at least once) since the start
|
||||
* of this session.
|
||||
*
|
||||
* NOTE TO IMPLEMENTORS:
|
||||
* These flags are intended for normal browsing, and they should therefore
|
||||
* not apply to content that must be validated before each use. Consider,
|
||||
* for example, a HTTP response with a "Cache-control: no-cache" header.
|
||||
* According to RFC2616, this response must be validated before it can
|
||||
* be taken from a cache. Breaking this requirement could result in
|
||||
* incorrect and potentially unpleasant side-effects.
|
||||
*/
|
||||
const unsigned long VALIDATE_ALWAYS = 1 << 11;
|
||||
const unsigned long VALIDATE_NEVER = 1 << 12;
|
||||
const unsigned long VALIDATE_ONCE_PER_SESSION = 1 << 13;
|
||||
};
|
||||
|
|
|
@ -54,8 +54,8 @@ PRLogModuleInfo* gLoadGroupLog = nsnull;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsLoadGroup::nsLoadGroup(nsISupports* outer)
|
||||
: mLoadFlags(LOAD_NORMAL)
|
||||
, mForegroundCount(0)
|
||||
: mForegroundCount(0)
|
||||
, mLoadFlags(LOAD_NORMAL)
|
||||
, mRequests(nsnull)
|
||||
, mStatus(NS_OK)
|
||||
{
|
||||
|
@ -377,6 +377,11 @@ NS_IMETHODIMP
|
|||
nsLoadGroup::SetDefaultLoadRequest(nsIRequest *aRequest)
|
||||
{
|
||||
mDefaultLoadRequest = aRequest;
|
||||
// Inherit the group load flags from the default load request
|
||||
if (mDefaultLoadRequest)
|
||||
mDefaultLoadRequest->GetLoadFlags(&mLoadFlags);
|
||||
else
|
||||
mLoadFlags = LOAD_NORMAL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -550,35 +555,14 @@ nsresult nsLoadGroup::MergeLoadFlags(nsIRequest *aRequest, nsLoadFlags& outFlags
|
|||
return rv;
|
||||
|
||||
oldFlags = flags;
|
||||
//
|
||||
// Inherit the group cache validation policy
|
||||
//
|
||||
if ( !((nsIRequest::VALIDATE_NEVER |
|
||||
nsIRequest::VALIDATE_ALWAYS |
|
||||
nsIRequest::VALIDATE_ONCE_PER_SESSION) & flags) ) {
|
||||
flags |= (nsIRequest::VALIDATE_NEVER |
|
||||
nsIRequest::VALIDATE_ALWAYS |
|
||||
nsIRequest::VALIDATE_ONCE_PER_SESSION) & mLoadFlags;
|
||||
}
|
||||
//
|
||||
// Inherit the group reload policy
|
||||
//
|
||||
if (!(nsIRequest::FORCE_VALIDATION & flags))
|
||||
flags |= (nsIRequest::FORCE_VALIDATION & mLoadFlags);
|
||||
if (!(nsIRequest::FORCE_RELOAD & flags))
|
||||
flags |= (nsIRequest::FORCE_RELOAD & mLoadFlags);
|
||||
|
||||
//
|
||||
// Inherit the group persistent cache policy
|
||||
//
|
||||
if (!(nsIRequest::INHIBIT_PERSISTENT_CACHING & flags))
|
||||
flags |= (nsIRequest::INHIBIT_PERSISTENT_CACHING & mLoadFlags);
|
||||
|
||||
//
|
||||
// Inherit the group loading policy
|
||||
//
|
||||
if (!(nsIRequest::LOAD_BACKGROUND & flags))
|
||||
flags |= (nsIRequest::LOAD_BACKGROUND & mLoadFlags);
|
||||
// Inherit the following bits...
|
||||
flags |= (mLoadFlags & (LOAD_BACKGROUND |
|
||||
LOAD_BYPASS_CACHE |
|
||||
LOAD_FROM_CACHE |
|
||||
VALIDATE_ALWAYS |
|
||||
VALIDATE_ONCE_PER_SESSION |
|
||||
VALIDATE_NEVER));
|
||||
|
||||
if (flags != oldFlags)
|
||||
rv = aRequest->SetLoadFlags(flags);
|
||||
|
|
|
@ -866,7 +866,7 @@ nsHTTPChannel::OpenCacheEntry()
|
|||
accessRequested = nsICache::ACCESS_READ;
|
||||
mFromCacheOnly = PR_TRUE;
|
||||
}
|
||||
else if (mLoadFlags & FORCE_RELOAD)
|
||||
else if (mLoadFlags & LOAD_BYPASS_CACHE)
|
||||
accessRequested = nsICache::ACCESS_WRITE; // replace cache entry
|
||||
else if (mFromCacheOnly)
|
||||
accessRequested = nsICache::ACCESS_READ; // read from cache
|
||||
|
@ -889,122 +889,16 @@ nsHTTPChannel::GenerateCacheKey(nsAWritableCString &cacheKey)
|
|||
cacheKey.Append(buf);
|
||||
cacheKey.Append("&url=");
|
||||
}
|
||||
// Use the override request spec if set.
|
||||
const char *spec = mRequest->OverrideRequestSpec();
|
||||
if (!spec)
|
||||
spec = mRequest->Spec();
|
||||
// Strip any trailing #ref from the URL before using it as the key
|
||||
char *p = PL_strchr(mRequest->Spec(), '#');
|
||||
char *p = PL_strchr(spec, '#');
|
||||
if (p)
|
||||
cacheKey.Append(mRequest->Spec(), p - mRequest->Spec());
|
||||
cacheKey.Append(spec, p - spec);
|
||||
else
|
||||
cacheKey.Append(mRequest->Spec());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
// where responseTime == now
|
||||
//
|
||||
// This is typically a very small number.
|
||||
//
|
||||
nsresult
|
||||
nsHTTPChannel::ComputeCurrentAge(PRUint32 now,
|
||||
PRUint32 *result)
|
||||
{
|
||||
NS_ENSURE_TRUE(mResponse, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
PRUint32 dateValue;
|
||||
PRUint32 ageValue = 0;
|
||||
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;
|
||||
|
||||
// Compute apparent age
|
||||
if (now > dateValue)
|
||||
*result = now - dateValue;
|
||||
|
||||
// Compute corrected received age
|
||||
if (avail)
|
||||
*result = PR_MAX(*result, ageValue);
|
||||
|
||||
NS_ASSERTION(now >= mRequestTime, "bogus request time");
|
||||
|
||||
// Compute current age
|
||||
*result += (now - mRequestTime);
|
||||
|
||||
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
|
||||
// <or>
|
||||
// freshnessLifetime = 0
|
||||
//
|
||||
nsresult
|
||||
nsHTTPChannel::ComputeFreshnessLifetime(PRUint32 *result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
NS_ENSURE_TRUE(mResponse, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsresult rv;
|
||||
PRBool avail = PR_FALSE;
|
||||
|
||||
*result = 0;
|
||||
|
||||
// Try HTTP/1.1 style max-age directive...
|
||||
rv = mResponse->GetMaxAge(result, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (avail)
|
||||
return NS_OK;
|
||||
|
||||
PRUint32 date, date2;
|
||||
|
||||
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) {
|
||||
*result = date2 - date;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Fallback on heuristic using last modified header...
|
||||
rv = mResponse->GetLastModifiedValue(&date2, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (avail) {
|
||||
LOG(("using last-modified to determine freshness-lifetime\n"));
|
||||
LOG(("last-modified = %u, date = %u\n", date2, date));
|
||||
*result = (date - date2) / 10;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(("nsHTTPChannel::ComputeFreshnessLifetime [this = %x] "
|
||||
"Insufficient information to compute a non-zero freshness "
|
||||
"lifetime!\n", this));
|
||||
|
||||
cacheKey.Append(spec);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1024,10 +918,10 @@ nsHTTPChannel::UpdateExpirationTime()
|
|||
PRUint32 now = NowInSeconds();
|
||||
PRUint32 freshnessLifetime, currentAge, timeRemaining = 0;
|
||||
|
||||
rv = ComputeCurrentAge(now, ¤tAge);
|
||||
rv = mResponse->ComputeCurrentAge(now, mRequestTime, ¤tAge);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = ComputeFreshnessLifetime(&freshnessLifetime);
|
||||
rv = mResponse->ComputeFreshnessLifetime(&freshnessLifetime);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
LOG(("freshnessLifetime = %u, currentAge = %u\n",
|
||||
|
@ -1093,8 +987,6 @@ nsHTTPChannel::CheckCache()
|
|||
rv = mCacheEntry->GetDataSize(&size);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
LOG(("Content-length=%d, CacheEntryDataSize=%u\n", contentLength, size));
|
||||
|
||||
if (size != (PRUint32) contentLength) {
|
||||
LOG(("Cached data size does not match the Content-Length header "
|
||||
"[content-length=%u size=%u]\n", contentLength, size));
|
||||
|
@ -1103,44 +995,59 @@ nsHTTPChannel::CheckCache()
|
|||
}
|
||||
}
|
||||
|
||||
// If validation is inhibited, we'll just use whatever data is in
|
||||
// the cache, regardless of whether or not it has expired.
|
||||
if (mLoadFlags & nsIRequest::VALIDATE_NEVER) {
|
||||
mCachedContentIsValid = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
PRBool doValidation = PR_FALSE;
|
||||
|
||||
PRBool doIfModifiedSince = PR_FALSE;
|
||||
|
||||
// Be optimistic: assume that we won't need to send If-Modified-Since
|
||||
mCachedContentIsValid = PR_TRUE;
|
||||
// Be optimistic: assume that we won't need to do validation
|
||||
SetRequestHeader(nsHTTPAtoms::If_Modified_Since, nsnull);
|
||||
SetRequestHeader(nsHTTPAtoms::If_None_Match, 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) {
|
||||
LOG(("No Last-Lodified header sent, try using the Date header.\n"));
|
||||
mCachedResponse->GetHeader(nsHTTPAtoms::Date,
|
||||
getter_Copies(lastModified));
|
||||
if (!lastModified) {
|
||||
LOG(("BAD SERVER!! No Date header sent... reloading the document.\n"));
|
||||
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 (mLoadFlags & nsIRequest::FORCE_VALIDATION) {
|
||||
LOG(("honoring nsIRequest::FORCE_VALIDATION\n"));
|
||||
doIfModifiedSince = PR_TRUE;
|
||||
// If the LOAD_FROM_CACHE flag is set, any cached data can simply be used.
|
||||
if (mLoadFlags & LOAD_FROM_CACHE) {
|
||||
LOG(("NOT validating based on LOAD_FROM_CACHE load flag\n"));
|
||||
doValidation = PR_FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
//
|
||||
// If the VALIDATE_ALWAYS flag is set, any cached data won't be used until
|
||||
// it's revalidated with the server.
|
||||
if (mLoadFlags & VALIDATE_ALWAYS) {
|
||||
LOG(("Validating based on VALIDATE_ALWAYS load flag\n"));
|
||||
doValidation = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// 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 (See RFC 2616, section 14.9.4).
|
||||
mCachedResponse->GetHeader(nsHTTPAtoms::Cache_Control, getter_Copies(str));
|
||||
if (str && PL_strstr(str, "must-revalidate")) {
|
||||
LOG(("Validating based on \"%s\" header\n", (const char *) str));
|
||||
doValidation = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
// The no-cache directive within the 'Cache-Control:' header indicates
|
||||
// that we must validate this cached response before reusing.
|
||||
if (str && PL_strstr(str, "no-cache")) {
|
||||
LOG(("Validating based on \"%s\" header\n", (const char *) str));
|
||||
doValidation = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
// XXX we are not quite handling no-cache correctly in this case. We really
|
||||
// should check for field-names and only force validation if they match
|
||||
// existing response headers. See RFC2616 section 14.9.1 for details.
|
||||
str = 0;
|
||||
|
||||
// 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.
|
||||
GetResponseHeader(nsHTTPAtoms::Pragma, getter_Copies(str));
|
||||
if (str && PL_strstr(str, "no-cache")) {
|
||||
LOG(("Validating based on \"%s\" header\n", (const char *) str));
|
||||
doValidation = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
str = 0;
|
||||
|
||||
// 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 "*"
|
||||
|
@ -1152,68 +1059,74 @@ nsHTTPChannel::CheckCache()
|
|||
// 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)) {
|
||||
LOG(("Need to validate content based on Vary header\n"));
|
||||
doIfModifiedSince = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
if (str && (PL_strstr(str, "*") ||
|
||||
PL_strstr(str, "accept-charset") ||
|
||||
PL_strstr(str, "accept-language"))) {
|
||||
LOG(("Validating based on \"%s\" header\n", (const char *) str));
|
||||
doValidation = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
str = 0;
|
||||
|
||||
if (mLoadFlags & VALIDATE_NEVER) {
|
||||
doValidation = PR_FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Determine if this is the first time that this cache entry has been
|
||||
// accessed in this session.
|
||||
// Check if the cache entry has expired...
|
||||
{
|
||||
PRBool firstAccessThisSession;
|
||||
PRUint32 sessionStartTime, lastWritten, expirationTime, now = NowInSeconds();
|
||||
PRUint32 time = 0; // a temporary variable for storing time values...
|
||||
|
||||
rv = mCacheEntry->GetLastModified(&lastWritten);
|
||||
rv = mCacheEntry->GetExpirationTime(&time);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mCacheEntry->GetExpirationTime(&expirationTime);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NowInSeconds() <= time)
|
||||
doValidation = PR_FALSE;
|
||||
else if (mLoadFlags & VALIDATE_ONCE_PER_SESSION) {
|
||||
// If the cached response does not include expiration infor-
|
||||
// mation, then we must validate the response, despite whether
|
||||
// or not this is the first access this session. This behavior
|
||||
// is consistent with existing browsers and is generally expected
|
||||
// by web authors.
|
||||
rv = mCachedResponse->ComputeFreshnessLifetime(&time);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
sessionStartTime = PRTimeToSeconds(mHandler->GetSessionStartTime());
|
||||
firstAccessThisSession = (sessionStartTime > lastWritten);
|
||||
|
||||
LOG(("firstAccessThisSession = %u\n", firstAccessThisSession));
|
||||
|
||||
// Check to see if we can use the cache data without revalidating
|
||||
// it with the server.
|
||||
//PRBool useHeuristicExpiration =
|
||||
// mLoadFlags & nsIRequest::VALIDATE_HEURISTICALLY;
|
||||
|
||||
// If the content is stale, issue an if-modified-since request
|
||||
if (now > expirationTime) {
|
||||
if (mLoadFlags & nsIRequest::VALIDATE_ONCE_PER_SESSION)
|
||||
doIfModifiedSince = firstAccessThisSession;
|
||||
else
|
||||
// VALIDATE_ALWAYS || VALIDATE_HEURISTICALLY || default
|
||||
doIfModifiedSince = PR_TRUE;
|
||||
if (time == 0)
|
||||
doValidation = PR_TRUE;
|
||||
else {
|
||||
rv = mCacheEntry->GetLastModified(&time);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// Determine if this is the first time that this cache entry
|
||||
// has been accessed in this session, and validate if so.
|
||||
doValidation = (mHandler->SessionStartTime() > time);
|
||||
}
|
||||
}
|
||||
else
|
||||
doValidation = PR_TRUE;
|
||||
}
|
||||
|
||||
end:
|
||||
if (doIfModifiedSince) {
|
||||
SetRequestHeader(nsHTTPAtoms::If_Modified_Since, lastModified);
|
||||
mCachedContentIsValid = !doValidation;
|
||||
|
||||
if (doValidation) {
|
||||
// Add If-Modified-Since header if a Last-Modified was given
|
||||
mCachedResponse->GetHeader(nsHTTPAtoms::Last_Modified, getter_Copies(str));
|
||||
if (!str) {
|
||||
LOG(("No Last-Lodified header sent, using the Date header instead...\n"));
|
||||
mCachedResponse->GetHeader(nsHTTPAtoms::Date, getter_Copies(str));
|
||||
}
|
||||
if (str)
|
||||
SetRequestHeader(nsHTTPAtoms::If_Modified_Since, str);
|
||||
str = 0;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
LOG(("nsHTTPChannel::CheckCache [this=%x if-modified-since=%d"
|
||||
" cache-entry-is-valid=%d]\n",
|
||||
this, doIfModifiedSince, mCachedContentIsValid));
|
||||
|
||||
LOG(("CheckCache [this=%x doValidation=%d\n", this, doValidation));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1272,13 +1185,14 @@ nsHTTPChannel::ReadFromCache()
|
|||
return rv;
|
||||
}
|
||||
|
||||
#if 0
|
||||
PRBool
|
||||
nsHTTPChannel::ResponseIsCacheable()
|
||||
{
|
||||
nsXPIDLCString str;
|
||||
|
||||
// The no-store directive within the 'Cache-Control:' header indicates
|
||||
// that we should not store the response in the cache
|
||||
// The no-cache directive within the 'Cache-Control:' header indicates
|
||||
// that we should not cache the response in a persistent cache
|
||||
GetResponseHeader(nsHTTPAtoms::Cache_Control, getter_Copies(str));
|
||||
if (str) {
|
||||
nsSubsumeCStr ss((char *) (const char *) str, PR_FALSE);
|
||||
|
@ -1328,6 +1242,7 @@ nsHTTPChannel::ResponseIsCacheable()
|
|||
|
||||
return PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsHTTPChannel::CacheAbort(PRUint32 statusCode)
|
||||
|
@ -1352,6 +1267,7 @@ nsresult
|
|||
nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||
nsIStreamListener **aResult)
|
||||
{
|
||||
nsXPIDLCString str;
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
|
@ -1371,25 +1287,23 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
|||
LOG(("nsHTTPChannel::CacheReceivedResponse [this=%x entry=%x]\n",
|
||||
this, mCacheEntry.get()));
|
||||
|
||||
// Every POST transaction has a unique ID associated with it. If this
|
||||
// is not a POST transaction (or if the POST transaction should not be
|
||||
// cached) then the ID will be zero.
|
||||
if (!mPostID && !ResponseIsCacheable()) {
|
||||
CacheAbort(0);
|
||||
return NS_OK;
|
||||
// The no-store directive within the 'Cache-Control:' header indicates
|
||||
// that we should not store the response in a persistent cache
|
||||
GetResponseHeader(nsHTTPAtoms::Cache_Control, getter_Copies(str));
|
||||
if (str && PL_strstr(str, "no-store")) {
|
||||
mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
|
||||
LOG(("Inhibiting persistent caching because of \"%s\"\n", (const char *) str));
|
||||
}
|
||||
|
||||
// Store secure data in memory only
|
||||
nsCOMPtr<nsISupports> securityInfo;
|
||||
rv = GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||
if (NS_SUCCEEDED(rv) && securityInfo) {
|
||||
rv = mCacheEntry->SetSecurityInfo(securityInfo);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||
if (securityInfo)
|
||||
mCacheEntry->SetSecurityInfo(securityInfo);
|
||||
|
||||
// For HTTPS connections, the storage policy will already be IN_MEMORY.
|
||||
// For HTTPS transactions, the storage policy will already be IN_MEMORY.
|
||||
// We are concerned instead about load attributes which may have changed.
|
||||
if (mLoadFlags & nsIRequest::INHIBIT_PERSISTENT_CACHING) {
|
||||
if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
|
||||
rv = mCacheEntry->SetStoragePolicy(nsICache::STORE_IN_MEMORY);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
@ -1541,7 +1455,7 @@ nsHTTPChannel::CheckCache()
|
|||
// If we can't use the cache data (because an end-to-end reload
|
||||
// has been requested)
|
||||
// there's no point in inspecting it since it's about to be overwritten.
|
||||
if (mLoadFlags & nsIRequest::FORCE_RELOAD)
|
||||
if (mLoadFlags & LOAD_BYPASS_CACHE)
|
||||
return NS_OK;
|
||||
|
||||
// Due to architectural limitations in the cache manager, a cache entry can
|
||||
|
@ -1629,11 +1543,11 @@ nsHTTPChannel::CheckCache()
|
|||
if (varyHeader)
|
||||
mustRevalidate = PR_TRUE;
|
||||
|
||||
// If the FORCE_VALIDATION flag is set, any cached data won't be used until
|
||||
// If the VALIDATE_ALWAYS flag is set, any cached data won't be used until
|
||||
// it's revalidated with the server, so there's no point in checking if it's
|
||||
// expired.
|
||||
PRBool doIfModifiedSince;
|
||||
if ((mLoadFlags & nsIRequest::FORCE_VALIDATION) || mustRevalidate)
|
||||
if ((mLoadFlags & nsIRequest::VALIDATE_ALWAYS) || mustRevalidate)
|
||||
doIfModifiedSince = PR_TRUE;
|
||||
else {
|
||||
doIfModifiedSince = PR_FALSE;
|
||||
|
@ -1665,7 +1579,6 @@ nsHTTPChannel::CheckCache()
|
|||
if (mLoadFlags & nsIRequest::VALIDATE_ONCE_PER_SESSION)
|
||||
doIfModifiedSince = firstAccessThisSession;
|
||||
else
|
||||
// VALIDATE_ALWAYS || VALIDATE_HEURISTICALLY || default
|
||||
doIfModifiedSince = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -2077,8 +1990,7 @@ nsHTTPChannel::Connect()
|
|||
}
|
||||
|
||||
// if using proxy...
|
||||
nsXPIDLCString requestSpec;
|
||||
rv = mRequest->GetOverrideRequestSpec(getter_Copies(requestSpec));
|
||||
const char *requestSpec = mRequest->OverrideRequestSpec();
|
||||
// no one has overwritten this value as yet...
|
||||
if (!requestSpec && mProxy && *mProxy && !mProxyTransparent) {
|
||||
nsXPIDLCString strurl;
|
||||
|
@ -2265,7 +2177,7 @@ nsresult nsHTTPChannel::Redirect(const char *aNewLocation,
|
|||
|
||||
// Add in LOAD_REPLACE to loadattributes indicate that this is a redirect
|
||||
nsLoadFlags loadFlags = mLoadFlags;
|
||||
loadFlags |= nsIRequest::LOAD_REPLACE;
|
||||
loadFlags |= LOAD_REPLACE;
|
||||
|
||||
rv = NS_OpenURI(getter_AddRefs(channel), newURI, serv, mLoadGroup,
|
||||
mCallbacks, loadFlags);
|
||||
|
@ -2332,7 +2244,7 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIStreamListener *aListener, nsresult
|
|||
nsresult rv = NS_OK;
|
||||
|
||||
LOG(("nsHTTPChannel::ResponseComplete() [this=%x] "
|
||||
"mDataListenet=%x, Status=%o\n",
|
||||
"mDataListenet=%x, Status=%x\n",
|
||||
this, (void*)mResponseDataListener, aStatus));
|
||||
|
||||
#if 0
|
||||
|
@ -2946,6 +2858,7 @@ nsHTTPChannel::ProcessStatusCode(void)
|
|||
// indicates that the cached response can be used.
|
||||
if (statusCode == 304) {
|
||||
rv = ProcessNotModifiedResponse(listener);
|
||||
LOG(("ProcessNotModifiedResponse returned rv=%x\n", rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
break;
|
||||
}
|
||||
|
@ -3015,11 +2928,14 @@ nsHTTPChannel::ProcessNotModifiedResponse(nsIStreamListener *aListener)
|
|||
"Using cache copy for: %s\n",
|
||||
this, mRequest->Spec()));
|
||||
|
||||
// XXX this should be unnecessary.. the response was successful!!
|
||||
#if 0
|
||||
// Orphan the current nsHTTPServerListener instance... It will be
|
||||
// replaced with a nsHTTPCacheListener instance.
|
||||
NS_ASSERTION(mHTTPServerListener, "No nsHTTPServerResponse available!");
|
||||
if (mHTTPServerListener)
|
||||
mHTTPServerListener->Abort();
|
||||
#endif
|
||||
|
||||
// Update the cached headers with any more recent ones from the
|
||||
// server - see RFC2616 [13.5.3]
|
||||
|
@ -3202,8 +3118,8 @@ nsHTTPChannel::SetProxyRequestURI(const char * i_Spec)
|
|||
NS_IMETHODIMP
|
||||
nsHTTPChannel::GetProxyRequestURI(char * *o_Spec)
|
||||
{
|
||||
return mRequest ?
|
||||
mRequest->GetOverrideRequestSpec(o_Spec) : NS_ERROR_FAILURE;
|
||||
return mRequest ?
|
||||
DupString(o_Spec, mRequest->OverrideRequestSpec()) : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -139,8 +139,6 @@ protected:
|
|||
nsresult OpenCacheEntry();
|
||||
nsresult GenerateCacheKey(nsAWritableCString &);
|
||||
|
||||
nsresult ComputeCurrentAge(PRUint32 now, PRUint32 *);
|
||||
nsresult ComputeFreshnessLifetime(PRUint32 *);
|
||||
nsresult UpdateExpirationTime();
|
||||
|
||||
PRBool ResponseIsCacheable();
|
||||
|
|
|
@ -954,7 +954,7 @@ nsHTTPHandler::Init()
|
|||
gHTTPLog = PR_NewLogModule("nsHTTPProtocol");
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
mSessionStartTime = PR_Now();
|
||||
mSessionStartTime = NowInSeconds();
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS, ("Creating nsHTTPHandler [this=%x].\n",
|
||||
this));
|
||||
|
|
|
@ -128,7 +128,7 @@ public:
|
|||
/* Remove this transport from the list. */
|
||||
virtual nsresult ReleaseTransport(nsITransport* i_pTrans, PRUint32 capabilies = 0, PRBool aDontRestartChannels = PR_FALSE, PRUint32 aKeepAliveTimeout = 0, PRInt32 aKeepAliveMaxCon = -1);
|
||||
virtual nsresult CancelPendingChannel(nsHTTPChannel* aChannel);
|
||||
PRTime GetSessionStartTime() { return mSessionStartTime; }
|
||||
PRUint32 SessionStartTime() { return mSessionStartTime; }
|
||||
|
||||
void PrefsChanged(const char* pref = 0);
|
||||
|
||||
|
@ -188,7 +188,7 @@ protected:
|
|||
nsCOMPtr<nsIPref> mPrefs;
|
||||
nsCOMPtr<nsIProtocolProxyService> mProxySvc;
|
||||
PRUint32 mReferrerLevel;
|
||||
PRTime mSessionStartTime;
|
||||
PRUint32 mSessionStartTime;
|
||||
|
||||
nsresult BuildUserAgent();
|
||||
nsCString mAppName;
|
||||
|
|
|
@ -311,12 +311,6 @@ nsHTTPRequest::SetOverrideRequestSpec(const char *aSpec)
|
|||
return DupString(&mRequestSpec, aSpec);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTTPRequest::GetOverrideRequestSpec(char **aSpec)
|
||||
{
|
||||
return DupString(aSpec, mRequestSpec);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTTPRequest::formHeaders(PRUint32 capabilities)
|
||||
{
|
||||
|
@ -352,24 +346,23 @@ nsHTTPRequest::formHeaders(PRUint32 capabilities)
|
|||
PRUint32 loadFlags;
|
||||
mConnection->GetLoadFlags(&loadFlags);
|
||||
|
||||
if (loadFlags &
|
||||
(nsIRequest::FORCE_VALIDATION | nsIRequest::FORCE_RELOAD)) {
|
||||
if (loadFlags & LOAD_BYPASS_CACHE) {
|
||||
// We need to send 'Pragma:no-cache' to inhibit proxy caching even if
|
||||
// no proxy is configured since we might be talking with a transparent
|
||||
// proxy, i.e. one that operates at the network level. See bug #14772
|
||||
SetHeader(nsHTTPAtoms::Pragma, "no-cache");
|
||||
}
|
||||
|
||||
if (loadFlags & nsIRequest::FORCE_RELOAD) {
|
||||
// If doing a reload, force end-to-end
|
||||
SetHeader(nsHTTPAtoms::Cache_Control, "no-cache");
|
||||
}
|
||||
else if (loadFlags & nsIRequest::FORCE_VALIDATION) {
|
||||
// XXX it should be sufficient to just validate with the immediate host.
|
||||
#if 0
|
||||
else if (loadFlags & VALIDATE_ALWAYS) {
|
||||
// A "max-age=0" cache-control directive forces each cache along the
|
||||
// path to the origin server to revalidate its own entry, if any, with
|
||||
// the next cache or server.
|
||||
SetHeader(nsHTTPAtoms::Cache_Control, "max-age=0");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Send */*. We're no longer chopping MIME-types for acceptance.
|
||||
// MIME based content negotiation has died.
|
||||
|
|
|
@ -118,9 +118,9 @@ public:
|
|||
nsresult SetUploadStream(nsIInputStream* i_UploadStream);
|
||||
|
||||
nsresult SetOverrideRequestSpec(const char* i_Spec);
|
||||
nsresult GetOverrideRequestSpec(char** o_Spec);
|
||||
|
||||
const char *Spec() { return (const char *) mSpec; }
|
||||
const char *OverrideRequestSpec() { return (const char *) mRequestSpec; }
|
||||
const char *Spec() { return (const char *) mSpec; }
|
||||
|
||||
// for POST or PUT data...
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
|
||||
#if defined(PR_LOGGING)
|
||||
extern PRLogModuleInfo* gHTTPLog;
|
||||
#endif /* PR_LOGGING */
|
||||
#endif
|
||||
|
||||
#define LOG(args) PR_LOG(gHTTPLog, PR_LOG_DEBUG, args)
|
||||
|
||||
// When deciding heuristically whether or not to validate an HTTP response with
|
||||
// the server, this constant can be used to tune how conservative the algorithm
|
||||
|
@ -935,4 +937,112 @@ nsHTTPResponse::GetExpiresValue(PRUint32 *result, PRBool *isAvail)
|
|||
return ParseDateHeader(nsHTTPAtoms::Expires, result, isAvail);
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
// where responseTime == now
|
||||
//
|
||||
// This is typically a very small number.
|
||||
//
|
||||
nsresult
|
||||
nsHTTPResponse::ComputeCurrentAge(PRUint32 now,
|
||||
PRUint32 requestTime,
|
||||
PRUint32 *result)
|
||||
{
|
||||
PRUint32 dateValue;
|
||||
PRUint32 ageValue = 0;
|
||||
PRBool avail = PR_FALSE;
|
||||
nsresult rv;
|
||||
|
||||
*result = 0;
|
||||
|
||||
rv = GetDateValue(&dateValue, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (!avail) {
|
||||
LOG(("nsHTTPResponse::ComputeCurrentAge [this=%x] Date response header not set!\n", this));
|
||||
// Assume we have a very fast connection !!
|
||||
dateValue = now;
|
||||
}
|
||||
|
||||
rv = GetAgeValue(&ageValue, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Compute apparent age
|
||||
if (now > dateValue)
|
||||
*result = now - dateValue;
|
||||
|
||||
// Compute corrected received age
|
||||
if (avail)
|
||||
*result = PR_MAX(*result, ageValue);
|
||||
|
||||
NS_ASSERTION(now >= requestTime, "bogus request time");
|
||||
|
||||
// Compute current age
|
||||
*result += (now - requestTime);
|
||||
|
||||
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_value - last_modified_value) * 0.10
|
||||
// <or>
|
||||
// freshnessLifetime = 0
|
||||
//
|
||||
nsresult
|
||||
nsHTTPResponse::ComputeFreshnessLifetime(PRUint32 *result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
|
||||
nsresult rv;
|
||||
PRBool avail = PR_FALSE;
|
||||
|
||||
*result = 0;
|
||||
|
||||
// Try HTTP/1.1 style max-age directive...
|
||||
rv = GetMaxAge(result, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (avail)
|
||||
return NS_OK;
|
||||
|
||||
PRUint32 date, date2;
|
||||
|
||||
rv = GetDateValue(&date, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (avail) {
|
||||
// Try HTTP/1.0 style expires header...
|
||||
rv = GetExpiresValue(&date2, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (avail) {
|
||||
*result = date2 - date;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Fallback on heuristic using last modified header...
|
||||
rv = GetLastModifiedValue(&date2, &avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (avail) {
|
||||
LOG(("using last-modified to determine freshness-lifetime\n"));
|
||||
LOG(("last-modified = %u, date = %u\n", date2, date));
|
||||
*result = (date - date2) / 10;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(("nsHTTPResponse::ComputeFreshnessLifetime [this = %x] "
|
||||
"Insufficient information to compute a non-zero freshness "
|
||||
"lifetime!\n", this));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -90,6 +90,8 @@ public:
|
|||
nsresult GetDateValue(PRUint32 *, PRBool *isAvail);
|
||||
nsresult GetLastModifiedValue(PRUint32 *, PRBool *isAvail);
|
||||
nsresult GetExpiresValue(PRUint32 *, PRBool *isAvail);
|
||||
nsresult ComputeFreshnessLifetime(PRUint32 *);
|
||||
nsresult ComputeCurrentAge(PRUint32 now, PRUint32 requestTime, PRUint32 *result);
|
||||
#endif
|
||||
nsresult GetMaxAge(PRUint32 *, PRBool *isAvail);
|
||||
|
||||
|
|
|
@ -447,6 +447,7 @@ nsHTTPServerListener::OnDataAvailable(nsIRequest *request,
|
|||
//
|
||||
if (!mResponseDataListener) {
|
||||
// XXX: What should the return code be?
|
||||
LOG(("nsHTTPServerListener::OnDataAvailable -- returning NS_BINDING_ABORTED\n"));
|
||||
rv = NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
|
@ -698,7 +699,13 @@ nsHTTPServerListener::OnStopRequest(nsIRequest* request, nsISupports* i_pContext
|
|||
mResponse->GetStatus(&status);
|
||||
|
||||
if (status != 304 || mChannel->HasCachedResponse()) {
|
||||
mChannel->ResponseCompleted(mResponseDataListener, i_Status);
|
||||
// For 304 responses, we'll call ResponseCompleted after the response
|
||||
// has been completely read from the cache.
|
||||
if (status != 304) {
|
||||
LOG(("Calling ResponseCompleted [httpStatus=%d status=%x]\n", status, i_Status));
|
||||
mChannel->ResponseCompleted(mResponseDataListener, i_Status);
|
||||
}
|
||||
// The channel is done with us.
|
||||
mChannel->SetHTTPServerListener(nsnull);
|
||||
}
|
||||
|
||||
|
@ -807,6 +814,8 @@ nsresult nsHTTPServerListener::Abort()
|
|||
nsresult nsHTTPServerListener::FireSingleOnData(nsIStreamListener *aListener,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
LOG(("nsHTTPServerListener::FireSingleOnData [this=%x]\n", this));
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mHeadersDone) {
|
||||
|
|
|
@ -371,7 +371,7 @@ nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
|
|||
|
||||
nsLoadFlags loadFlags = 0;
|
||||
mPartChannel->GetLoadFlags(&loadFlags);
|
||||
loadFlags |= nsIRequest::LOAD_REPLACE;
|
||||
loadFlags |= nsIChannel::LOAD_REPLACE;
|
||||
mPartChannel->SetLoadFlags(loadFlags);
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
|
|
|
@ -465,7 +465,7 @@ nsDocLoaderImpl::OnStartRequest(nsIRequest *request, nsISupports *aCtxt)
|
|||
PRUint32 loadFlags = 0;
|
||||
request->GetLoadFlags(&loadFlags);
|
||||
|
||||
if (!mIsLoadingDocument && (loadFlags & nsIRequest::LOAD_DOCUMENT_URI)) {
|
||||
if (!mIsLoadingDocument && (loadFlags & nsIChannel::LOAD_DOCUMENT_URI)) {
|
||||
mIsLoadingDocument = PR_TRUE;
|
||||
ClearInternalProgress(); // only clear our progress if we are starting a new load....
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ nsDocLoaderImpl::OnStartRequest(nsIRequest *request, nsISupports *aCtxt)
|
|||
//
|
||||
AddRequestInfo(request);
|
||||
|
||||
if ((1 == count) && (loadFlags & nsIRequest::LOAD_DOCUMENT_URI)) {
|
||||
if ((1 == count) && (loadFlags & nsIChannel::LOAD_DOCUMENT_URI)) {
|
||||
// This request is associated with the entire document...
|
||||
mDocumentRequest = do_QueryInterface(request);
|
||||
mLoadGroup->SetDefaultLoadRequest(mDocumentRequest);
|
||||
|
|
|
@ -363,7 +363,7 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports *
|
|||
// we must be retargeting...so set an appropriate flag on the channel
|
||||
nsLoadFlags loadFlags = 0;
|
||||
aChannel->GetLoadFlags(&loadFlags);
|
||||
loadFlags |= nsIRequest::LOAD_RETARGETED_DOCUMENT_URI;
|
||||
loadFlags |= nsIChannel::LOAD_RETARGETED_DOCUMENT_URI;
|
||||
aChannel->SetLoadFlags(loadFlags);
|
||||
}
|
||||
|
||||
|
|
|
@ -1987,7 +1987,7 @@ nsBookmarksService::FireTimer(nsITimer* aTimer, void* aClosure)
|
|||
nsCOMPtr<nsIChannel> channel;
|
||||
if (NS_SUCCEEDED(rv = NS_OpenURI(getter_AddRefs(channel), uri, nsnull)))
|
||||
{
|
||||
channel->SetLoadFlags(nsIRequest::FORCE_VALIDATION | nsIRequest::VALIDATE_ALWAYS);
|
||||
channel->SetLoadFlags(nsIRequest::VALIDATE_ALWAYS);
|
||||
nsCOMPtr<nsIHTTPChannel> httpChannel = do_QueryInterface(channel);
|
||||
if (httpChannel)
|
||||
{
|
||||
|
|
|
@ -91,8 +91,9 @@
|
|||
<radiogroup id="browserCacheCheckDocFrequency" orient="vertical" autostretch="never"
|
||||
pref="true" preftype="int" prefstring="browser.cache.check_doc_frequency"
|
||||
prefattribute="value">
|
||||
<radio group="browserCacheCheckDocFrequency" value="0" label="&oncePsessionRadio.label;" accesskey="&oncePsessionRadio.accesskey;"/>
|
||||
<radio group="browserCacheCheckDocFrequency" value="1" label="&everyTimeRadio.label;" accesskey="&everyTimeRadio.accesskey;"/>
|
||||
<radio group="browserCacheCheckDocFrequency" value="3" label="&autoRadio.label;" accesskey="&autoRadio.accesskey;"/>
|
||||
<radio group="browserCacheCheckDocFrequency" value="0" label="&oncePsessionRadio.label;" accesskey="&oncePsessionRadio.accesskey;"/>
|
||||
<radio group="browserCacheCheckDocFrequency" value="2" label="&neverRadio.label;" accesskey="&neverRadio.accesskey;"/>
|
||||
</radiogroup>
|
||||
</box>
|
||||
|
|
|
@ -24,3 +24,5 @@
|
|||
<!ENTITY everyTimeRadio.accesskey "e">
|
||||
<!ENTITY neverRadio.label "Never">
|
||||
<!ENTITY neverRadio.accesskey "n">
|
||||
<!ENTITY autoRadio.label "Automatically">
|
||||
<!ENTITY autoRadio.accesskey "a">
|
||||
|
|
|
@ -626,7 +626,7 @@ InternetSearchDataSource::FireTimer(nsITimer* aTimer, void* aClosure)
|
|||
nsCOMPtr<nsIChannel> channel;
|
||||
if (NS_FAILED(rv = NS_OpenURI(getter_AddRefs(channel), uri, nsnull))) return;
|
||||
|
||||
channel->SetLoadFlags(nsIRequest::FORCE_VALIDATION | nsIRequest::VALIDATE_ALWAYS);
|
||||
channel->SetLoadFlags(nsIRequest::VALIDATE_ALWAYS);
|
||||
|
||||
nsCOMPtr<nsIHTTPChannel> httpChannel (do_QueryInterface(channel));
|
||||
if (!httpChannel) return;
|
||||
|
@ -3562,7 +3562,7 @@ InternetSearchDataSource::DoSearch(nsIRDFResource *source, nsIRDFResource *engin
|
|||
}
|
||||
|
||||
// get it just from the cache if we can (do not validate)
|
||||
channel->SetLoadFlags(nsIRequest::VALIDATE_NEVER);
|
||||
channel->SetLoadFlags(nsIRequest::LOAD_FROM_CACHE);
|
||||
|
||||
if (methodStr.EqualsIgnoreCase("post"))
|
||||
{
|
||||
|
|
|
@ -176,9 +176,9 @@ nsStreamTransfer::SelectFileAndTransferLocationSpec( char const *aURL,
|
|||
rv = NS_OpenURI( getter_AddRefs( channel ), uri, nsnull );
|
||||
|
||||
if ( NS_SUCCEEDED( rv ) && channel ) {
|
||||
// See if VALIDATE_NEVER is called for.
|
||||
// See if LOAD_FROM_CACHE is called for.
|
||||
if ( doNotValidate ) {
|
||||
channel->SetLoadFlags( nsIRequest::VALIDATE_NEVER );
|
||||
channel->SetLoadFlags( nsIRequest::LOAD_FROM_CACHE );
|
||||
}
|
||||
// Post data provided?
|
||||
if ( postData ) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче