Commit fdabbaf4 authored by Dave Tapuska's avatar Dave Tapuska Committed by Commit Bot

Add parsing of stale-while-revalidate cache control field.

Add the ability to fetch the stale while revalidate field out of the
cache control header.

BUG=348877

Change-Id: I7e6132b71c10c462019687a150e259e02fe9c332
Reviewed-on: https://chromium-review.googlesource.com/1101242
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568002}
parent 00e7301b
...@@ -404,6 +404,15 @@ double ResourceResponse::CacheControlMaxAge() const { ...@@ -404,6 +404,15 @@ double ResourceResponse::CacheControlMaxAge() const {
return cache_control_header_.max_age; return cache_control_header_.max_age;
} }
double ResourceResponse::CacheControlStaleWhileRevalidate() const {
if (!cache_control_header_.parsed) {
cache_control_header_ = ParseCacheControlDirectives(
http_header_fields_.Get(kCacheControlHeader),
http_header_fields_.Get(kPragmaHeader));
}
return cache_control_header_.stale_while_revalidate;
}
static double ParseDateValueInHeader(const HTTPHeaderMap& headers, static double ParseDateValueInHeader(const HTTPHeaderMap& headers,
const AtomicString& header_name) { const AtomicString& header_name) {
const AtomicString& header_value = headers.Get(header_name); const AtomicString& header_value = headers.Get(header_name);
......
...@@ -218,6 +218,7 @@ class PLATFORM_EXPORT ResourceResponse final { ...@@ -218,6 +218,7 @@ class PLATFORM_EXPORT ResourceResponse final {
bool CacheControlContainsMustRevalidate() const; bool CacheControlContainsMustRevalidate() const;
bool HasCacheValidatorFields() const; bool HasCacheValidatorFields() const;
double CacheControlMaxAge() const; double CacheControlMaxAge() const;
double CacheControlStaleWhileRevalidate() const;
double Date() const; double Date() const;
double Age() const; double Age() const;
double Expires() const; double Expires() const;
......
...@@ -507,11 +507,14 @@ CacheControlHeader ParseCacheControlDirectives( ...@@ -507,11 +507,14 @@ CacheControlHeader ParseCacheControlDirectives(
CacheControlHeader cache_control_header; CacheControlHeader cache_control_header;
cache_control_header.parsed = true; cache_control_header.parsed = true;
cache_control_header.max_age = std::numeric_limits<double>::quiet_NaN(); cache_control_header.max_age = std::numeric_limits<double>::quiet_NaN();
cache_control_header.stale_while_revalidate =
std::numeric_limits<double>::quiet_NaN();
static const char kNoCacheDirective[] = "no-cache"; static const char kNoCacheDirective[] = "no-cache";
static const char kNoStoreDirective[] = "no-store"; static const char kNoStoreDirective[] = "no-store";
static const char kMustRevalidateDirective[] = "must-revalidate"; static const char kMustRevalidateDirective[] = "must-revalidate";
static const char kMaxAgeDirective[] = "max-age"; static const char kMaxAgeDirective[] = "max-age";
static const char kStaleWhileRevalidateDirective[] = "stale-while-revalidate";
if (!cache_control_value.IsEmpty()) { if (!cache_control_value.IsEmpty()) {
Vector<std::pair<String, String>> directives; Vector<std::pair<String, String>> directives;
...@@ -540,6 +543,17 @@ CacheControlHeader ParseCacheControlDirectives( ...@@ -540,6 +543,17 @@ CacheControlHeader ParseCacheControlDirectives(
double max_age = directives[i].second.ToDouble(&ok); double max_age = directives[i].second.ToDouble(&ok);
if (ok) if (ok)
cache_control_header.max_age = max_age; cache_control_header.max_age = max_age;
} else if (DeprecatedEqualIgnoringCase(directives[i].first,
kStaleWhileRevalidateDirective)) {
if (!std::isnan(cache_control_header.stale_while_revalidate)) {
// First stale-while-revalidate directive wins if there are multiple
// ones.
continue;
}
bool ok;
double stale_while_revalidate = directives[i].second.ToDouble(&ok);
if (ok)
cache_control_header.stale_while_revalidate = stale_while_revalidate;
} }
} }
} }
......
...@@ -72,13 +72,15 @@ struct CacheControlHeader { ...@@ -72,13 +72,15 @@ struct CacheControlHeader {
bool contains_no_store : 1; bool contains_no_store : 1;
bool contains_must_revalidate : 1; bool contains_must_revalidate : 1;
double max_age; double max_age;
double stale_while_revalidate;
CacheControlHeader() CacheControlHeader()
: parsed(false), : parsed(false),
contains_no_cache(false), contains_no_cache(false),
contains_no_store(false), contains_no_store(false),
contains_must_revalidate(false), contains_must_revalidate(false),
max_age(0.0) {} max_age(0.0),
stale_while_revalidate(0.0) {}
}; };
using ServerTimingHeaderVector = Vector<std::unique_ptr<ServerTimingHeader>>; using ServerTimingHeaderVector = Vector<std::unique_ptr<ServerTimingHeader>>;
......
...@@ -22,6 +22,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -22,6 +22,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("no-cache no-store", AtomicString()); header = ParseCacheControlDirectives("no-cache no-store", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -29,6 +30,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -29,6 +30,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = header =
ParseCacheControlDirectives("no-store must-revalidate", AtomicString()); ParseCacheControlDirectives("no-store must-revalidate", AtomicString());
...@@ -37,6 +39,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -37,6 +39,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_TRUE(header.contains_no_store); EXPECT_TRUE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("max-age=0", AtomicString()); header = ParseCacheControlDirectives("max-age=0", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -44,6 +47,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -44,6 +47,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_EQ(0.0, header.max_age); EXPECT_EQ(0.0, header.max_age);
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("max-age", AtomicString()); header = ParseCacheControlDirectives("max-age", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -51,6 +55,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -51,6 +55,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("max-age=0 no-cache", AtomicString()); header = ParseCacheControlDirectives("max-age=0 no-cache", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -58,6 +63,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -58,6 +63,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_EQ(0.0, header.max_age); EXPECT_EQ(0.0, header.max_age);
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("no-cache=foo", AtomicString()); header = ParseCacheControlDirectives("no-cache=foo", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -65,6 +71,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -65,6 +71,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("nonsense", AtomicString()); header = ParseCacheControlDirectives("nonsense", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -72,6 +79,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -72,6 +79,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("\rno-cache\n\t\v\0\b", AtomicString()); header = ParseCacheControlDirectives("\rno-cache\n\t\v\0\b", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -79,6 +87,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -79,6 +87,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives(" no-cache ", AtomicString()); header = ParseCacheControlDirectives(" no-cache ", AtomicString());
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -86,6 +95,7 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -86,6 +95,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives(AtomicString(), "no-cache"); header = ParseCacheControlDirectives(AtomicString(), "no-cache");
EXPECT_TRUE(header.parsed); EXPECT_TRUE(header.parsed);
...@@ -93,6 +103,16 @@ TEST(HTTPParsersTest, ParseCacheControl) { ...@@ -93,6 +103,16 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store); EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate); EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age)); EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives(
"stale-while-revalidate=2,stale-while-revalidate=3", AtomicString());
EXPECT_TRUE(header.parsed);
EXPECT_FALSE(header.contains_no_cache);
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
EXPECT_EQ(2.0, header.stale_while_revalidate);
} }
TEST(HTTPParsersTest, CommaDelimitedHeaderSet) { TEST(HTTPParsersTest, CommaDelimitedHeaderSet) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment