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 |