summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorricea <ricea@chromium.org>2015-08-24 02:01:49 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-24 09:02:38 +0000
commit8bad09d9dd4d3de03c877a22c7c309454e219670 (patch)
treeae399b10032a5389910b0be88fe81bb4fb0a3735
parentf18c1bfd0e37fdab083225344e7590652a250275 (diff)
downloadchromium_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.h5
-rw-r--r--net/http/http_cache_transaction.cc9
-rw-r--r--net/http/http_cache_unittest.cc77
-rw-r--r--net/http/http_response_info.cc9
-rw-r--r--net/http/http_response_info.h5
-rw-r--r--net/http/http_response_info_unittest.cc24
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