Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(316)

Unified Diff: net/http/http_cache_transaction.cc

Issue 455623003: stale-while-revalidate experimental implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add load flag LOAD_ASYNC_REVALIDATION. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/http/http_cache_transaction.cc
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 286a526a3edb2fa39e7101e10429cf3c15b7920a..4a4bda51dbd92261f8858e5e4ec2a112543ad023 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -17,6 +17,7 @@
#include "base/compiler_specific.h"
#include "base/format_macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
@@ -26,6 +27,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
+#include "base/values.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
@@ -51,6 +53,8 @@ using base::TimeTicks;
namespace {
+typedef net::HttpResponseHeaders::ValidationType ValidationType;
+
// TODO(ricea): Move this to HttpResponseHeaders once it is standardised.
static const char kFreshnessHeader[] = "Resource-Freshness";
@@ -238,6 +242,18 @@ void RecordNoStoreHeaderHistogram(int load_flags,
}
}
+base::Value* NetLogAsyncRevalidationInfoCallback(
+ const net::NetLog::Source& source,
+ const net::HttpRequestInfo* request,
+ net::NetLog::LogLevel log_level) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+ source.AddToEventParameters(dict);
+
+ dict->SetString("url", request->url.possibly_invalid_spec());
+ dict->SetString("method", request->method);
+ return dict;
+}
+
} // namespace
namespace net {
@@ -2093,7 +2109,16 @@ int HttpCache::Transaction::BeginCacheRead() {
int HttpCache::Transaction::BeginCacheValidation() {
DCHECK(mode_ == READ_WRITE);
- bool skip_validation = !RequiresValidation();
+ ValidationType required_validation = RequiresValidation();
+
+ bool skip_validation = required_validation == ValidationType::VALIDATION_NONE;
rvargas (doing something else) 2014/09/05 22:52:39 nit: use () around ==
Adam Rice 2014/09/09 12:36:45 Done.
+
+ if (required_validation == ValidationType::VALIDATION_ASYNCHRONOUS &&
+ !(request_->method == "GET" && (truncated_ || partial_)) && cache_ &&
+ cache_->use_stale_while_revalidate()) {
+ TriggerAsyncValidation();
+ skip_validation = true;
+ }
if (request_->method == "HEAD" &&
(truncated_ || response_.headers->response_code() == 206)) {
@@ -2123,6 +2148,7 @@ int HttpCache::Transaction::BeginCacheValidation() {
}
if (skip_validation) {
+ // TODO(ricea): Is this pattern okay for asynchronous revalidations?
UpdateTransactionPattern(PATTERN_ENTRY_USED);
RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE);
return SetupEntryForRead();
@@ -2262,37 +2288,43 @@ int HttpCache::Transaction::RestartNetworkRequestWithAuth(
return rv;
}
-bool HttpCache::Transaction::RequiresValidation() {
+ValidationType HttpCache::Transaction::RequiresValidation() {
// TODO(darin): need to do more work here:
// - make sure we have a matching request method
// - watch out for cached responses that depend on authentication
// In playback mode, nothing requires validation.
if (cache_->mode() == net::HttpCache::PLAYBACK)
- return false;
+ return ValidationType::VALIDATION_NONE;
if (response_.vary_data.is_valid() &&
!response_.vary_data.MatchesRequest(*request_,
*response_.headers.get())) {
vary_mismatch_ = true;
- return true;
+ return ValidationType::VALIDATION_SYNCHRONOUS;
}
if (effective_load_flags_ & LOAD_PREFERRING_CACHE)
- return false;
+ return ValidationType::VALIDATION_NONE;
rvargas (doing something else) 2014/09/05 22:52:40 I think we should move the enum out of ResponseHea
Adam Rice 2014/09/09 12:36:45 Done.
- if (effective_load_flags_ & LOAD_VALIDATE_CACHE)
- return true;
+ if (effective_load_flags_ & (LOAD_VALIDATE_CACHE | LOAD_ASYNC_REVALIDATION))
rvargas (doing something else) 2014/09/05 22:52:39 I just realized, can't we use LOAD_VALIDATE_CACHE
Adam Rice 2014/09/09 12:36:45 I tried that. It does add headers. See http_networ
+ return ValidationType::VALIDATION_SYNCHRONOUS;
if (request_->method == "PUT" || request_->method == "DELETE")
- return true;
+ return ValidationType::VALIDATION_SYNCHRONOUS;
- if (response_.headers->RequiresValidation(
- response_.request_time, response_.response_time, Time::Now())) {
- return true;
+ ValidationType validation_required_by_headers =
+ response_.headers->RequiresValidation(
+ response_.request_time, response_.response_time, Time::Now());
+
+ if (validation_required_by_headers ==
+ ValidationType::VALIDATION_ASYNCHRONOUS) {
+ // Asynchronous revalidation is only supported for GET and HEAD methods.
+ if (request_->method != "GET" && request_->method != "HEAD")
+ return ValidationType::VALIDATION_SYNCHRONOUS;
}
- return false;
+ return validation_required_by_headers;
}
bool HttpCache::Transaction::ConditionalizeRequest() {
@@ -2344,7 +2376,7 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
if (response_.headers->GetStaleWhileRevalidateValue(
&stale_while_revalidate) &&
stale_while_revalidate > TimeDelta()) {
- TimeDelta max_age =
+ HttpResponseHeaders::Freshness freshness =
response_.headers->GetFreshnessLifetime(response_.response_time);
TimeDelta current_age = response_.headers->GetCurrentAge(
response_.request_time, response_.response_time, Time::Now());
@@ -2353,7 +2385,7 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
kFreshnessHeader,
base::StringPrintf("max-age=%" PRId64
",stale-while-revalidate=%" PRId64 ",age=%" PRId64,
- max_age.InSeconds(),
+ freshness.lifetime.InSeconds(),
stale_while_revalidate.InSeconds(),
current_age.InSeconds()));
}
@@ -2523,6 +2555,26 @@ void HttpCache::Transaction::FixHeadersForHead() {
}
}
+void HttpCache::Transaction::TriggerAsyncValidation() {
+ DCHECK(!request_->upload_data_stream);
+ BoundNetLog async_revalidation_net_log(
+ BoundNetLog::Make(net_log_.net_log(), NetLog::SOURCE_ASYNC_REVALIDATION));
+ net_log_.AddEvent(
+ NetLog::TYPE_HTTP_CACHE_VALIDATE_RESOURCE_ASYNC,
+ async_revalidation_net_log.source().ToEventParametersCallback());
+ async_revalidation_net_log.BeginEvent(
+ NetLog::TYPE_ASYNC_REVALIDATION,
+ base::Bind(
+ &NetLogAsyncRevalidationInfoCallback, net_log_.source(), request_));
+ // cache_ is a weak pointer.
rvargas (doing something else) 2014/09/05 22:52:40 nit: move comment inline with the argument
Adam Rice 2014/09/09 12:36:45 Done.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&HttpCache::PerformAsyncValidation,
+ cache_,
+ *request_,
+ async_revalidation_net_log));
+}
+
void HttpCache::Transaction::FailRangeRequest() {
response_ = *new_response_;
partial_->FixResponseHeaders(response_.headers.get(), false);

Powered by Google App Engine
This is Rietveld 408576698