diff options
author | jamartin <jamartin@chromium.org> | 2016-02-29 09:39:22 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-29 17:40:22 +0000 |
commit | 2edf0e7ce56f2126ed7a22392b61a25dcc62f3dd (patch) | |
tree | 510f9941935b3da280689dbe01f0f773286a0822 | |
parent | 722b61256e269c5cd4c136c13266ff15f00cedae (diff) | |
download | chromium_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.cc | 2 | ||||
-rw-r--r-- | components/precache/core/precache_fetcher_unittest.cc | 2 | ||||
-rw-r--r-- | net/http/http_response_headers.cc | 9 | ||||
-rw-r--r-- | net/http/http_response_headers.h | 5 | ||||
-rw-r--r-- | net/http/http_response_headers_unittest.cc | 34 | ||||
-rw-r--r-- | net/http/http_util.cc | 21 | ||||
-rw-r--r-- | net/http/http_util.h | 9 | ||||
-rw-r--r-- | net/http/http_util_unittest.cc | 59 |
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 |