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

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: Compile fix for ResourcePrefreshPredictor. Created 6 years, 2 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 b06e8f3a272b4df533756a423f5a5fc0b321b532..5e901316f486f39bfa2fed42db3ccf33ae5192c6 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"
@@ -238,6 +240,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;
+}
+
enum ExternallyConditionalizedType {
EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION,
EXTERNALLY_CONDITIONALIZED_CACHE_USABLE,
@@ -2110,7 +2124,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 == VALIDATION_NONE);
+
+ if (required_validation == 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)) {
@@ -2140,6 +2163,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();
@@ -2295,37 +2319,42 @@ 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 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;
+ if (effective_load_flags_ & (LOAD_VALIDATE_CACHE | LOAD_ASYNC_REVALIDATION))
+ 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(
+ 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;
}
- return false;
+ return validation_required_by_headers;
}
bool HttpCache::Transaction::ConditionalizeRequest() {
@@ -2374,12 +2403,9 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
if (!use_if_range) {
// 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;
- if (response_.headers->GetStaleWhileRevalidateValue(
- &stale_while_revalidate) &&
- stale_while_revalidate > TimeDelta()) {
- TimeDelta max_age =
- response_.headers->GetFreshnessLifetime(response_.response_time);
+ HttpResponseHeaders::FreshnessLifetimes lifetime =
+ response_.headers->GetFreshnessLifetimes(response_.response_time);
+ if (lifetime.stale > TimeDelta()) {
TimeDelta current_age = response_.headers->GetCurrentAge(
response_.request_time, response_.response_time, Time::Now());
@@ -2387,8 +2413,8 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
kFreshnessHeader,
base::StringPrintf("max-age=%" PRId64
",stale-while-revalidate=%" PRId64 ",age=%" PRId64,
- max_age.InSeconds(),
- stale_while_revalidate.InSeconds(),
+ lifetime.fresh.InSeconds(),
+ lifetime.stale.InSeconds(),
current_age.InSeconds()));
}
}
@@ -2557,6 +2583,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_, // cache_ is a weak pointer.
+ *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