mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 20:49:27 +00:00
fixes bug 112564 "Cache-Control: no-cache should not affect back/forward
buttons" r=dougt, sr=brendan
This commit is contained in:
parent
89c84455fe
commit
a8fec387ad
@ -5162,8 +5162,8 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI,
|
||||
nsCOMPtr<nsIURI> referrerURI;
|
||||
nsCOMPtr<nsISupports> cacheKey;
|
||||
nsCOMPtr<nsISupports> cacheToken;
|
||||
PRPackedBool expired = PR_FALSE;
|
||||
nsXPIDLCString val;
|
||||
PRBool expired = PR_FALSE;
|
||||
PRBool discardLayoutState = PR_FALSE;
|
||||
if (aChannel) {
|
||||
nsCOMPtr<nsICachingChannel>
|
||||
cacheChannel(do_QueryInterface(aChannel));
|
||||
@ -5183,7 +5183,16 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI,
|
||||
if (httpChannel) {
|
||||
httpChannel->GetUploadStream(getter_AddRefs(inputStream));
|
||||
httpChannel->GetReferrer(getter_AddRefs(referrerURI));
|
||||
httpChannel->GetResponseHeader("Cache-Control", getter_Copies(val));
|
||||
|
||||
// figure out if SH should be saving layout state (see bug 112564)
|
||||
nsCOMPtr<nsISupports> securityInfo;
|
||||
PRBool noStore = PR_FALSE, noCache = PR_FALSE;
|
||||
|
||||
httpChannel->GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||
httpChannel->IsNoStoreResponse(&noStore);
|
||||
httpChannel->IsNoCacheResponse(&noCache);
|
||||
|
||||
discardLayoutState = noStore || (noCache && securityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5199,15 +5208,15 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI,
|
||||
* HistoryLayoutState. By default, SH will set this
|
||||
* flag to PR_TRUE and save HistoryLayoutState.
|
||||
*/
|
||||
if (val && (PL_strcasestr(val, "no-store") || PL_strcasestr(val, "no-cache"))) {
|
||||
if (discardLayoutState) {
|
||||
entry->SetSaveLayoutStateFlag(PR_FALSE);
|
||||
}
|
||||
if (cacheToken) {
|
||||
// Check if the page has expired from cache
|
||||
nsCOMPtr<nsICacheEntryDescriptor> cacheEntryDesc(do_QueryInterface(cacheToken));
|
||||
if (cacheEntryDesc) {
|
||||
nsCOMPtr<nsICacheEntryInfo> cacheEntryInfo(do_QueryInterface(cacheToken));
|
||||
if (cacheEntryInfo) {
|
||||
PRUint32 expTime;
|
||||
cacheEntryDesc->GetExpirationTime(&expTime);
|
||||
cacheEntryInfo->GetExpirationTime(&expTime);
|
||||
PRUint32 now = PRTimeToSeconds(PR_Now());
|
||||
if (expTime <= now)
|
||||
expired = PR_TRUE;
|
||||
|
@ -79,6 +79,18 @@ interface nsIHttpChannel : nsIChannel
|
||||
void setResponseHeader(in string header, in string value);
|
||||
void visitResponseHeaders(in nsIHttpHeaderVisitor visitor);
|
||||
|
||||
/**
|
||||
* True if the server sent a "Cache-control: no-store" response header.
|
||||
*/
|
||||
boolean isNoStoreResponse();
|
||||
|
||||
/**
|
||||
* True if the server sent the equivalent of a "Cache-control: no-cache"
|
||||
* response header. Other equivalent response headers include: "Pragma:
|
||||
* no-cache" and "Expires" with a date-value in the past.
|
||||
*/
|
||||
boolean isNoCacheResponse();
|
||||
|
||||
/**
|
||||
* Get the charset for the response, which may be NULL if not specified
|
||||
* by the server (ie. the Content-Type header may not specify a charset).
|
||||
|
@ -742,7 +742,7 @@ nsHttpChannel::UpdateExpirationTime()
|
||||
|
||||
NS_ENSURE_TRUE(mResponseHead, NS_ERROR_FAILURE);
|
||||
|
||||
if (!mResponseHead->MustRevalidate()) {
|
||||
if (!mResponseHead->MustValidate()) {
|
||||
nsresult rv;
|
||||
PRUint32 freshnessLifetime, currentAge;
|
||||
|
||||
@ -841,33 +841,36 @@ nsHttpChannel::CheckCache()
|
||||
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) {
|
||||
else if (mLoadFlags & VALIDATE_ALWAYS) {
|
||||
LOG(("Validating based on VALIDATE_ALWAYS load flag\n"));
|
||||
doValidation = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// check revalidation is strictly required.
|
||||
if (mCachedResponseHead->MustRevalidate()) {
|
||||
// Even if the VALIDATE_NEVER flag is set, there are still some cases in
|
||||
// which we must validate the cached response with the server.
|
||||
else if (mLoadFlags & VALIDATE_NEVER) {
|
||||
LOG(("VALIDATE_NEVER set\n"));
|
||||
// if no-store or if no-cache and ssl, validate cached response (see
|
||||
// bug 112564 for an explanation of this logic)
|
||||
if (mCachedResponseHead->NoStore() ||
|
||||
(mCachedResponseHead->NoCache() && mConnectionInfo->UsingSSL())) {
|
||||
LOG(("Validating based on (no-store || (no-cache && ssl)) logic\n"));
|
||||
doValidation = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
LOG(("NOT validating based on VALIDATE_NEVER load flag\n"));
|
||||
doValidation = PR_FALSE;
|
||||
}
|
||||
}
|
||||
// check if validation is strictly required...
|
||||
else if (mCachedResponseHead->MustValidate()) {
|
||||
LOG(("Validating based on MustValidate() returning TRUE\n"));
|
||||
doValidation = PR_TRUE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// delay checking this flag until we've verified that the response headers
|
||||
// do not require mandatory revalidation.
|
||||
if (mLoadFlags & VALIDATE_NEVER) {
|
||||
LOG(("Not validating based on VALIDATE_NEVER flag\n"));
|
||||
doValidation = PR_FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Check if the cache entry has expired...
|
||||
{
|
||||
else {
|
||||
PRUint32 time = 0; // a temporary variable for storing time values...
|
||||
|
||||
rv = mCacheEntry->GetExpirationTime(&time);
|
||||
@ -875,6 +878,8 @@ nsHttpChannel::CheckCache()
|
||||
|
||||
if (NowInSeconds() <= time)
|
||||
doValidation = PR_FALSE;
|
||||
else if (mCachedResponseHead->MustValidateIfExpired())
|
||||
doValidation = PR_TRUE;
|
||||
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
|
||||
@ -894,7 +899,6 @@ nsHttpChannel::CheckCache()
|
||||
// has been accessed in this session, and validate if so.
|
||||
doValidation = (nsHttpHandler::get()->SessionStartTime() > time);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
doValidation = PR_TRUE;
|
||||
@ -902,10 +906,11 @@ nsHttpChannel::CheckCache()
|
||||
LOG(("%salidating based on expiration time\n", doValidation ? "V" : "Not v"));
|
||||
}
|
||||
|
||||
end:
|
||||
mCachedContentIsValid = !doValidation;
|
||||
|
||||
if (doValidation) {
|
||||
// add validation headers unless the cached response is marked no-store...
|
||||
// this'll force no-store content to be refetched each time from the server.
|
||||
if (doValidation && !mCachedResponseHead->NoStore()) {
|
||||
const char *val;
|
||||
// Add If-Modified-Since header if a Last-Modified was given
|
||||
val = mCachedResponseHead->PeekHeader(nsHttp::Last_Modified);
|
||||
@ -1016,7 +1021,6 @@ nsHttpChannel::CloseCacheEntry(nsresult status)
|
||||
nsresult
|
||||
nsHttpChannel::InitCacheEntry()
|
||||
{
|
||||
const char *val;
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_UNEXPECTED);
|
||||
@ -1029,16 +1033,10 @@ nsHttpChannel::InitCacheEntry()
|
||||
LOG(("nsHttpChannel::InitCacheEntry [this=%x entry=%x]\n",
|
||||
this, mCacheEntry.get()));
|
||||
|
||||
// XXX blow away any existing cache meta data
|
||||
|
||||
// The no-store directive within the 'Cache-Control:' header indicates
|
||||
// that we should not store the response in the cache.
|
||||
val = mResponseHead->PeekHeader(nsHttp::Cache_Control);
|
||||
if (val && PL_strcasestr(val, "no-store")) {
|
||||
LOG(("Inhibiting caching because of \"%s\"\n", val));
|
||||
CloseCacheEntry(NS_ERROR_ABORT);
|
||||
return NS_OK;
|
||||
}
|
||||
// that we must not store the response in a persistent cache.
|
||||
if (mResponseHead->NoStore())
|
||||
mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
|
||||
|
||||
// For HTTPS transactions, the storage policy will already be IN_MEMORY.
|
||||
// We are concerned instead about load attributes which may have changed.
|
||||
@ -1077,16 +1075,6 @@ nsHttpChannel::FinalizeCacheEntry()
|
||||
LOG(("nsHttpChannel::FinalizeCacheEntry [this=%x]\n", this));
|
||||
|
||||
if (mResponseHead && mResponseHeadersModified) {
|
||||
// The no-store directive within the 'Cache-Control:' header indicates
|
||||
// that we should not store the response in the cache.
|
||||
// XXX this should probably be done from within SetResponseHeader.
|
||||
const char *val = mResponseHead->PeekHeader(nsHttp::Cache_Control);
|
||||
if (val && PL_strcasestr(val, "no-store")) {
|
||||
LOG(("Dooming cache entry because of \"%s\"\n", val));
|
||||
mCacheEntry->Doom();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Set the expiration time for this cache entry
|
||||
nsresult rv = UpdateExpirationTime();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -2281,6 +2269,26 @@ nsHttpChannel::VisitResponseHeaders(nsIHttpHeaderVisitor *visitor)
|
||||
return mResponseHead->Headers().VisitHeaders(visitor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::IsNoStoreResponse(PRBool *value)
|
||||
{
|
||||
if (!mResponseHead)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
*value = mResponseHead->NoStore();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::IsNoCacheResponse(PRBool *value)
|
||||
{
|
||||
if (!mResponseHead)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
*value = mResponseHead->NoCache();
|
||||
if (!*value)
|
||||
*value = mResponseHead->ExpiresInPast();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::GetCharset(char **value)
|
||||
{
|
||||
|
@ -31,6 +31,21 @@
|
||||
// nsHttpResponseHead <public>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsHttpResponseHead::SetHeader(nsHttpAtom hdr, const char *val)
|
||||
{
|
||||
nsresult rv = mHeaders.SetHeader(hdr, val);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// response to changes in these headers
|
||||
if (hdr == nsHttp::Cache_Control)
|
||||
ParseCacheControl(val);
|
||||
else if (hdr == nsHttp::Pragma)
|
||||
ParsePragma(val);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpResponseHead::SetContentLength(PRInt32 len)
|
||||
{
|
||||
@ -143,7 +158,7 @@ nsHttpResponseHead::ParseStatusLine(char *line)
|
||||
|
||||
if ((mVersion == NS_HTTP_VERSION_0_9) || !(line = PL_strchr(line, ' '))) {
|
||||
mStatus = 200;
|
||||
mStatusText.Adopt(nsCRT::strdup("OK"));
|
||||
mStatusText = nsCRT::strdup("OK");
|
||||
}
|
||||
else {
|
||||
// Status-Code
|
||||
@ -156,14 +171,14 @@ nsHttpResponseHead::ParseStatusLine(char *line)
|
||||
// Reason-Phrase is whatever is remaining of the line
|
||||
if (!(line = PL_strchr(line, ' '))) {
|
||||
LOG(("mal-formed response status line; assuming statusText = 'OK'\n"));
|
||||
mStatusText.Adopt(nsCRT::strdup("OK"));
|
||||
mStatusText = nsCRT::strdup("OK");
|
||||
}
|
||||
else
|
||||
mStatusText.Adopt(nsCRT::strdup(++line));
|
||||
mStatusText = nsCRT::strdup(++line);
|
||||
}
|
||||
|
||||
LOG(("Have status line [version=%u status=%u statusText=%s]\n",
|
||||
PRUintn(mVersion), PRUintn(mStatus), mStatusText.get()));
|
||||
PRUintn(mVersion), PRUintn(mStatus), mStatusText));
|
||||
}
|
||||
|
||||
void
|
||||
@ -179,6 +194,10 @@ nsHttpResponseHead::ParseHeaderLine(char *line)
|
||||
mContentLength = atoi(val);
|
||||
else if (hdr == nsHttp::Content_Type)
|
||||
ParseContentType(val);
|
||||
else if (hdr == nsHttp::Cache_Control)
|
||||
ParseCacheControl(val);
|
||||
else if (hdr == nsHttp::Pragma)
|
||||
ParsePragma(val);
|
||||
}
|
||||
|
||||
// From section 13.2.3 of RFC2616, we compute the current age of a cached
|
||||
@ -280,47 +299,33 @@ nsHttpResponseHead::ComputeFreshnessLifetime(PRUint32 *result)
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHttpResponseHead::MustRevalidate()
|
||||
nsHttpResponseHead::MustValidate()
|
||||
{
|
||||
const char *val;
|
||||
|
||||
LOG(("nsHttpResponseHead::MustRevalidate ??\n"));
|
||||
LOG(("nsHttpResponseHead::MustValidate ??\n"));
|
||||
|
||||
// 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).
|
||||
val = PeekHeader(nsHttp::Cache_Control);
|
||||
if (val && PL_strcasestr(val, "must-revalidate")) {
|
||||
LOG(("Must revalidate based on \"%s\" header\n", val));
|
||||
// The no-cache response header indicates that we must validate this
|
||||
// cached response before reusing.
|
||||
if (NoCache()) {
|
||||
LOG(("Must validate since response contains 'no-cache' header\n"));
|
||||
return PR_TRUE;
|
||||
}
|
||||
// The no-cache directive within the 'Cache-Control:' header indicates
|
||||
// that we must validate this cached response before reusing.
|
||||
if (val && PL_strcasestr(val, "no-cache")) {
|
||||
LOG(("Must revalidate based on \"%s\" header\n", val));
|
||||
return PR_TRUE;
|
||||
}
|
||||
// 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.
|
||||
|
||||
// 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.
|
||||
val = PeekHeader(nsHttp::Pragma);
|
||||
if (val && PL_strcasestr(val, "no-cache")) {
|
||||
LOG(("Must revalidate based on \"%s\" header\n", val));
|
||||
// Likewise, if the response is no-store, then we must validate this
|
||||
// cached response before reusing. NOTE: it may seem odd that a no-store
|
||||
// response may be cached, but indeed all responses are cached in order
|
||||
// to support File->SaveAs, View->PageSource, and other browser features.
|
||||
if (NoStore()) {
|
||||
LOG(("Must validate since response contains 'no-store' header\n"));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Compare the Expires header to the Date header. If the server sent an
|
||||
// Expires header with a timestamp in the past, then we must validate this
|
||||
// cached response before reusing.
|
||||
PRUint32 expiresVal, dateVal;
|
||||
if (NS_SUCCEEDED(GetExpiresValue(&expiresVal)) &&
|
||||
NS_SUCCEEDED(GetDateValue(&dateVal)) &&
|
||||
expiresVal < dateVal) {
|
||||
LOG(("Must revalidate since Expires < Date\n"));
|
||||
if (ExpiresInPast()) {
|
||||
LOG(("Must validate since Expires < Date\n"));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -339,14 +344,36 @@ nsHttpResponseHead::MustRevalidate()
|
||||
if (val && (PL_strstr(val, "*") ||
|
||||
PL_strcasestr(val, "accept-charset") ||
|
||||
PL_strcasestr(val, "accept-language"))) {
|
||||
LOG(("Must revalidate based on \"%s\" header\n", val));
|
||||
LOG(("Must validate based on \"%s\" header\n", val));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
LOG(("no mandatory revalidation requirement\n"));
|
||||
LOG(("no mandatory validation requirement\n"));
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHttpResponseHead::MustValidateIfExpired()
|
||||
{
|
||||
// according to RFC2616, section 14.9.4:
|
||||
//
|
||||
// When the must-revalidate directive is present in a response received by a
|
||||
// cache, that cache MUST NOT use the entry after it becomes stale to respond to
|
||||
// a subsequent request without first revalidating it with the origin server.
|
||||
//
|
||||
const char *val = PeekHeader(nsHttp::Cache_Control);
|
||||
return val && PL_strcasestr(val, "must-revalidate");
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHttpResponseHead::ExpiresInPast()
|
||||
{
|
||||
PRUint32 expiresVal, dateVal;
|
||||
return NS_SUCCEEDED(GetExpiresValue(&expiresVal)) &&
|
||||
NS_SUCCEEDED(GetDateValue(&dateVal)) &&
|
||||
expiresVal < dateVal;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpResponseHead::UpdateHeaders(nsHttpHeaderArray &headers)
|
||||
{
|
||||
@ -410,10 +437,13 @@ nsHttpResponseHead::Reset()
|
||||
|
||||
mVersion = NS_HTTP_VERSION_1_1;
|
||||
mStatus = 200;
|
||||
mStatusText.Adopt(0);
|
||||
mContentLength = -1;
|
||||
mContentType.Adopt(0);
|
||||
mContentCharset.Adopt(0);
|
||||
mCacheControlNoStore = PR_FALSE;
|
||||
mCacheControlNoCache = PR_FALSE;
|
||||
mPragmaNoCache = PR_FALSE;
|
||||
CRTFREEIF(mStatusText);
|
||||
CRTFREEIF(mContentType);
|
||||
CRTFREEIF(mContentCharset);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -510,14 +540,19 @@ nsHttpResponseHead::ParseVersion(const char *str)
|
||||
// This code is duplicated in nsMultiMixedConv.cpp. If you change it
|
||||
// here, change it there, too!
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsHttpResponseHead::ParseContentType(char *type)
|
||||
{
|
||||
LOG(("nsHttpResponseHead::ParseContentType [type=%s]\n", type));
|
||||
|
||||
// don't bother with an empty content-type header - bug 83465
|
||||
if (!*type)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
// a response could have multiple content type headers... we'll honor
|
||||
// the last one.
|
||||
CRTFREEIF(mContentCharset);
|
||||
CRTFREEIF(mContentType);
|
||||
|
||||
// we don't care about comments (although they are invalid here)
|
||||
char *p = PL_strchr(type, '(');
|
||||
@ -541,7 +576,7 @@ nsHttpResponseHead::ParseContentType(char *type)
|
||||
} while ((*p3 == ' ') || (*p3 == '\t'));
|
||||
*++p3 = 0; // overwrite first char after the charset field
|
||||
|
||||
mContentCharset.Adopt(nsCRT::strdup(p2));
|
||||
mContentCharset = nsCRT::strdup(p2);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -556,7 +591,47 @@ nsHttpResponseHead::ParseContentType(char *type)
|
||||
while (--p >= type)
|
||||
*p = nsCRT::ToLower(*p);
|
||||
|
||||
mContentType.Adopt(nsCRT::strdup(type));
|
||||
|
||||
return NS_OK;
|
||||
mContentType = nsCRT::strdup(type);
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpResponseHead::ParseCacheControl(const char *val)
|
||||
{
|
||||
if (!val) {
|
||||
// clear no-cache flag
|
||||
mCacheControlNoCache = PR_FALSE;
|
||||
return;
|
||||
}
|
||||
else if (!*val)
|
||||
return;
|
||||
|
||||
const char *s = val;
|
||||
|
||||
// search header value for occurance(s) of "no-cache" but ignore
|
||||
// occurance(s) of "no-cache=blah"
|
||||
while (s = PL_strcasestr(s, "no-cache")) {
|
||||
s += (sizeof("no-cache") - 1);
|
||||
if (*s != '=')
|
||||
mCacheControlNoCache = PR_TRUE;
|
||||
}
|
||||
|
||||
// search header value for occurance of "no-store"
|
||||
if (PL_strcasestr(val, "no-store"))
|
||||
mCacheControlNoStore = PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpResponseHead::ParsePragma(const char *val)
|
||||
{
|
||||
if (!val) {
|
||||
// clear no-cache flag
|
||||
mPragmaNoCache = PR_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (*val && !PL_strcasestr(val, "no-cache"))
|
||||
mPragmaNoCache = PR_TRUE;
|
||||
}
|
||||
|
@ -38,7 +38,13 @@ class nsHttpResponseHead
|
||||
public:
|
||||
nsHttpResponseHead() : mVersion(NS_HTTP_VERSION_1_1)
|
||||
, mStatus(200)
|
||||
, mContentLength(-1) {}
|
||||
, mStatusText(nsnull)
|
||||
, mContentLength(-1)
|
||||
, mContentType(nsnull)
|
||||
, mContentCharset(nsnull)
|
||||
, mCacheControlNoStore(PR_FALSE)
|
||||
, mCacheControlNoCache(PR_FALSE)
|
||||
, mPragmaNoCache(PR_FALSE) {}
|
||||
~nsHttpResponseHead() {}
|
||||
|
||||
nsHttpHeaderArray &Headers() { return mHeaders; }
|
||||
@ -48,13 +54,15 @@ public:
|
||||
PRInt32 ContentLength() { return mContentLength; }
|
||||
const char *ContentType() { return mContentType; }
|
||||
const char *ContentCharset() { return mContentCharset; }
|
||||
PRBool NoStore() { return mCacheControlNoStore; }
|
||||
PRBool NoCache() { return (mCacheControlNoCache || mPragmaNoCache); }
|
||||
|
||||
const char *PeekHeader(nsHttpAtom h) { return mHeaders.PeekHeader(h); }
|
||||
nsresult SetHeader(nsHttpAtom h, const char *v) { return mHeaders.SetHeader(h, v); }
|
||||
nsresult SetHeader(nsHttpAtom h, const char *v);
|
||||
nsresult GetHeader(nsHttpAtom h, char **v) { return mHeaders.GetHeader(h, v); }
|
||||
void ClearHeaders() { mHeaders.Clear(); }
|
||||
|
||||
void SetContentType(const char *s) { mContentType.Adopt(s ? nsCRT::strdup(s) : 0); }
|
||||
void SetContentType(const char *s) { CRTFREEIF(mContentType); mContentType = (s ? nsCRT::strdup(s) : 0); }
|
||||
void SetContentLength(PRInt32);
|
||||
|
||||
// write out the response status line and headers as a single text block,
|
||||
@ -75,7 +83,12 @@ public:
|
||||
// cache validation support methods
|
||||
nsresult ComputeFreshnessLifetime(PRUint32 *);
|
||||
nsresult ComputeCurrentAge(PRUint32 now, PRUint32 requestTime, PRUint32 *result);
|
||||
PRBool MustRevalidate();
|
||||
PRBool MustValidate();
|
||||
PRBool MustValidateIfExpired();
|
||||
|
||||
// returns true if the Expires header has a value in the past relative to the
|
||||
// value of the Date header.
|
||||
PRBool ExpiresInPast();
|
||||
|
||||
// update headers...
|
||||
nsresult UpdateHeaders(nsHttpHeaderArray &headers);
|
||||
@ -93,16 +106,21 @@ public:
|
||||
|
||||
private:
|
||||
void ParseVersion(const char *);
|
||||
nsresult ParseContentType(char *);
|
||||
void ParseContentType(char *);
|
||||
void ParseCacheControl(const char *);
|
||||
void ParsePragma(const char *);
|
||||
|
||||
private:
|
||||
nsHttpHeaderArray mHeaders;
|
||||
nsHttpVersion mVersion;
|
||||
PRUint16 mStatus;
|
||||
nsXPIDLCString mStatusText;
|
||||
char *mStatusText;
|
||||
PRInt32 mContentLength;
|
||||
nsXPIDLCString mContentType;
|
||||
nsXPIDLCString mContentCharset;
|
||||
char *mContentType;
|
||||
char *mContentCharset;
|
||||
PRPackedBool mCacheControlNoStore;
|
||||
PRPackedBool mCacheControlNoCache;
|
||||
PRPackedBool mPragmaNoCache;
|
||||
};
|
||||
|
||||
#endif // nsHttpResponseHead_h__
|
||||
|
Loading…
x
Reference in New Issue
Block a user