summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjamartin <jamartin@chromium.org>2016-02-29 09:39:22 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-29 17:40:22 +0000
commit2edf0e7ce56f2126ed7a22392b61a25dcc62f3dd (patch)
tree510f9941935b3da280689dbe01f0f773286a0822
parent722b61256e269c5cd4c136c13266ff15f00cedae (diff)
downloadchromium_src-2edf0e7ce56f2126ed7a22392b61a25dcc62f3dd.zip
chromium_src-2edf0e7ce56f2126ed7a22392b61a25dcc62f3dd.tar.gz
chromium_src-2edf0e7ce56f2126ed7a22392b61a25dcc62f3dd.tar.bz2
Added HttpUtils::HasValidators and HttpResponse::HasValidators
Used in components/precache_fetcher.cc, part of the project "Wi-Fi Prefetch for Chrome Mobile" (see BUG), in order to increase the coverage of cacheable resources. Tested: $ ./build/gyp_chromium -D OS=linux && \ ninja -C out/Debug components_unittests net_unittests && \ out/Debug/components_unittests --gtest_filter=Precache* && \ out/Debug/net_unittests --gtest_filter=*.HasValidators* BUG=309216 Review URL: https://codereview.chromium.org/1481143002 Cr-Commit-Position: refs/heads/master@{#378226}
-rw-r--r--components/precache/core/precache_fetcher.cc2
-rw-r--r--components/precache/core/precache_fetcher_unittest.cc2
-rw-r--r--net/http/http_response_headers.cc9
-rw-r--r--net/http/http_response_headers.h5
-rw-r--r--net/http/http_response_headers_unittest.cc34
-rw-r--r--net/http/http_util.cc21
-rw-r--r--net/http/http_util.h9
-rw-r--r--net/http/http_util_unittest.cc59
8 files changed, 139 insertions, 2 deletions
diff --git a/components/precache/core/precache_fetcher.cc b/components/precache/core/precache_fetcher.cc
index 5aac067..fc52258a 100644
--- a/components/precache/core/precache_fetcher.cc
+++ b/components/precache/core/precache_fetcher.cc
@@ -191,7 +191,7 @@ void PrecacheFetcher::Fetcher::OnURLFetchComplete(const URLFetcher* source) {
if (fetch_stage_ == FetchStage::CACHE &&
(source->GetStatus().error() == net::ERR_CACHE_MISS ||
(source->GetResponseHeaders() &&
- source->GetResponseHeaders()->HasStrongValidators()))) {
+ source->GetResponseHeaders()->HasValidators()))) {
// If the resource was not found in the cache, request it from the
// network.
//
diff --git a/components/precache/core/precache_fetcher_unittest.cc b/components/precache/core/precache_fetcher_unittest.cc
index cf47a01..e0468cb 100644
--- a/components/precache/core/precache_fetcher_unittest.cc
+++ b/components/precache/core/precache_fetcher_unittest.cc
@@ -231,7 +231,7 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceNotInCache) {
EXPECT_EQ(true, callback_called_);
}
-TEST_F(PrecacheFetcherFetcherTest, ResourceHasStrongValidators) {
+TEST_F(PrecacheFetcherFetcherTest, ResourceHasValidators) {
GURL url(kGoodResourceURL);
net::FakeURLFetcher *fetcher1 = nullptr, *fetcher2 = nullptr;
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
index 2167aac..8f8ce9d 100644
--- a/net/http/http_response_headers.cc
+++ b/net/http/http_response_headers.cc
@@ -1248,6 +1248,15 @@ bool HttpResponseHeaders::HasStrongValidators() const {
date_header);
}
+bool HttpResponseHeaders::HasValidators() const {
+ std::string etag_header;
+ EnumerateHeader(NULL, "etag", &etag_header);
+ std::string last_modified_header;
+ EnumerateHeader(NULL, "Last-Modified", &last_modified_header);
+ return HttpUtil::HasValidators(GetHttpVersion(), etag_header,
+ last_modified_header);
+}
+
// From RFC 2616:
// Content-Length = "Content-Length" ":" 1*DIGIT
int64_t HttpResponseHeaders::GetContentLength() const {
diff --git a/net/http/http_response_headers.h b/net/http/http_response_headers.h
index 3ba7a8c..a3126aa 100644
--- a/net/http/http_response_headers.h
+++ b/net/http/http_response_headers.h
@@ -273,6 +273,11 @@ class NET_EXPORT HttpResponseHeaders
// See section 13.3.3 of RFC 2616.
bool HasStrongValidators() const;
+ // Returns true if this response has any validator (either a Last-Modified or
+ // an ETag) regardless of whether it is strong or weak. See section 13.3.3 of
+ // RFC 2616.
+ bool HasValidators() const;
+
// Extracts the value of the Content-Length header or returns -1 if there is
// no such header in the response.
int64_t GetContentLength() const;
diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc
index cb0d200..70a5d09 100644
--- a/net/http/http_response_headers_unittest.cc
+++ b/net/http/http_response_headers_unittest.cc
@@ -1634,6 +1634,40 @@ INSTANTIATE_TEST_CASE_P(HttpResponseHeaders,
HasStrongValidatorsTest,
testing::ValuesIn(strong_validators_tests));
+TEST(HttpResponseHeadersTest, HasValidatorsNone) {
+ std::string headers("HTTP/1.1 200 OK");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_FALSE(parsed->HasValidators());
+}
+
+TEST(HttpResponseHeadersTest, HasValidatorsEtag) {
+ std::string headers(
+ "HTTP/1.1 200 OK\n"
+ "etag: \"anything\"");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_TRUE(parsed->HasValidators());
+}
+
+TEST(HttpResponseHeadersTest, HasValidatorsLastModified) {
+ std::string headers(
+ "HTTP/1.1 200 OK\n"
+ "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_TRUE(parsed->HasValidators());
+}
+
+TEST(HttpResponseHeadersTest, HasValidatorsWeakEtag) {
+ std::string headers(
+ "HTTP/1.1 200 OK\n"
+ "etag: W/\"anything\"");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_TRUE(parsed->HasValidators());
+}
+
struct AddHeaderTestData {
const char* orig_headers;
const char* new_header;
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index 940ee80..932f838 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -738,6 +738,9 @@ bool HttpUtil::HasStrongValidators(HttpVersion version,
const std::string& etag_header,
const std::string& last_modified_header,
const std::string& date_header) {
+ if (!HasValidators(version, etag_header, last_modified_header))
+ return false;
+
if (version < HttpVersion(1, 1))
return false;
@@ -761,9 +764,27 @@ bool HttpUtil::HasStrongValidators(HttpVersion version,
if (!base::Time::FromString(date_header.c_str(), &date))
return false;
+ // Last-Modified is implicitly weak unless it is at least 60 seconds before
+ // the Date value.
return ((date - last_modified).InSeconds() >= 60);
}
+bool HttpUtil::HasValidators(HttpVersion version,
+ const std::string& etag_header,
+ const std::string& last_modified_header) {
+ if (version < HttpVersion(1, 0))
+ return false;
+
+ base::Time last_modified;
+ if (base::Time::FromString(last_modified_header.c_str(), &last_modified))
+ return true;
+
+ // It is OK to consider an empty string in etag_header to be a missing header
+ // since valid ETags are always quoted-strings (see RFC 2616 3.11) and thus
+ // empty ETags aren't empty strings (i.e., an empty ETag might be "\"\"").
+ return version >= HttpVersion(1, 1) && !etag_header.empty();
+}
+
// Functions for histogram initialization. The code 0 is put in the map to
// track status codes that are invalid.
// TODO(gavinp): Greatly prune the collected codes once we learn which
diff --git a/net/http/http_util.h b/net/http/http_util.h
index 7e71310..458a718 100644
--- a/net/http/http_util.h
+++ b/net/http/http_util.h
@@ -205,11 +205,20 @@ class NET_EXPORT HttpUtil {
// Returns true if the parameters describe a response with a strong etag or
// last-modified header. See section 13.3.3 of RFC 2616.
+ // An empty string should be passed for missing headers.
static bool HasStrongValidators(HttpVersion version,
const std::string& etag_header,
const std::string& last_modified_header,
const std::string& date_header);
+ // Returns true if this response has any validator (either a Last-Modified or
+ // an ETag) regardless of whether it is strong or weak. See section 13.3.3 of
+ // RFC 2616.
+ // An empty string should be passed for missing headers.
+ static bool HasValidators(HttpVersion version,
+ const std::string& etag_header,
+ const std::string& last_modified_header);
+
// Gets a vector of common HTTP status codes for histograms of status
// codes. Currently returns everything in the range [100, 600), plus 0
// (for invalid responses/status codes).
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc
index e83f6b9..2b45660 100644
--- a/net/http/http_util_unittest.cc
+++ b/net/http/http_util_unittest.cc
@@ -1200,4 +1200,63 @@ TEST(HttpUtilTest, IsValidHeaderValueRFC7230) {
EXPECT_TRUE(HttpUtil::IsValidHeaderValueRFC7230("q\x80q"));
}
+TEST(HttpUtilTest, HasValidators) {
+ const char* const kMissing = "";
+ const char* const kEtagEmpty = "\"\"";
+ const char* const kEtagStrong = "\"strong\"";
+ const char* const kEtagWeak = "W/\"weak\"";
+ const char* const kLastModified = "Tue, 15 Nov 1994 12:45:26 GMT";
+ const char* const kLastModifiedInvalid = "invalid";
+
+ const HttpVersion v0_9 = HttpVersion(0, 9);
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kMissing));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModified));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModified));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModified));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModified));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModifiedInvalid));
+ EXPECT_FALSE(
+ HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModifiedInvalid));
+
+ const HttpVersion v1_0 = HttpVersion(1, 0);
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagStrong, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kMissing));
+
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kMissing, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModified));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kLastModifiedInvalid));
+ EXPECT_FALSE(
+ HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModifiedInvalid));
+
+ const HttpVersion v1_1 = HttpVersion(1, 1);
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kMissing));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kMissing));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kMissing));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kMissing));
+
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kMissing, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModified));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kLastModifiedInvalid));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModifiedInvalid));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModifiedInvalid));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModifiedInvalid));
+}
+
} // namespace net