Chromium Code Reviews| Index: net/http/http_cache_transaction.cc |
| diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc |
| index 50e9da10ea8da4c3747b3e33011a6949aee72dca..530561ac3c78605cb683c7d6c2f5308c3590f807 100644 |
| --- a/net/http/http_cache_transaction.cc |
| +++ b/net/http/http_cache_transaction.cc |
| @@ -27,6 +27,7 @@ |
| #include "base/strings/string_piece.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| +#include "base/time/clock.h" |
| #include "base/time/time.h" |
| #include "base/values.h" |
| #include "net/base/completion_callback.h" |
| @@ -756,8 +757,8 @@ int HttpCache::Transaction::HandleResult(int rv) { |
| // 2. Cached entry, no validation: |
| // Start(): |
| // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* |
| -// -> BeginPartialCacheValidation() -> BeginCacheValidation() -> |
| -// SetupEntryForRead() |
| +// -> CacheDispatchValidation -> BeginPartialCacheValidation() -> |
| +// BeginCacheValidation() -> SetupEntryForRead() |
| // |
| // Read(): |
| // CacheReadData* |
| @@ -765,10 +766,10 @@ int HttpCache::Transaction::HandleResult(int rv) { |
| // 3. Cached entry, validation (304): |
| // Start(): |
| // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* |
| -// -> BeginPartialCacheValidation() -> BeginCacheValidation() -> |
| -// SendRequest* -> SuccessfulSendRequest -> UpdateCachedResponse -> |
| -// CacheWriteResponse* -> UpdateCachedResponseComplete -> |
| -// OverwriteCachedResponse -> PartialHeadersReceived |
| +// -> CacheDispatchValidation -> BeginPartialCacheValidation() -> |
| +// BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> |
| +// UpdateCachedResponse -> CacheWriteResponse* -> UpdateCachedResponseComplete |
| +// -> OverwriteCachedResponse -> PartialHeadersReceived |
| // |
| // Read(): |
| // CacheReadData* |
| @@ -776,10 +777,10 @@ int HttpCache::Transaction::HandleResult(int rv) { |
| // 4. Cached entry, validation and replace (200): |
| // Start(): |
| // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* |
| -// -> BeginPartialCacheValidation() -> BeginCacheValidation() -> |
| -// SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse -> |
| -// CacheWriteResponse* -> DoTruncateCachedData* -> TruncateCachedMetadata* -> |
| -// PartialHeadersReceived |
| +// -> CacheDispatchValidation -> BeginPartialCacheValidation() -> |
| +// BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> |
| +// OverwriteCachedResponse -> CacheWriteResponse* -> DoTruncateCachedData* -> |
| +// TruncateCachedMetadata* -> PartialHeadersReceived |
| // |
| // Read(): |
| // NetworkRead* -> CacheWriteData* |
| @@ -787,12 +788,12 @@ int HttpCache::Transaction::HandleResult(int rv) { |
| // 5. Sparse entry, partially cached, byte range request: |
| // Start(): |
| // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* |
| -// -> BeginPartialCacheValidation() -> CacheQueryData* -> |
| -// ValidateEntryHeadersAndContinue() -> StartPartialCacheValidation -> |
| -// CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* -> |
| -// SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteResponse* -> |
| -// UpdateCachedResponseComplete -> OverwriteCachedResponse -> |
| -// PartialHeadersReceived |
| +// -> CacheDispatchValidation -> BeginPartialCacheValidation() -> |
| +// CacheQueryData* -> ValidateEntryHeadersAndContinue() -> |
| +// StartPartialCacheValidation -> CompletePartialCacheValidation -> |
| +// BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> |
| +// UpdateCachedResponse -> CacheWriteResponse* -> UpdateCachedResponseComplete |
| +// -> OverwriteCachedResponse -> PartialHeadersReceived |
| // |
| // Read() 1: |
| // NetworkRead* -> CacheWriteData* |
| @@ -831,8 +832,9 @@ int HttpCache::Transaction::HandleResult(int rv) { |
| // itself. |
| // Start(): |
| // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* |
| -// -> BeginPartialCacheValidation() -> BeginCacheValidation() -> |
| -// SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse |
| +// -> CacheDispatchValidation -> BeginPartialCacheValidation() -> |
| +// BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> |
| +// OverwriteCachedResponse |
| // |
| // 10. HEAD. Sparse entry, partially cached: |
| // Serve the request from the cache, as long as it doesn't require |
| @@ -843,6 +845,19 @@ int HttpCache::Transaction::HandleResult(int rv) { |
| // Start(): Basically the same as example 7, as we never create a partial_ |
| // object for this request. |
| // |
| +// 11. Prefetch, not-cached entry: |
| +// The same as example 1. The "unused_since_prefetch" bit is stored as true in |
| +// UpdateCachedResponse. |
| +// |
| +// 12. Prefetch, cached entry: |
| +// Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between |
| +// CacheReadResponse* and CacheDispatchValidation if the unused_since_prefetch |
| +// bit is unset. |
| +// |
| +// 13. Cached entry, unused_since_prefetch is true: |
| +// Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between |
|
rvargas (doing something else)
2015/01/09 20:16:13
mind making this explicit? Assuming the entry is u
jkarlin
2015/01/12 13:01:14
Done.
|
| +// CacheReadResponse* and CacheDispatchValidation and a validation request is |
| +// not sent if the entry is less than 5 minutes old. |
| int HttpCache::Transaction::DoLoop(int result) { |
| DCHECK(next_state_ != STATE_NONE); |
| @@ -951,6 +966,17 @@ int HttpCache::Transaction::DoLoop(int result) { |
| case STATE_CACHE_READ_RESPONSE_COMPLETE: |
| rv = DoCacheReadResponseComplete(rv); |
| break; |
| + case STATE_CACHE_DISPATCH_VALIDATION: |
| + DCHECK_EQ(OK, rv); |
| + rv = DoCacheDispatchValidation(); |
| + break; |
| + case STATE_TOGGLE_UNUSED_SINCE_PREFETCH: |
| + DCHECK_EQ(OK, rv); |
| + rv = DoCacheToggleUnusedSincePrefetch(); |
| + break; |
| + case STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE: |
| + rv = DoCacheToggleUnusedSincePrefetchComplete(rv); |
| + break; |
| case STATE_CACHE_WRITE_RESPONSE: |
| DCHECK_EQ(OK, rv); |
| rv = DoCacheWriteResponse(); |
| @@ -1630,6 +1656,7 @@ int HttpCache::Transaction::DoUpdateCachedResponse() { |
| response_.response_time = new_response_->response_time; |
| response_.request_time = new_response_->request_time; |
| response_.network_accessed = new_response_->network_accessed; |
| + response_.unused_since_prefetch = new_response_->unused_since_prefetch; |
| if (response_.headers->HasHeaderValue("cache-control", "no-store")) { |
| if (!entry_->doomed) { |
| @@ -1848,6 +1875,42 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { |
| if (response_.headers->GetContentLength() == current_size) |
| truncated_ = false; |
| + if ((response_.unused_since_prefetch && |
| + !(request_->load_flags & LOAD_PREFETCH)) || |
| + (!response_.unused_since_prefetch && |
| + (request_->load_flags & LOAD_PREFETCH))) { |
| + // Either this is the first use of an entry since it was prefetched or |
| + // this is a prefetch. The value of response.unused_since_prefetch is valid |
| + // for this transaction but the bit needs to be flipped in storage. |
| + next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH; |
| + return OK; |
| + } |
| + |
| + next_state_ = STATE_CACHE_DISPATCH_VALIDATION; |
| + return OK; |
| +} |
| + |
| +int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch() { |
| + // Write back the toggled value for the next use of this entry. |
| + response_.unused_since_prefetch = !response_.unused_since_prefetch; |
| + |
| + // TODO(jkarlin): If DoUpdateCachedResponse is also called for this |
| + // transaction then metadata will be written to cache twice. If prefetching |
| + // becomes more common, consider combining the writes. |
| + target_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE; |
| + next_state_ = STATE_CACHE_WRITE_RESPONSE; |
| + return OK; |
| +} |
| + |
| +int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete( |
| + int result) { |
| + // Restore the original value for this transaction. |
| + response_.unused_since_prefetch = !response_.unused_since_prefetch; |
| + next_state_ = STATE_CACHE_DISPATCH_VALIDATION; |
| + return OK; |
| +} |
| + |
| +int HttpCache::Transaction::DoCacheDispatchValidation() { |
|
rvargas (doing something else)
2015/01/09 20:16:13
Time to make sure that method definition follows t
jkarlin
2015/01/12 13:01:14
Done. Thanks!
|
| // We now have access to the cache entry. |
| // |
| // o if we are a reader for the transaction, then we can start reading the |
| @@ -1861,6 +1924,7 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { |
| // conditionalized request (if-modified-since / if-none-match). We check |
| // if the request headers define a validation request. |
| // |
| + int result = ERR_FAILED; |
| switch (mode_) { |
| case READ: |
| UpdateTransactionPattern(PATTERN_ENTRY_USED); |
| @@ -1875,7 +1939,6 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { |
| case WRITE: |
| default: |
| NOTREACHED(); |
| - result = ERR_FAILED; |
| } |
| return result; |
| } |
| @@ -2545,6 +2608,16 @@ ValidationType HttpCache::Transaction::RequiresValidation() { |
| if (effective_load_flags_ & LOAD_PREFERRING_CACHE) |
| return VALIDATION_NONE; |
| + if (response_.unused_since_prefetch && |
| + !(effective_load_flags_ & LOAD_PREFETCH) && |
| + response_.headers->GetCurrentAge( |
| + response_.request_time, response_.response_time, |
| + cache_->clock_->Now()) < TimeDelta::FromMinutes(kPrefetchReuseMins)) { |
| + // The first use of a resource after prefetch within a short window skips |
| + // validation. |
| + return VALIDATION_NONE; |
| + } |
| + |
| if (effective_load_flags_ & (LOAD_VALIDATE_CACHE | LOAD_ASYNC_REVALIDATION)) |
| return VALIDATION_SYNCHRONOUS; |
| @@ -2552,8 +2625,9 @@ ValidationType HttpCache::Transaction::RequiresValidation() { |
| return VALIDATION_SYNCHRONOUS; |
| ValidationType validation_required_by_headers = |
| - response_.headers->RequiresValidation( |
| - response_.request_time, response_.response_time, Time::Now()); |
| + response_.headers->RequiresValidation(response_.request_time, |
| + response_.response_time, |
| + cache_->clock_->Now()); |
| if (validation_required_by_headers == VALIDATION_ASYNCHRONOUS) { |
| // Asynchronous revalidation is only supported for GET and HEAD methods. |
| @@ -2614,7 +2688,8 @@ bool HttpCache::Transaction::ConditionalizeRequest() { |
| response_.headers->GetFreshnessLifetimes(response_.response_time); |
| if (lifetimes.staleness > TimeDelta()) { |
| TimeDelta current_age = response_.headers->GetCurrentAge( |
| - response_.request_time, response_.response_time, Time::Now()); |
| + response_.request_time, response_.response_time, |
| + cache_->clock_->Now()); |
| custom_request_->extra_headers.SetHeader( |
| kFreshnessHeader, |