| 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" | |
| 21 #include "base/metrics/field_trial.h" | 20 #include "base/metrics/field_trial.h" |
| 22 #include "base/metrics/histogram.h" | 21 #include "base/metrics/histogram.h" |
| 23 #include "base/metrics/sparse_histogram.h" | 22 #include "base/metrics/sparse_histogram.h" |
| 24 #include "base/profiler/scoped_tracker.h" | 23 #include "base/profiler/scoped_tracker.h" |
| 25 #include "base/rand_util.h" | 24 #include "base/rand_util.h" |
| 26 #include "base/strings/string_number_conversions.h" | 25 #include "base/strings/string_number_conversions.h" |
| 27 #include "base/strings/string_piece.h" | 26 #include "base/strings/string_piece.h" |
| 28 #include "base/strings/string_util.h" | 27 #include "base/strings/string_util.h" |
| 29 #include "base/strings/stringprintf.h" | 28 #include "base/strings/stringprintf.h" |
| 30 #include "base/time/clock.h" | 29 #include "base/time/clock.h" |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 174 |
| 176 void RecordNoStoreHeaderHistogram(int load_flags, | 175 void RecordNoStoreHeaderHistogram(int load_flags, |
| 177 const HttpResponseInfo* response) { | 176 const HttpResponseInfo* response) { |
| 178 if (load_flags & LOAD_MAIN_FRAME) { | 177 if (load_flags & LOAD_MAIN_FRAME) { |
| 179 UMA_HISTOGRAM_BOOLEAN( | 178 UMA_HISTOGRAM_BOOLEAN( |
| 180 "Net.MainFrameNoStore", | 179 "Net.MainFrameNoStore", |
| 181 response->headers->HasHeaderValue("cache-control", "no-store")); | 180 response->headers->HasHeaderValue("cache-control", "no-store")); |
| 182 } | 181 } |
| 183 } | 182 } |
| 184 | 183 |
| 185 scoped_ptr<base::Value> NetLogAsyncRevalidationInfoCallback( | |
| 186 const NetLog::Source& source, | |
| 187 const HttpRequestInfo* request, | |
| 188 NetLogCaptureMode capture_mode) { | |
| 189 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | |
| 190 source.AddToEventParameters(dict.get()); | |
| 191 | |
| 192 dict->SetString("url", request->url.possibly_invalid_spec()); | |
| 193 dict->SetString("method", request->method); | |
| 194 return dict.Pass(); | |
| 195 } | |
| 196 | |
| 197 enum ExternallyConditionalizedType { | 184 enum ExternallyConditionalizedType { |
| 198 EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION, | 185 EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION, |
| 199 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE, | 186 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE, |
| 200 EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS, | 187 EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS, |
| 201 EXTERNALLY_CONDITIONALIZED_MAX | 188 EXTERNALLY_CONDITIONALIZED_MAX |
| 202 }; | 189 }; |
| 203 | 190 |
| 204 } // namespace | 191 } // namespace |
| 205 | 192 |
| 206 struct HeaderNameAndValue { | 193 struct HeaderNameAndValue { |
| (...skipping 1918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2125 return OK; | 2112 return OK; |
| 2126 } | 2113 } |
| 2127 | 2114 |
| 2128 int HttpCache::Transaction::BeginCacheValidation() { | 2115 int HttpCache::Transaction::BeginCacheValidation() { |
| 2129 DCHECK(mode_ == READ_WRITE); | 2116 DCHECK(mode_ == READ_WRITE); |
| 2130 | 2117 |
| 2131 ValidationType required_validation = RequiresValidation(); | 2118 ValidationType required_validation = RequiresValidation(); |
| 2132 | 2119 |
| 2133 bool skip_validation = (required_validation == VALIDATION_NONE); | 2120 bool skip_validation = (required_validation == VALIDATION_NONE); |
| 2134 | 2121 |
| 2135 if (required_validation == VALIDATION_ASYNCHRONOUS && | |
| 2136 !(request_->method == "GET" && (truncated_ || partial_)) && cache_ && | |
| 2137 cache_->use_stale_while_revalidate()) { | |
| 2138 TriggerAsyncValidation(); | |
| 2139 skip_validation = true; | |
| 2140 } | |
| 2141 | |
| 2142 if (request_->method == "HEAD" && | 2122 if (request_->method == "HEAD" && |
| 2143 (truncated_ || response_.headers->response_code() == 206)) { | 2123 (truncated_ || response_.headers->response_code() == 206)) { |
| 2144 DCHECK(!partial_); | 2124 DCHECK(!partial_); |
| 2145 if (skip_validation) | 2125 if (skip_validation) |
| 2146 return SetupEntryForRead(); | 2126 return SetupEntryForRead(); |
| 2147 | 2127 |
| 2148 // Bail out! | 2128 // Bail out! |
| 2149 next_state_ = STATE_SEND_REQUEST; | 2129 next_state_ = STATE_SEND_REQUEST; |
| 2150 mode_ = NONE; | 2130 mode_ = NONE; |
| 2151 return OK; | 2131 return OK; |
| 2152 } | 2132 } |
| 2153 | 2133 |
| 2154 if (truncated_) { | 2134 if (truncated_) { |
| 2155 // Truncated entries can cause partial gets, so we shouldn't record this | 2135 // Truncated entries can cause partial gets, so we shouldn't record this |
| 2156 // load in histograms. | 2136 // load in histograms. |
| 2157 UpdateTransactionPattern(PATTERN_NOT_COVERED); | 2137 UpdateTransactionPattern(PATTERN_NOT_COVERED); |
| 2158 skip_validation = !partial_->initial_validation(); | 2138 skip_validation = !partial_->initial_validation(); |
| 2159 } | 2139 } |
| 2160 | 2140 |
| 2161 if (partial_.get() && (is_sparse_ || truncated_) && | 2141 if (partial_.get() && (is_sparse_ || truncated_) && |
| 2162 (!partial_->IsCurrentRangeCached() || invalid_range_)) { | 2142 (!partial_->IsCurrentRangeCached() || invalid_range_)) { |
| 2163 // Force revalidation for sparse or truncated entries. Note that we don't | 2143 // Force revalidation for sparse or truncated entries. Note that we don't |
| 2164 // want to ignore the regular validation logic just because a byte range was | 2144 // want to ignore the regular validation logic just because a byte range was |
| 2165 // part of the request. | 2145 // part of the request. |
| 2166 skip_validation = false; | 2146 skip_validation = false; |
| 2167 } | 2147 } |
| 2168 | 2148 |
| 2169 if (skip_validation) { | 2149 if (skip_validation) { |
| 2170 // TODO(ricea): Is this pattern okay for asynchronous revalidations? | |
| 2171 UpdateTransactionPattern(PATTERN_ENTRY_USED); | 2150 UpdateTransactionPattern(PATTERN_ENTRY_USED); |
| 2172 return SetupEntryForRead(); | 2151 return SetupEntryForRead(); |
| 2173 } else { | 2152 } else { |
| 2174 // Make the network request conditional, to see if we may reuse our cached | 2153 // Make the network request conditional, to see if we may reuse our cached |
| 2175 // response. If we cannot do so, then we just resort to a normal fetch. | 2154 // response. If we cannot do so, then we just resort to a normal fetch. |
| 2176 // Our mode remains READ_WRITE for a conditional request. Even if the | 2155 // Our mode remains READ_WRITE for a conditional request. Even if the |
| 2177 // conditionalization fails, we don't switch to WRITE mode until we | 2156 // conditionalization fails, we don't switch to WRITE mode until we |
| 2178 // know we won't be falling back to using the cache entry in the | 2157 // know we won't be falling back to using the cache entry in the |
| 2179 // LOAD_FROM_CACHE_IF_OFFLINE case. | 2158 // LOAD_FROM_CACHE_IF_OFFLINE case. |
| 2180 if (!ConditionalizeRequest()) { | 2159 if (!ConditionalizeRequest()) { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2340 if (response_.unused_since_prefetch && | 2319 if (response_.unused_since_prefetch && |
| 2341 !(effective_load_flags_ & LOAD_PREFETCH) && | 2320 !(effective_load_flags_ & LOAD_PREFETCH) && |
| 2342 response_.headers->GetCurrentAge( | 2321 response_.headers->GetCurrentAge( |
| 2343 response_.request_time, response_.response_time, | 2322 response_.request_time, response_.response_time, |
| 2344 cache_->clock_->Now()) < TimeDelta::FromMinutes(kPrefetchReuseMins)) { | 2323 cache_->clock_->Now()) < TimeDelta::FromMinutes(kPrefetchReuseMins)) { |
| 2345 // The first use of a resource after prefetch within a short window skips | 2324 // The first use of a resource after prefetch within a short window skips |
| 2346 // validation. | 2325 // validation. |
| 2347 return VALIDATION_NONE; | 2326 return VALIDATION_NONE; |
| 2348 } | 2327 } |
| 2349 | 2328 |
| 2350 if (effective_load_flags_ & (LOAD_VALIDATE_CACHE | LOAD_ASYNC_REVALIDATION)) | 2329 if (effective_load_flags_ & LOAD_VALIDATE_CACHE) |
| 2351 return VALIDATION_SYNCHRONOUS; | 2330 return VALIDATION_SYNCHRONOUS; |
| 2352 | 2331 |
| 2353 if (request_->method == "PUT" || request_->method == "DELETE") | 2332 if (request_->method == "PUT" || request_->method == "DELETE") |
| 2354 return VALIDATION_SYNCHRONOUS; | 2333 return VALIDATION_SYNCHRONOUS; |
| 2355 | 2334 |
| 2356 ValidationType validation_required_by_headers = | 2335 ValidationType validation_required_by_headers = |
| 2357 response_.headers->RequiresValidation(response_.request_time, | 2336 response_.headers->RequiresValidation(response_.request_time, |
| 2358 response_.response_time, | 2337 response_.response_time, |
| 2359 cache_->clock_->Now()); | 2338 cache_->clock_->Now()); |
| 2360 | 2339 |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 mode_ = NONE; | 2573 mode_ = NONE; |
| 2595 } | 2574 } |
| 2596 | 2575 |
| 2597 void HttpCache::Transaction::FixHeadersForHead() { | 2576 void HttpCache::Transaction::FixHeadersForHead() { |
| 2598 if (response_.headers->response_code() == 206) { | 2577 if (response_.headers->response_code() == 206) { |
| 2599 response_.headers->RemoveHeader("Content-Range"); | 2578 response_.headers->RemoveHeader("Content-Range"); |
| 2600 response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK"); | 2579 response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK"); |
| 2601 } | 2580 } |
| 2602 } | 2581 } |
| 2603 | 2582 |
| 2604 void HttpCache::Transaction::TriggerAsyncValidation() { | |
| 2605 DCHECK(!request_->upload_data_stream); | |
| 2606 BoundNetLog async_revalidation_net_log( | |
| 2607 BoundNetLog::Make(net_log_.net_log(), NetLog::SOURCE_ASYNC_REVALIDATION)); | |
| 2608 net_log_.AddEvent( | |
| 2609 NetLog::TYPE_HTTP_CACHE_VALIDATE_RESOURCE_ASYNC, | |
| 2610 async_revalidation_net_log.source().ToEventParametersCallback()); | |
| 2611 async_revalidation_net_log.BeginEvent( | |
| 2612 NetLog::TYPE_ASYNC_REVALIDATION, | |
| 2613 base::Bind( | |
| 2614 &NetLogAsyncRevalidationInfoCallback, net_log_.source(), request_)); | |
| 2615 base::MessageLoop::current()->PostTask( | |
| 2616 FROM_HERE, | |
| 2617 base::Bind(&HttpCache::PerformAsyncValidation, | |
| 2618 cache_, // cache_ is a weak pointer. | |
| 2619 *request_, | |
| 2620 async_revalidation_net_log)); | |
| 2621 } | |
| 2622 | |
| 2623 void HttpCache::Transaction::FailRangeRequest() { | 2583 void HttpCache::Transaction::FailRangeRequest() { |
| 2624 response_ = *new_response_; | 2584 response_ = *new_response_; |
| 2625 partial_->FixResponseHeaders(response_.headers.get(), false); | 2585 partial_->FixResponseHeaders(response_.headers.get(), false); |
| 2626 } | 2586 } |
| 2627 | 2587 |
| 2628 int HttpCache::Transaction::SetupEntryForRead() { | 2588 int HttpCache::Transaction::SetupEntryForRead() { |
| 2629 if (network_trans_) | 2589 if (network_trans_) |
| 2630 ResetNetworkTransaction(); | 2590 ResetNetworkTransaction(); |
| 2631 if (partial_.get()) { | 2591 if (partial_.get()) { |
| 2632 if (truncated_ || is_sparse_ || !invalid_range_) { | 2592 if (truncated_ || is_sparse_ || !invalid_range_) { |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2978 default: | 2938 default: |
| 2979 NOTREACHED(); | 2939 NOTREACHED(); |
| 2980 } | 2940 } |
| 2981 } | 2941 } |
| 2982 | 2942 |
| 2983 void HttpCache::Transaction::OnIOComplete(int result) { | 2943 void HttpCache::Transaction::OnIOComplete(int result) { |
| 2984 DoLoop(result); | 2944 DoLoop(result); |
| 2985 } | 2945 } |
| 2986 | 2946 |
| 2987 } // namespace net | 2947 } // namespace net |
| OLD | NEW |