author | Patrick McManus <mcmanus@ducksong.com> |
Wed, 04 May 2016 22:37:53 -0400 | |
changeset 297199 | 06a3edfb00cd |
parent 297198 | 1c91c9a5fdba |
child 297200 | 546b3763d1b6 |
push id | 30253 |
push user | cbook@mozilla.com |
push date | 2016-05-13 09:59 +0000 |
treeherder | mozilla-central@5a2deb5a9b09 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mayhemer |
bugs | 1267474 |
milestone | 49.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/netwerk/base/nsIRequest.idl +++ b/netwerk/base/nsIRequest.idl @@ -175,17 +175,17 @@ interface nsIRequest : nsISupports 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. + * its expiration time (unless it is https with Cache-Control: immutable) * * VALIDATE_NEVER disables validation of cached content, unless it arrived * with the "Cache: no-store" header, or arrived via HTTPS with the * "Cache: no-cache" header. * * VALIDATE_ONCE_PER_SESSION disables validation of expired content, * provided it has already been validated (at least once) since the start * of this session.
--- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -3402,16 +3402,23 @@ nsHttpChannel::OnCacheEntryCheck(nsICach NS_ENSURE_SUCCESS(rv,rv); bool doValidation = false; bool canAddImsHeader = true; bool isForcedValid = false; entry->GetIsForcedValid(&isForcedValid); + nsXPIDLCString framedBuf; + rv = entry->GetMetaDataElement("strongly-framed", getter_Copies(framedBuf)); + // describe this in terms of explicitly weakly framed so as to be backwards + // compatible with old cache contents which dont have strongly-framed makers + bool weaklyFramed = NS_SUCCEEDED(rv) && framedBuf.EqualsLiteral("0"); + bool isImmutable = !weaklyFramed && isHttps && mCachedResponseHead->Immutable(); + // Cached entry is not the entity we request (see bug #633743) if (ResponseWouldVary(entry)) { LOG(("Validating based on Vary headers returning TRUE\n")); canAddImsHeader = false; doValidation = true; } // Check isForcedValid to see if it is possible to skip validation. // Don't skip validation if we have serious reason to believe that this @@ -3427,17 +3434,17 @@ nsHttpChannel::OnCacheEntryCheck(nsICach } // If the LOAD_FROM_CACHE flag is set, any cached data can simply be used else if (mLoadFlags & nsIRequest::LOAD_FROM_CACHE || mAllowStaleCacheContent) { LOG(("NOT validating based on LOAD_FROM_CACHE load flag\n")); doValidation = false; } // If the VALIDATE_ALWAYS flag is set, any cached data won't be used until // it's revalidated with the server. - else if (mLoadFlags & nsIRequest::VALIDATE_ALWAYS) { + else if ((mLoadFlags & nsIRequest::VALIDATE_ALWAYS) && !isImmutable) { LOG(("Validating based on VALIDATE_ALWAYS load flag\n")); doValidation = true; } // 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 & nsIRequest::VALIDATE_NEVER) { LOG(("VALIDATE_NEVER set\n")); // if no-store validate cached response (see bug 112564) @@ -3554,39 +3561,33 @@ nsHttpChannel::OnCacheEntryCheck(nsICach if (doValidation && mInterceptCache == INTERCEPTED) { doValidation = false; } mCachedContentIsValid = !doValidation; if (doValidation) { - nsXPIDLCString buf; - rv = entry->GetMetaDataElement("strongly-framed", getter_Copies(buf)); - // describe this in terms of explicitly weakly framed so as to be backwards - // compatible with old cache contents which dont have strongly-framed makers - bool weaklyFramed = NS_SUCCEEDED(rv) && buf.EqualsLiteral("0"); - // // now, we are definitely going to issue a HTTP request to the server. // make it conditional if possible. // // do not attempt to validate no-store content, since servers will not // expect it to be cached. (we only keep it in our cache for the // purposes of back/forward, etc.) // // the request method MUST be either GET or HEAD (see bug 175641) and // the cached response code must be < 400 // - // the cached content must not be weakly framed + // the cached content must not be weakly framed or marked immutable // // do not override conditional headers when consumer has defined its own if (!mCachedResponseHead->NoStore() && (mRequestHead.IsGet() || mRequestHead.IsHead()) && - !mCustomConditionalRequest && !weaklyFramed && + !mCustomConditionalRequest && !weaklyFramed && !isImmutable && (mCachedResponseHead->Status() < 400)) { if (mConcurentCacheAccess) { // In case of concurrent read and also validation request we // must wait for the current writer to close the output stream // first. Otherwise, when the writer's job would have been interrupted // before all the data were downloaded, we'd have to do a range request // which would be a second request in line during this channel's
--- a/netwerk/protocol/http/nsHttpResponseHead.cpp +++ b/netwerk/protocol/http/nsHttpResponseHead.cpp @@ -638,16 +638,17 @@ nsHttpResponseHead::Reset() ClearHeaders(); mVersion = NS_HTTP_VERSION_1_1; mStatus = 200; mContentLength = -1; mCacheControlPrivate = false; mCacheControlNoStore = false; mCacheControlNoCache = false; + mCacheControlImmutable = false; mPragmaNoCache = false; mStatusText.Truncate(); mContentType.Truncate(); mContentCharset.Truncate(); } nsresult nsHttpResponseHead::ParseDateHeader(nsHttpAtom header, uint32_t *result) const @@ -807,31 +808,37 @@ nsHttpResponseHead::ParseVersion(const c void nsHttpResponseHead::ParseCacheControl(const char *val) { if (!(val && *val)) { // clear flags mCacheControlPrivate = false; mCacheControlNoCache = false; mCacheControlNoStore = false; + mCacheControlImmutable = false; return; } // search header value for occurrence of "private" if (nsHttp::FindToken(val, "private", HTTP_HEADER_VALUE_SEPS)) mCacheControlPrivate = true; // search header value for occurrence(s) of "no-cache" but ignore // occurrence(s) of "no-cache=blah" if (nsHttp::FindToken(val, "no-cache", HTTP_HEADER_VALUE_SEPS)) mCacheControlNoCache = true; // search header value for occurrence of "no-store" if (nsHttp::FindToken(val, "no-store", HTTP_HEADER_VALUE_SEPS)) mCacheControlNoStore = true; + + // search header value for occurrence of "immutable" + if (nsHttp::FindToken(val, "immutable", HTTP_HEADER_VALUE_SEPS)) { + mCacheControlImmutable = true; + } } void nsHttpResponseHead::ParsePragma(const char *val) { LOG(("nsHttpResponseHead::ParsePragma [val=%s]\n", val)); if (!(val && *val)) {
--- a/netwerk/protocol/http/nsHttpResponseHead.h +++ b/netwerk/protocol/http/nsHttpResponseHead.h @@ -27,31 +27,33 @@ class nsHttpResponseHead { public: nsHttpResponseHead() : mVersion(NS_HTTP_VERSION_1_1) , mStatus(200) , mContentLength(-1) , mCacheControlPrivate(false) , mCacheControlNoStore(false) , mCacheControlNoCache(false) + , mCacheControlImmutable(false) , mPragmaNoCache(false) {} const nsHttpHeaderArray & Headers() const { return mHeaders; } nsHttpHeaderArray &Headers() { return mHeaders; } nsHttpVersion Version() const { return mVersion; } // X11's Xlib.h #defines 'Status' to 'int' on some systems! #undef Status uint16_t Status() const { return mStatus; } const nsAFlatCString &StatusText() const { return mStatusText; } int64_t ContentLength() const { return mContentLength; } const nsAFlatCString &ContentType() const { return mContentType; } const nsAFlatCString &ContentCharset() const { return mContentCharset; } bool Private() const { return mCacheControlPrivate; } bool NoStore() const { return mCacheControlNoStore; } bool NoCache() const { return (mCacheControlNoCache || mPragmaNoCache); } + bool Immutable() const { return mCacheControlImmutable; } /** * Full length of the entity. For byte-range requests, this may be larger * than ContentLength(), which will only represent the requested part of the * entity. */ int64_t TotalEntitySize() const; const char *PeekHeader(nsHttpAtom h) const { return mHeaders.PeekHeader(h); } @@ -128,16 +130,17 @@ public: mStatus == aOther.mStatus && mStatusText == aOther.mStatusText && mContentLength == aOther.mContentLength && mContentType == aOther.mContentType && mContentCharset == aOther.mContentCharset && mCacheControlPrivate == aOther.mCacheControlPrivate && mCacheControlNoCache == aOther.mCacheControlNoCache && mCacheControlNoStore == aOther.mCacheControlNoStore && + mCacheControlImmutable == aOther.mCacheControlImmutable && mPragmaNoCache == aOther.mPragmaNoCache; } private: void AssignDefaultStatusText(); void ParseVersion(const char *); void ParseCacheControl(const char *); void ParsePragma(const char *); @@ -149,16 +152,17 @@ private: uint16_t mStatus; nsCString mStatusText; int64_t mContentLength; nsCString mContentType; nsCString mContentCharset; bool mCacheControlPrivate; bool mCacheControlNoStore; bool mCacheControlNoCache; + bool mCacheControlImmutable; bool mPragmaNoCache; friend struct IPC::ParamTraits<nsHttpResponseHead>; }; } // namespace net } // namespace mozilla