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

Side by Side Diff: net/http/http_cache_transaction.cc

Issue 793823002: Let prefetched resources skip cache revalidation once for a short duration. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleaning up Created 6 years 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_cache_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #if defined(OS_POSIX) 9 #if defined(OS_POSIX)
10 #include <unistd.h> 10 #include <unistd.h>
11 #endif 11 #endif
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <string> 14 #include <string>
15 15
16 #include "base/bind.h" 16 #include "base/bind.h"
17 #include "base/compiler_specific.h" 17 #include "base/compiler_specific.h"
18 #include "base/format_macros.h" 18 #include "base/format_macros.h"
19 #include "base/memory/ref_counted.h" 19 #include "base/memory/ref_counted.h"
20 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
21 #include "base/metrics/field_trial.h" 21 #include "base/metrics/field_trial.h"
22 #include "base/metrics/histogram.h" 22 #include "base/metrics/histogram.h"
23 #include "base/metrics/sparse_histogram.h" 23 #include "base/metrics/sparse_histogram.h"
24 #include "base/profiler/scoped_tracker.h" 24 #include "base/profiler/scoped_tracker.h"
25 #include "base/rand_util.h" 25 #include "base/rand_util.h"
26 #include "base/strings/string_number_conversions.h" 26 #include "base/strings/string_number_conversions.h"
27 #include "base/strings/string_piece.h" 27 #include "base/strings/string_piece.h"
28 #include "base/strings/string_util.h" 28 #include "base/strings/string_util.h"
29 #include "base/strings/stringprintf.h" 29 #include "base/strings/stringprintf.h"
30 #include "base/time/clock.h"
30 #include "base/time/time.h" 31 #include "base/time/time.h"
31 #include "base/values.h" 32 #include "base/values.h"
32 #include "net/base/completion_callback.h" 33 #include "net/base/completion_callback.h"
33 #include "net/base/io_buffer.h" 34 #include "net/base/io_buffer.h"
34 #include "net/base/load_flags.h" 35 #include "net/base/load_flags.h"
35 #include "net/base/load_timing_info.h" 36 #include "net/base/load_timing_info.h"
36 #include "net/base/net_errors.h" 37 #include "net/base/net_errors.h"
37 #include "net/base/net_log.h" 38 #include "net/base/net_log.h"
38 #include "net/base/upload_data_stream.h" 39 #include "net/base/upload_data_stream.h"
39 #include "net/cert/cert_status_flags.h" 40 #include "net/cert/cert_status_flags.h"
(...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after
1527 // We received 304 or 206 and we want to update the cached response headers. 1528 // We received 304 or 206 and we want to update the cached response headers.
1528 int HttpCache::Transaction::DoUpdateCachedResponse() { 1529 int HttpCache::Transaction::DoUpdateCachedResponse() {
1529 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; 1530 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
1530 int rv = OK; 1531 int rv = OK;
1531 // Update cached response based on headers in new_response. 1532 // Update cached response based on headers in new_response.
1532 // TODO(wtc): should we update cached certificate (response_.ssl_info), too? 1533 // TODO(wtc): should we update cached certificate (response_.ssl_info), too?
1533 response_.headers->Update(*new_response_->headers.get()); 1534 response_.headers->Update(*new_response_->headers.get());
1534 response_.response_time = new_response_->response_time; 1535 response_.response_time = new_response_->response_time;
1535 response_.request_time = new_response_->request_time; 1536 response_.request_time = new_response_->request_time;
1536 response_.network_accessed = new_response_->network_accessed; 1537 response_.network_accessed = new_response_->network_accessed;
1538 response_.unused_since_prefetch = new_response_->unused_since_prefetch;
1537 1539
1538 if (response_.headers->HasHeaderValue("cache-control", "no-store")) { 1540 if (response_.headers->HasHeaderValue("cache-control", "no-store")) {
1539 if (!entry_->doomed) { 1541 if (!entry_->doomed) {
1540 int ret = cache_->DoomEntry(cache_key_, NULL); 1542 int ret = cache_->DoomEntry(cache_key_, NULL);
1541 DCHECK_EQ(OK, ret); 1543 DCHECK_EQ(OK, ret);
1542 } 1544 }
1543 } else { 1545 } else {
1544 // If we are already reading, we already updated the headers for this 1546 // If we are already reading, we already updated the headers for this
1545 // request; doing it again will change Content-Length. 1547 // request; doing it again will change Content-Length.
1546 if (!reading_) { 1548 if (!reading_) {
(...skipping 13 matching lines...) Expand all
1560 // 1562 //
1561 // By closing the cached entry now, we make sure that the 304 rather than 1563 // By closing the cached entry now, we make sure that the 304 rather than
1562 // the cached 200 response, is what will be returned to the user. 1564 // the cached 200 response, is what will be returned to the user.
1563 DoneWritingToEntry(true); 1565 DoneWritingToEntry(true);
1564 } else if (entry_ && !handling_206_) { 1566 } else if (entry_ && !handling_206_) {
1565 DCHECK_EQ(READ_WRITE, mode_); 1567 DCHECK_EQ(READ_WRITE, mode_);
1566 if (!partial_.get() || partial_->IsLastRange()) { 1568 if (!partial_.get() || partial_->IsLastRange()) {
1567 cache_->ConvertWriterToReader(entry_); 1569 cache_->ConvertWriterToReader(entry_);
1568 mode_ = READ; 1570 mode_ = READ;
1569 } 1571 }
1570 // We no longer need the network transaction, so destroy it. 1572
1571 final_upload_progress_ = network_trans_->GetUploadProgress(); 1573 if (network_trans_) {
1572 ResetNetworkTransaction(); 1574 // We no longer need the network transaction, so destroy it.
1575 final_upload_progress_ = network_trans_->GetUploadProgress();
1576 ResetNetworkTransaction();
1577 }
1573 } else if (entry_ && handling_206_ && truncated_ && 1578 } else if (entry_ && handling_206_ && truncated_ &&
1574 partial_->initial_validation()) { 1579 partial_->initial_validation()) {
1575 // We just finished the validation of a truncated entry, and the server 1580 // We just finished the validation of a truncated entry, and the server
1576 // is willing to resume the operation. Now we go back and start serving 1581 // is willing to resume the operation. Now we go back and start serving
1577 // the first part to the user. 1582 // the first part to the user.
1578 ResetNetworkTransaction(); 1583 ResetNetworkTransaction();
1579 new_response_ = NULL; 1584 new_response_ = NULL;
1580 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 1585 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
1581 partial_->SetRangeToStartDownload(); 1586 partial_->SetRangeToStartDownload();
1582 return OK; 1587 return OK;
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
2165 // Force revalidation for sparse or truncated entries. Note that we don't 2170 // Force revalidation for sparse or truncated entries. Note that we don't
2166 // want to ignore the regular validation logic just because a byte range was 2171 // want to ignore the regular validation logic just because a byte range was
2167 // part of the request. 2172 // part of the request.
2168 skip_validation = false; 2173 skip_validation = false;
2169 } 2174 }
2170 2175
2171 if (skip_validation) { 2176 if (skip_validation) {
2172 // TODO(ricea): Is this pattern okay for asynchronous revalidations? 2177 // TODO(ricea): Is this pattern okay for asynchronous revalidations?
2173 UpdateTransactionPattern(PATTERN_ENTRY_USED); 2178 UpdateTransactionPattern(PATTERN_ENTRY_USED);
2174 RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE); 2179 RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE);
2180
2181 if (response_.unused_since_prefetch ||
2182 (!response_.unused_since_prefetch &&
2183 request_->load_flags & LOAD_PREFETCH)) {
2184 // Either this is the first use of an entry since it was prefetched or
2185 // this is a prefetch. Flip the bit on response.unused_since_prefetch and
2186 // write it back to the cache before reading.
2187 response_.unused_since_prefetch = !response_.unused_since_prefetch;
rvargas (doing something else) 2014/12/12 02:20:49 READ and UPDATE requests don't go through this cod
jkarlin 2014/12/15 17:19:25 Done.
2188 target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
rvargas (doing something else) 2014/12/12 02:20:49 Joining back in DoUpdateCachedResponseComplete loo
jkarlin 2014/12/15 17:19:25 Done.
2189 next_state_ = STATE_CACHE_WRITE_RESPONSE;
2190 return OK;
2191 }
2192
2175 return SetupEntryForRead(); 2193 return SetupEntryForRead();
2176 } else { 2194 } else {
2177 // Make the network request conditional, to see if we may reuse our cached 2195 // Make the network request conditional, to see if we may reuse our cached
2178 // response. If we cannot do so, then we just resort to a normal fetch. 2196 // response. If we cannot do so, then we just resort to a normal fetch.
2179 // Our mode remains READ_WRITE for a conditional request. Even if the 2197 // Our mode remains READ_WRITE for a conditional request. Even if the
2180 // conditionalization fails, we don't switch to WRITE mode until we 2198 // conditionalization fails, we don't switch to WRITE mode until we
2181 // know we won't be falling back to using the cache entry in the 2199 // know we won't be falling back to using the cache entry in the
2182 // LOAD_FROM_CACHE_IF_OFFLINE case. 2200 // LOAD_FROM_CACHE_IF_OFFLINE case.
2183 if (!ConditionalizeRequest()) { 2201 if (!ConditionalizeRequest()) {
2184 couldnt_conditionalize_request_ = true; 2202 couldnt_conditionalize_request_ = true;
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2337 if (response_.vary_data.is_valid() && 2355 if (response_.vary_data.is_valid() &&
2338 !response_.vary_data.MatchesRequest(*request_, 2356 !response_.vary_data.MatchesRequest(*request_,
2339 *response_.headers.get())) { 2357 *response_.headers.get())) {
2340 vary_mismatch_ = true; 2358 vary_mismatch_ = true;
2341 return VALIDATION_SYNCHRONOUS; 2359 return VALIDATION_SYNCHRONOUS;
2342 } 2360 }
2343 2361
2344 if (effective_load_flags_ & LOAD_PREFERRING_CACHE) 2362 if (effective_load_flags_ & LOAD_PREFERRING_CACHE)
2345 return VALIDATION_NONE; 2363 return VALIDATION_NONE;
2346 2364
2365 if (response_.unused_since_prefetch &&
2366 response_.headers->GetCurrentAge(
2367 response_.request_time, response_.response_time,
2368 cache_->clock_->Now()) < TimeDelta::FromMinutes(kPrefetchReuseMins)) {
2369 // The first use of a resource after prefetch within a short window skips
2370 // validation.
2371 return VALIDATION_NONE;
2372 }
2373
2347 if (effective_load_flags_ & (LOAD_VALIDATE_CACHE | LOAD_ASYNC_REVALIDATION)) 2374 if (effective_load_flags_ & (LOAD_VALIDATE_CACHE | LOAD_ASYNC_REVALIDATION))
2348 return VALIDATION_SYNCHRONOUS; 2375 return VALIDATION_SYNCHRONOUS;
2349 2376
2350 if (request_->method == "PUT" || request_->method == "DELETE") 2377 if (request_->method == "PUT" || request_->method == "DELETE")
2351 return VALIDATION_SYNCHRONOUS; 2378 return VALIDATION_SYNCHRONOUS;
2352 2379
2353 ValidationType validation_required_by_headers = 2380 ValidationType validation_required_by_headers =
2354 response_.headers->RequiresValidation( 2381 response_.headers->RequiresValidation(response_.request_time,
2355 response_.request_time, response_.response_time, Time::Now()); 2382 response_.response_time,
2383 cache_->clock_->Now());
2356 2384
2357 if (validation_required_by_headers == VALIDATION_ASYNCHRONOUS) { 2385 if (validation_required_by_headers == VALIDATION_ASYNCHRONOUS) {
2358 // Asynchronous revalidation is only supported for GET and HEAD methods. 2386 // Asynchronous revalidation is only supported for GET and HEAD methods.
2359 if (request_->method != "GET" && request_->method != "HEAD") 2387 if (request_->method != "GET" && request_->method != "HEAD")
2360 return VALIDATION_SYNCHRONOUS; 2388 return VALIDATION_SYNCHRONOUS;
2361 } 2389 }
2362 2390
2363 return validation_required_by_headers; 2391 return validation_required_by_headers;
2364 } 2392 }
2365 2393
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2406 bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() && 2434 bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() &&
2407 !invalid_range_; 2435 !invalid_range_;
2408 2436
2409 if (!use_if_range) { 2437 if (!use_if_range) {
2410 // stale-while-revalidate is not useful when we only have a partial response 2438 // stale-while-revalidate is not useful when we only have a partial response
2411 // cached, so don't set the header in that case. 2439 // cached, so don't set the header in that case.
2412 HttpResponseHeaders::FreshnessLifetimes lifetimes = 2440 HttpResponseHeaders::FreshnessLifetimes lifetimes =
2413 response_.headers->GetFreshnessLifetimes(response_.response_time); 2441 response_.headers->GetFreshnessLifetimes(response_.response_time);
2414 if (lifetimes.staleness > TimeDelta()) { 2442 if (lifetimes.staleness > TimeDelta()) {
2415 TimeDelta current_age = response_.headers->GetCurrentAge( 2443 TimeDelta current_age = response_.headers->GetCurrentAge(
2416 response_.request_time, response_.response_time, Time::Now()); 2444 response_.request_time, response_.response_time,
2445 cache_->clock_->Now());
2417 2446
2418 custom_request_->extra_headers.SetHeader( 2447 custom_request_->extra_headers.SetHeader(
2419 kFreshnessHeader, 2448 kFreshnessHeader,
2420 base::StringPrintf("max-age=%" PRId64 2449 base::StringPrintf("max-age=%" PRId64
2421 ",stale-while-revalidate=%" PRId64 ",age=%" PRId64, 2450 ",stale-while-revalidate=%" PRId64 ",age=%" PRId64,
2422 lifetimes.freshness.InSeconds(), 2451 lifetimes.freshness.InSeconds(),
2423 lifetimes.staleness.InSeconds(), 2452 lifetimes.staleness.InSeconds(),
2424 current_age.InSeconds())); 2453 current_age.InSeconds()));
2425 } 2454 }
2426 } 2455 }
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
2952 2981
2953 void HttpCache::Transaction::OnIOComplete(int result) { 2982 void HttpCache::Transaction::OnIOComplete(int result) {
2954 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. 2983 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
2955 tracked_objects::ScopedTracker tracking_profile( 2984 tracked_objects::ScopedTracker tracking_profile(
2956 FROM_HERE_WITH_EXPLICIT_FUNCTION("422516 Transaction::OnIOComplete")); 2985 FROM_HERE_WITH_EXPLICIT_FUNCTION("422516 Transaction::OnIOComplete"));
2957 2986
2958 DoLoop(result); 2987 DoLoop(result);
2959 } 2988 }
2960 2989
2961 } // namespace net 2990 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698