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

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: Stop setting Cache-Control: max-age=0 on async revalidations. Created 6 years, 4 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..503587cb566131a5f6f3e73c48b1274c26e000d7 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,13 @@ using base::TimeTicks;
namespace {
+typedef net::HttpResponseHeaders::ValidationType ValidationType;
+const ValidationType VALIDATION_NONE = ValidationType::VALIDATION_NONE;
rvargas (doing something else) 2014/08/29 23:36:07 I think we should just live with HttpResponseHeade
Adam Rice 2014/09/01 14:43:00 Done.
+const ValidationType VALIDATION_SYNCHRONOUS =
+ ValidationType::VALIDATION_SYNCHRONOUS;
+const ValidationType VALIDATION_ASYNCHRONOUS =
+ ValidationType::VALIDATION_ASYNCHRONOUS;
+
// TODO(ricea): Move this to HttpResponseHeaders once it is standardised.
static const char kFreshnessHeader[] = "Resource-Freshness";
@@ -238,6 +247,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 {
@@ -412,6 +433,11 @@ const BoundNetLog& HttpCache::Transaction::net_log() const {
return net_log_;
}
+void HttpCache::Transaction::ValidateInternalCache() {
+ DCHECK(!request_); // Start() should not have been called.
+ effective_load_flags_ |= LOAD_VALIDATE_CACHE;
+}
+
int HttpCache::Transaction::Start(const HttpRequestInfo* request,
const CompletionCallback& callback,
const BoundNetLog& net_log) {
@@ -1938,7 +1964,9 @@ void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log,
const HttpRequestInfo* request) {
net_log_ = net_log;
request_ = request;
- effective_load_flags_ = request_->load_flags;
+ // effective_load_flags_ may already have had LOAD_VALIDATE_CACHE set by the
+ // ValidateInternalCache() method.
+ effective_load_flags_ |= request_->load_flags;
switch (cache_->mode()) {
case NORMAL:
@@ -2093,7 +2121,15 @@ int HttpCache::Transaction::BeginCacheRead() {
int HttpCache::Transaction::BeginCacheValidation() {
DCHECK(mode_ == READ_WRITE);
- bool skip_validation = !RequiresValidation();
+ ValidationType required_validation = RequiredValidationType();
+
+ bool skip_validation = required_validation == VALIDATION_NONE;
+
+ if (required_validation == VALIDATION_ASYNCHRONOUS && cache_ &&
+ cache_->use_stale_while_revalidate()) {
+ TriggerAsyncValidation();
+ skip_validation = true;
+ }
if (request_->method == "HEAD" &&
(truncated_ || response_.headers->response_code() == 206)) {
@@ -2123,6 +2159,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 +2299,47 @@ int HttpCache::Transaction::RestartNetworkRequestWithAuth(
return rv;
}
-bool HttpCache::Transaction::RequiresValidation() {
+ValidationType HttpCache::Transaction::RequiredValidationType() {
// 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 VALIDATION_NONE;
if (response_.vary_data.is_valid() &&
!response_.vary_data.MatchesRequest(*request_,
*response_.headers.get())) {
vary_mismatch_ = true;
- return true;
+ return VALIDATION_SYNCHRONOUS;
}
if (effective_load_flags_ & LOAD_PREFERRING_CACHE)
- return false;
+ return VALIDATION_NONE;
if (effective_load_flags_ & LOAD_VALIDATE_CACHE)
- return true;
+ return VALIDATION_SYNCHRONOUS;
if (request_->method == "PUT" || request_->method == "DELETE")
- return true;
+ return VALIDATION_SYNCHRONOUS;
- if (response_.headers->RequiresValidation(
- response_.request_time, response_.response_time, Time::Now())) {
- return true;
+ ValidationType validation_required_by_headers =
+ response_.headers->RequiresValidation(
rvargas (doing something else) 2014/08/29 23:36:06 If you keep the name for ResponseHeaders::Requires
Adam Rice 2014/09/01 14:43:00 Done.
+ response_.request_time, response_.response_time, Time::Now());
+
+ if (validation_required_by_headers == VALIDATION_ASYNCHRONOUS) {
+ // Asynchronous revalidation is only supported for GET and HEAD methods.
+ if (request_->method != "GET" && request_->method != "HEAD")
+ return VALIDATION_SYNCHRONOUS;
+
+ // Asynchronous revalidation of GETs can only be used for completely cached
+ // resources.
+ if (request_->method == "GET" && (truncated_ || partial_))
rvargas (doing something else) 2014/08/29 23:36:06 This part belong on the caller side.
Adam Rice 2014/09/01 14:43:00 Done.
+ return VALIDATION_SYNCHRONOUS;
}
- return false;
+ return validation_required_by_headers;
}
bool HttpCache::Transaction::ConditionalizeRequest() {
@@ -2341,11 +2388,13 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
// stale-while-revalidate is not useful when we only have a partial response
// cached, so don't set the header in that case.
TimeDelta stale_while_revalidate;
+ TimeDelta max_age;
if (response_.headers->GetStaleWhileRevalidateValue(
&stale_while_revalidate) &&
+ response_.headers->GetFreshnessLifetime(response_.response_time,
rvargas (doing something else) 2014/08/29 23:36:07 This pattern reads very weird: returning a value t
Adam Rice 2014/09/01 14:43:00 I have attempted to improve it. PTAL.
+ &max_age) !=
+ HttpResponseHeaders::NEVER_FRESH &&
stale_while_revalidate > TimeDelta()) {
- TimeDelta max_age =
- response_.headers->GetFreshnessLifetime(response_.response_time);
TimeDelta current_age = response_.headers->GetCurrentAge(
response_.request_time, response_.response_time, Time::Now());
@@ -2523,6 +2572,25 @@ 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_));
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&HttpCache::PerformAsyncValidation,
+ cache_,
rvargas (doing something else) 2014/08/29 23:36:06 Is the intention here to use a weak pointer? (I be
Adam Rice 2014/09/01 14:43:00 Yes. I have added a comment.
+ *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