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

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: Rebase. 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..d1b85f62321e5e84e920a13636ffb58767f83385 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;
+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);
yhirano 2014/08/26 07:52:01 This parameter is not specified in net_log_event_t
Adam Rice 2014/08/26 13:38:42 Done.
+ return dict;
+}
+
} // namespace
namespace net {
@@ -2093,7 +2114,18 @@ 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) {
+ if (cache_ && cache_->use_stale_while_revalidate()) {
+ TriggerAsyncValidation();
+ skip_validation = true;
+ } else {
+ skip_validation = false;
yhirano 2014/08/26 07:52:01 We don't need this statement: skip_validation is a
Adam Rice 2014/08/26 13:38:42 Oh good, that makes the code cleaner.
+ }
+ }
if (request_->method == "HEAD" &&
(truncated_ || response_.headers->response_code() == 206)) {
@@ -2123,6 +2155,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 +2295,47 @@ int HttpCache::Transaction::RestartNetworkRequestWithAuth(
return rv;
}
-bool HttpCache::Transaction::RequiresValidation() {
+ValidationType HttpCache::Transaction::RequiresValidation() {
yhirano 2014/08/26 07:52:01 This function should be renamed because its return
Adam Rice 2014/08/26 13:38:42 Done.
// 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(
+ 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_))
+ return VALIDATION_SYNCHRONOUS;
}
- return false;
+ return validation_required_by_headers;
}
bool HttpCache::Transaction::ConditionalizeRequest() {
@@ -2341,11 +2384,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,
+ &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 +2568,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_,
+ *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