diff options
author | ricea <ricea@chromium.org> | 2015-08-24 02:01:49 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-24 09:02:38 +0000 |
commit | 8bad09d9dd4d3de03c877a22c7c309454e219670 (patch) | |
tree | ae399b10032a5389910b0be88fe81bb4fb0a3735 | |
parent | f18c1bfd0e37fdab083225344e7590652a250275 (diff) | |
download | chromium_src-8bad09d9dd4d3de03c877a22c7c309454e219670.zip chromium_src-8bad09d9dd4d3de03c877a22c7c309454e219670.tar.gz chromium_src-8bad09d9dd4d3de03c877a22c7c309454e219670.tar.bz2 |
//net changes for stale-while-revalidate
Add load flag LOAD_SUPPORT_ASYNC_REVALIDATION, HttpResponseInfo flag
async_revalidation_required and logic to HttpCache::Transaction to use
them.
See the design doc at
https://docs.google.com/a/chromium.org/document/d/1nBhr25nSJgoyAh4S1-U5h2sH70Iz4RR0NAfXNL79G5Y/edit
BUG=348877
TEST=net_unittests
Review URL: https://codereview.chromium.org/1039263002
Cr-Commit-Position: refs/heads/master@{#345037}
-rw-r--r-- | net/base/load_flags_list.h | 5 | ||||
-rw-r--r-- | net/http/http_cache_transaction.cc | 9 | ||||
-rw-r--r-- | net/http/http_cache_unittest.cc | 77 | ||||
-rw-r--r-- | net/http/http_response_info.cc | 9 | ||||
-rw-r--r-- | net/http/http_response_info.h | 5 | ||||
-rw-r--r-- | net/http/http_response_info_unittest.cc | 24 |
6 files changed, 124 insertions, 5 deletions
diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h index 0db44e3..d0f4f0f 100644 --- a/net/base/load_flags_list.h +++ b/net/base/load_flags_list.h @@ -81,3 +81,8 @@ LOAD_FLAG(MAYBE_USER_GESTURE, 1 << 16) // Indicates that the username:password portion of the URL should not // be honored, but that other forms of authority may be used. LOAD_FLAG(DO_NOT_USE_EMBEDDED_IDENTITY, 1 << 17) + +// The creator of this URLRequest wishes to receive stale responses when allowed +// by the "Cache-Control: stale-while-revalidate" directive and is able to issue +// an async revalidation to update the cache. +LOAD_FLAG(SUPPORT_ASYNC_REVALIDATION, 1 << 18) diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index d5cb94d..85ad67e 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc @@ -2115,6 +2115,13 @@ int HttpCache::Transaction::BeginCacheValidation() { bool skip_validation = (required_validation == VALIDATION_NONE); + if ((effective_load_flags_ & LOAD_SUPPORT_ASYNC_REVALIDATION) && + required_validation == VALIDATION_ASYNCHRONOUS) { + DCHECK_EQ(request_->method, "GET"); + skip_validation = true; + response_.async_revalidation_required = true; + } + if (request_->method == "HEAD" && (truncated_ || response_.headers->response_code() == 206)) { DCHECK(!partial_); @@ -2242,7 +2249,7 @@ int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { EXTERNALLY_CONDITIONALIZED_CACHE_USABLE; if (mode_ == NONE) type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS; - else if (RequiresValidation()) + else if (RequiresValidation() != VALIDATION_NONE) type = EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION; // TODO(ricea): Add CACHE_USABLE_STALE once stale-while-revalidate CL landed. diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 8d62ee0..779af46 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -7377,6 +7377,83 @@ TEST(HttpCache, ResourceFreshnessHeaderNotSent) { EXPECT_EQ(2, cache.network_layer()->transaction_count()); } +TEST(HttpCache, StaleContentNotUsedWhenLoadFlagNotSet) { + MockHttpCache cache; + + ScopedMockTransaction stale_while_revalidate_transaction( + kSimpleGET_Transaction); + + stale_while_revalidate_transaction.response_headers = + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" + "Age: 10801\n" + "Cache-Control: max-age=0,stale-while-revalidate=86400\n"; + + // Write to the cache. + RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + + // Send the request again and check that it is sent to the network again. + HttpResponseInfo response_info; + RunTransactionTestWithResponseInfo( + cache.http_cache(), stale_while_revalidate_transaction, &response_info); + + EXPECT_EQ(2, cache.network_layer()->transaction_count()); + EXPECT_FALSE(response_info.async_revalidation_required); +} + +TEST(HttpCache, StaleContentUsedWhenLoadFlagSetAndUsable) { + MockHttpCache cache; + + ScopedMockTransaction stale_while_revalidate_transaction( + kSimpleGET_Transaction); + stale_while_revalidate_transaction.load_flags |= + LOAD_SUPPORT_ASYNC_REVALIDATION; + stale_while_revalidate_transaction.response_headers = + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" + "Age: 10801\n" + "Cache-Control: max-age=0,stale-while-revalidate=86400\n"; + + // Write to the cache. + RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + + // Send the request again and check that it is not sent to the network again. + HttpResponseInfo response_info; + RunTransactionTestWithResponseInfo( + cache.http_cache(), stale_while_revalidate_transaction, &response_info); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + EXPECT_TRUE(response_info.async_revalidation_required); +} + +TEST(HttpCache, StaleContentNotUsedWhenUnusable) { + MockHttpCache cache; + + ScopedMockTransaction stale_while_revalidate_transaction( + kSimpleGET_Transaction); + stale_while_revalidate_transaction.load_flags |= + LOAD_SUPPORT_ASYNC_REVALIDATION; + stale_while_revalidate_transaction.response_headers = + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" + "Age: 10801\n" + "Cache-Control: max-age=0,stale-while-revalidate=1800\n"; + + // Write to the cache. + RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + + // Send the request again and check that it is sent to the network again. + HttpResponseInfo response_info; + RunTransactionTestWithResponseInfo( + cache.http_cache(), stale_while_revalidate_transaction, &response_info); + + EXPECT_EQ(2, cache.network_layer()->transaction_count()); + EXPECT_FALSE(response_info.async_revalidation_required); +} + // Tests that we allow multiple simultaneous, non-overlapping transactions to // take place on a sparse entry. TEST(HttpCache, RangeGET_MultipleRequests) { diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index dbfb62e..c6be3e6 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc @@ -106,8 +106,8 @@ HttpResponseInfo::HttpResponseInfo() was_fetched_via_proxy(false), did_use_http_auth(false), unused_since_prefetch(false), - connection_info(CONNECTION_INFO_UNKNOWN) { -} + async_revalidation_required(false), + connection_info(CONNECTION_INFO_UNKNOWN) {} HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) : was_cached(rhs.was_cached), @@ -119,6 +119,7 @@ HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) proxy_server(rhs.proxy_server), did_use_http_auth(rhs.did_use_http_auth), unused_since_prefetch(rhs.unused_since_prefetch), + async_revalidation_required(rhs.async_revalidation_required), socket_address(rhs.socket_address), npn_negotiated_protocol(rhs.npn_negotiated_protocol), connection_info(rhs.connection_info), @@ -129,8 +130,7 @@ HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) ssl_info(rhs.ssl_info), headers(rhs.headers), vary_data(rhs.vary_data), - metadata(rhs.metadata) { -} + metadata(rhs.metadata) {} HttpResponseInfo::~HttpResponseInfo() { } @@ -145,6 +145,7 @@ HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) { was_fetched_via_proxy = rhs.was_fetched_via_proxy; did_use_http_auth = rhs.did_use_http_auth; unused_since_prefetch = rhs.unused_since_prefetch; + async_revalidation_required = rhs.async_revalidation_required; socket_address = rhs.socket_address; npn_negotiated_protocol = rhs.npn_negotiated_protocol; connection_info = rhs.connection_info; diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h index 1ce64f8..dd1b3da 100644 --- a/net/http/http_response_info.h +++ b/net/http/http_response_info.h @@ -106,6 +106,11 @@ class NET_EXPORT HttpResponseInfo { // used since. bool unused_since_prefetch; + // True if this resource is stale and requires async revalidation. + // This value is not persisted by Persist(); it is only ever set when the + // response is retrieved from the cache. + bool async_revalidation_required; + // Remote address of the socket which fetched this resource. // // NOTE: If the response was served from the cache (was_cached is true), diff --git a/net/http/http_response_info_unittest.cc b/net/http/http_response_info_unittest.cc index ef7d411..d27fb1c 100644 --- a/net/http/http_response_info_unittest.cc +++ b/net/http/http_response_info_unittest.cc @@ -52,6 +52,30 @@ TEST_F(HttpResponseInfoTest, UnusedSincePrefetchPersistTrue) { EXPECT_TRUE(restored_response_info.unused_since_prefetch); } +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredDefault) { + EXPECT_FALSE(response_info_.async_revalidation_required); +} + +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredCopy) { + response_info_.async_revalidation_required = true; + net::HttpResponseInfo response_info_clone(response_info_); + EXPECT_TRUE(response_info_clone.async_revalidation_required); +} + +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredAssign) { + response_info_.async_revalidation_required = true; + net::HttpResponseInfo response_info_clone; + response_info_clone = response_info_; + EXPECT_TRUE(response_info_clone.async_revalidation_required); +} + +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredNotPersisted) { + response_info_.async_revalidation_required = true; + net::HttpResponseInfo restored_response_info; + PickleAndRestore(response_info_, &restored_response_info); + EXPECT_FALSE(restored_response_info.async_revalidation_required); +} + } // namespace } // namespace net |