Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Unified Diff: Source/platform/network/ResourceResponse.cpp

Issue 232993004: Reland "Allow cache reuse of some requests with Cache-Control headers" (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/platform/network/ResourceResponse.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/network/ResourceResponse.cpp
diff --git a/Source/platform/network/ResourceResponse.cpp b/Source/platform/network/ResourceResponse.cpp
index ea22e78ea2851a5411cf9de280c0cf29376ea646..65c53e54cc629678411fd380b1815b1ed4f66e7e 100644
--- a/Source/platform/network/ResourceResponse.cpp
+++ b/Source/platform/network/ResourceResponse.cpp
@@ -27,15 +27,11 @@
#include "config.h"
#include "platform/network/ResourceResponse.h"
-#include "platform/network/HTTPParsers.h"
#include "wtf/CurrentTime.h"
-#include "wtf/MathExtras.h"
#include "wtf/StdLibExtras.h"
namespace WebCore {
-static void parseCacheHeader(const String& header, Vector<pair<String, String> >& result);
-
ResourceResponse::ResourceResponse()
: m_expectedContentLength(0)
, m_httpStatusCode(0)
@@ -44,15 +40,10 @@ ResourceResponse::ResourceResponse()
, m_connectionID(0)
, m_connectionReused(false)
, m_isNull(true)
- , m_haveParsedCacheControlHeader(false)
, m_haveParsedAgeHeader(false)
, m_haveParsedDateHeader(false)
, m_haveParsedExpiresHeader(false)
, m_haveParsedLastModifiedHeader(false)
- , m_cacheControlContainsNoCache(false)
- , m_cacheControlContainsNoStore(false)
- , m_cacheControlContainsMustRevalidate(false)
- , m_cacheControlMaxAge(0.0)
, m_age(0.0)
, m_date(0.0)
, m_expires(0.0)
@@ -81,15 +72,10 @@ ResourceResponse::ResourceResponse(const KURL& url, const AtomicString& mimeType
, m_connectionID(0)
, m_connectionReused(false)
, m_isNull(false)
- , m_haveParsedCacheControlHeader(false)
, m_haveParsedAgeHeader(false)
, m_haveParsedDateHeader(false)
, m_haveParsedExpiresHeader(false)
, m_haveParsedLastModifiedHeader(false)
- , m_cacheControlContainsNoCache(false)
- , m_cacheControlContainsNoStore(false)
- , m_cacheControlContainsMustRevalidate(false)
- , m_cacheControlMaxAge(0.0)
, m_age(0.0)
, m_date(0.0)
, m_expires(0.0)
@@ -277,19 +263,29 @@ const AtomicString& ResourceResponse::httpHeaderField(const char* name) const
return m_httpHeaderFields.get(name);
}
+static const AtomicString& cacheControlHeaderString()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, cacheControlHeader, ("cache-control", AtomicString::ConstructFromLiteral));
+ return cacheControlHeader;
+}
+
+static const AtomicString& pragmaHeaderString()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma", AtomicString::ConstructFromLiteral));
+ return pragmaHeader;
+}
+
void ResourceResponse::updateHeaderParsedState(const AtomicString& name)
{
DEFINE_STATIC_LOCAL(const AtomicString, ageHeader, ("age", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, cacheControlHeader, ("cache-control", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, dateHeader, ("date", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, expiresHeader, ("expires", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, lastModifiedHeader, ("last-modified", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma", AtomicString::ConstructFromLiteral));
if (equalIgnoringCase(name, ageHeader))
m_haveParsedAgeHeader = false;
- else if (equalIgnoringCase(name, cacheControlHeader) || equalIgnoringCase(name, pragmaHeader))
- m_haveParsedCacheControlHeader = false;
+ else if (equalIgnoringCase(name, cacheControlHeaderString()) || equalIgnoringCase(name, pragmaHeaderString()))
+ m_cacheControlHeader = CacheControlHeader();
else if (equalIgnoringCase(name, dateHeader))
m_haveParsedDateHeader = false;
else if (equalIgnoringCase(name, expiresHeader))
@@ -324,80 +320,25 @@ const HTTPHeaderMap& ResourceResponse::httpHeaderFields() const
return m_httpHeaderFields;
}
-void ResourceResponse::parseCacheControlDirectives() const
-{
- ASSERT(!m_haveParsedCacheControlHeader);
-
- m_haveParsedCacheControlHeader = true;
-
- m_cacheControlContainsMustRevalidate = false;
- m_cacheControlContainsNoCache = false;
- m_cacheControlMaxAge = std::numeric_limits<double>::quiet_NaN();
-
- DEFINE_STATIC_LOCAL(const AtomicString, cacheControlString, ("cache-control", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, noCacheDirective, ("no-cache", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, noStoreDirective, ("no-store", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, mustRevalidateDirective, ("must-revalidate", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, maxAgeDirective, ("max-age", AtomicString::ConstructFromLiteral));
-
- const AtomicString& cacheControlValue = m_httpHeaderFields.get(cacheControlString);
- if (!cacheControlValue.isEmpty()) {
- Vector<pair<String, String> > directives;
- parseCacheHeader(cacheControlValue, directives);
-
- size_t directivesSize = directives.size();
- for (size_t i = 0; i < directivesSize; ++i) {
- // RFC2616 14.9.1: A no-cache directive with a value is only meaningful for proxy caches.
- // It should be ignored by a browser level cache.
- if (equalIgnoringCase(directives[i].first, noCacheDirective) && directives[i].second.isEmpty())
- m_cacheControlContainsNoCache = true;
- else if (equalIgnoringCase(directives[i].first, noStoreDirective))
- m_cacheControlContainsNoStore = true;
- else if (equalIgnoringCase(directives[i].first, mustRevalidateDirective))
- m_cacheControlContainsMustRevalidate = true;
- else if (equalIgnoringCase(directives[i].first, maxAgeDirective)) {
- if (!std::isnan(m_cacheControlMaxAge)) {
- // First max-age directive wins if there are multiple ones.
- continue;
- }
- bool ok;
- double maxAge = directives[i].second.toDouble(&ok);
- if (ok)
- m_cacheControlMaxAge = maxAge;
- }
- }
- }
-
- if (!m_cacheControlContainsNoCache) {
- // Handle Pragma: no-cache
- // This is deprecated and equivalent to Cache-control: no-cache
- // Don't bother tokenizing the value, it is not important
- DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma", AtomicString::ConstructFromLiteral));
- const AtomicString& pragmaValue = m_httpHeaderFields.get(pragmaHeader);
-
- m_cacheControlContainsNoCache = pragmaValue.lower().contains(noCacheDirective);
- }
-}
-
-bool ResourceResponse::cacheControlContainsNoCache() const
+bool ResourceResponse::cacheControlContainsNoCache()
{
- if (!m_haveParsedCacheControlHeader)
- parseCacheControlDirectives();
- return m_cacheControlContainsNoCache;
+ if (!m_cacheControlHeader.parsed)
+ m_cacheControlHeader = parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeaderString()), m_httpHeaderFields.get(pragmaHeaderString()));
+ return m_cacheControlHeader.containsNoCache;
}
-bool ResourceResponse::cacheControlContainsNoStore() const
+bool ResourceResponse::cacheControlContainsNoStore()
{
- if (!m_haveParsedCacheControlHeader)
- parseCacheControlDirectives();
- return m_cacheControlContainsNoStore;
+ if (!m_cacheControlHeader.parsed)
+ m_cacheControlHeader = parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeaderString()), m_httpHeaderFields.get(pragmaHeaderString()));
+ return m_cacheControlHeader.containsNoStore;
}
-bool ResourceResponse::cacheControlContainsMustRevalidate() const
+bool ResourceResponse::cacheControlContainsMustRevalidate()
{
- if (!m_haveParsedCacheControlHeader)
- parseCacheControlDirectives();
- return m_cacheControlContainsMustRevalidate;
+ if (!m_cacheControlHeader.parsed)
+ m_cacheControlHeader = parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeaderString()), m_httpHeaderFields.get(pragmaHeaderString()));
+ return m_cacheControlHeader.containsMustRevalidate;
}
bool ResourceResponse::hasCacheValidatorFields() const
@@ -407,11 +348,11 @@ bool ResourceResponse::hasCacheValidatorFields() const
return !m_httpHeaderFields.get(lastModifiedHeader).isEmpty() || !m_httpHeaderFields.get(eTagHeader).isEmpty();
}
-double ResourceResponse::cacheControlMaxAge() const
+double ResourceResponse::cacheControlMaxAge()
{
- if (!m_haveParsedCacheControlHeader)
- parseCacheControlDirectives();
- return m_cacheControlMaxAge;
+ if (!m_cacheControlHeader.parsed)
+ m_cacheControlHeader = parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeaderString()), m_httpHeaderFields.get(pragmaHeaderString()));
+ return m_cacheControlHeader.maxAge;
}
static double parseDateValueInHeader(const HTTPHeaderMap& headers, const AtomicString& headerName)
@@ -585,99 +526,4 @@ bool ResourceResponse::compare(const ResourceResponse& a, const ResourceResponse
return true;
}
-static bool isCacheHeaderSeparator(UChar c)
-{
- // See RFC 2616, Section 2.2
- switch (c) {
- case '(':
- case ')':
- case '<':
- case '>':
- case '@':
- case ',':
- case ';':
- case ':':
- case '\\':
- case '"':
- case '/':
- case '[':
- case ']':
- case '?':
- case '=':
- case '{':
- case '}':
- case ' ':
- case '\t':
- return true;
- default:
- return false;
- }
-}
-
-static bool isControlCharacter(UChar c)
-{
- return c < ' ' || c == 127;
-}
-
-static inline String trimToNextSeparator(const String& str)
-{
- return str.substring(0, str.find(isCacheHeaderSeparator));
-}
-
-static void parseCacheHeader(const String& header, Vector<pair<String, String> >& result)
-{
- const String safeHeader = header.removeCharacters(isControlCharacter);
- unsigned max = safeHeader.length();
- for (unsigned pos = 0; pos < max; /* pos incremented in loop */) {
- size_t nextCommaPosition = safeHeader.find(',', pos);
- size_t nextEqualSignPosition = safeHeader.find('=', pos);
- if (nextEqualSignPosition != kNotFound && (nextEqualSignPosition < nextCommaPosition || nextCommaPosition == kNotFound)) {
- // Get directive name, parse right hand side of equal sign, then add to map
- String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos).stripWhiteSpace());
- pos += nextEqualSignPosition - pos + 1;
-
- String value = safeHeader.substring(pos, max - pos).stripWhiteSpace();
- if (value[0] == '"') {
- // The value is a quoted string
- size_t nextDoubleQuotePosition = value.find('"', 1);
- if (nextDoubleQuotePosition != kNotFound) {
- // Store the value as a quoted string without quotes
- result.append(pair<String, String>(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
- pos += (safeHeader.find('"', pos) - pos) + nextDoubleQuotePosition + 1;
- // Move past next comma, if there is one
- size_t nextCommaPosition2 = safeHeader.find(',', pos);
- if (nextCommaPosition2 != kNotFound)
- pos += nextCommaPosition2 - pos + 1;
- else
- return; // Parse error if there is anything left with no comma
- } else {
- // Parse error; just use the rest as the value
- result.append(pair<String, String>(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
- return;
- }
- } else {
- // The value is a token until the next comma
- size_t nextCommaPosition2 = value.find(',');
- if (nextCommaPosition2 != kNotFound) {
- // The value is delimited by the next comma
- result.append(pair<String, String>(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
- pos += (safeHeader.find(',', pos) - pos) + 1;
- } else {
- // The rest is the value; no change to value needed
- result.append(pair<String, String>(directive, trimToNextSeparator(value)));
- return;
- }
- }
- } else if (nextCommaPosition != kNotFound && (nextCommaPosition < nextEqualSignPosition || nextEqualSignPosition == kNotFound)) {
- // Add directive to map with empty string as value
- result.append(pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
- pos += nextCommaPosition - pos + 1;
- } else {
- // Add last directive to map with empty string as value
- result.append(pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
- return;
- }
- }
-}
-
}
« no previous file with comments | « Source/platform/network/ResourceResponse.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698