OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |