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