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 2319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2330 stale_entry_freshness_ = lifetimes.freshness; | 2330 stale_entry_freshness_ = lifetimes.freshness; |
2331 stale_entry_age_ = response_.headers->GetCurrentAge( | 2331 stale_entry_age_ = response_.headers->GetCurrentAge( |
2332 response_.request_time, response_.response_time, | 2332 response_.request_time, response_.response_time, |
2333 cache_->clock_->Now()); | 2333 cache_->clock_->Now()); |
2334 } | 2334 } |
2335 } | 2335 } |
2336 | 2336 |
2337 return validation_required_by_headers; | 2337 return validation_required_by_headers; |
2338 } | 2338 } |
2339 | 2339 |
| 2340 bool HttpCache::Transaction::ResponseConditionalizable( |
| 2341 std::string* etag_value, |
| 2342 std::string* last_modified_value) { |
| 2343 DCHECK(response_.headers.get()); |
| 2344 |
| 2345 // This only makes sense for cached 200 or 206 responses. |
| 2346 if (response_.headers->response_code() != 200 && |
| 2347 response_.headers->response_code() != 206) { |
| 2348 return false; |
| 2349 } |
| 2350 |
| 2351 // ### this looks scary. |
| 2352 DCHECK(response_.headers->response_code() != 206 || |
| 2353 response_.headers->HasStrongValidators()); |
| 2354 |
| 2355 // Just use the first available ETag and/or Last-Modified header value. |
| 2356 // TODO(darin): Or should we use the last? |
| 2357 |
| 2358 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) |
| 2359 response_.headers->EnumerateHeader(NULL, "etag", etag_value); |
| 2360 |
| 2361 response_.headers->EnumerateHeader(NULL, "last-modified", |
| 2362 last_modified_value); |
| 2363 |
| 2364 if (etag_value->empty() && last_modified_value->empty()) |
| 2365 return false; |
| 2366 |
| 2367 return true; |
| 2368 } |
| 2369 |
2340 bool HttpCache::Transaction::ConditionalizeRequest() { | 2370 bool HttpCache::Transaction::ConditionalizeRequest() { |
2341 DCHECK(response_.headers.get()); | 2371 DCHECK(response_.headers.get()); |
2342 | 2372 |
2343 if (request_->method == "PUT" || request_->method == "DELETE") | 2373 if (request_->method == "PUT" || request_->method == "DELETE") |
2344 return false; | 2374 return false; |
2345 | 2375 |
2346 // This only makes sense for cached 200 or 206 responses. | |
2347 if (response_.headers->response_code() != 200 && | |
2348 response_.headers->response_code() != 206) { | |
2349 return false; | |
2350 } | |
2351 | |
2352 if (fail_conditionalization_for_test_) | 2376 if (fail_conditionalization_for_test_) |
2353 return false; | 2377 return false; |
2354 | 2378 |
2355 DCHECK(response_.headers->response_code() != 206 || | 2379 std::string etag_value; |
2356 response_.headers->HasStrongValidators()); | 2380 std::string last_modified_value; |
| 2381 if (!ResponseConditionalizable(&etag_value, &last_modified_value)) |
| 2382 return false; |
2357 | 2383 |
2358 // Just use the first available ETag and/or Last-Modified header value. | 2384 if (vary_mismatch_) { |
2359 // TODO(darin): Or should we use the last? | 2385 // Can't rely on last-modified if vary is different. |
2360 | 2386 last_modified_value.clear(); |
2361 std::string etag_value; | 2387 if (etag_value.empty()) |
2362 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) | 2388 return false; |
2363 response_.headers->EnumerateHeader(NULL, "etag", &etag_value); | |
2364 | |
2365 std::string last_modified_value; | |
2366 if (!vary_mismatch_) { | |
2367 response_.headers->EnumerateHeader(NULL, "last-modified", | |
2368 &last_modified_value); | |
2369 } | 2389 } |
2370 | 2390 |
2371 if (etag_value.empty() && last_modified_value.empty()) | |
2372 return false; | |
2373 | |
2374 if (!partial_) { | 2391 if (!partial_) { |
2375 // Need to customize the request, so this forces us to allocate :( | 2392 // Need to customize the request, so this forces us to allocate :( |
2376 custom_request_.reset(new HttpRequestInfo(*request_)); | 2393 custom_request_.reset(new HttpRequestInfo(*request_)); |
2377 request_ = custom_request_.get(); | 2394 request_ = custom_request_.get(); |
2378 } | 2395 } |
2379 DCHECK(custom_request_.get()); | 2396 DCHECK(custom_request_.get()); |
2380 | 2397 |
2381 bool use_if_range = | 2398 bool use_if_range = |
2382 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_; | 2399 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_; |
2383 | 2400 |
(...skipping 19 matching lines...) Expand all Loading... |
2403 HttpRequestHeaders::kIfRange, last_modified_value); | 2420 HttpRequestHeaders::kIfRange, last_modified_value); |
2404 } else { | 2421 } else { |
2405 custom_request_->extra_headers.SetHeader( | 2422 custom_request_->extra_headers.SetHeader( |
2406 HttpRequestHeaders::kIfModifiedSince, last_modified_value); | 2423 HttpRequestHeaders::kIfModifiedSince, last_modified_value); |
2407 } | 2424 } |
2408 } | 2425 } |
2409 | 2426 |
2410 return true; | 2427 return true; |
2411 } | 2428 } |
2412 | 2429 |
| 2430 bool HttpCache::Transaction::CanRejectBasedOnMemoryEntryData( |
| 2431 uint8_t in_memory_info) { |
| 2432 // We can tell that some entries in cache may be unusable under present |
| 2433 // circumstances if: |
| 2434 // 1) We aren't using everything because of LOAD_SKIP_CACHE_VALIDATION. |
| 2435 // 2) We aren't holding on to results of an unused prefetch. |
| 2436 // 3) The entry has zero freshness (so it's known to be expired!) |
| 2437 // 4) We know the entry can't be revalidated |
| 2438 // (we may be able to match more things here). |
| 2439 if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION) |
| 2440 return false; |
| 2441 |
| 2442 return (in_memory_info & HttpCache::OBH_ZERO_LIFETIME) && |
| 2443 (in_memory_info & HttpCache::OBH_RESPONSE_CANT_CONDITIONALIZE) && |
| 2444 !(in_memory_info & OBH_UNUSED_SINCE_PREFETCH); |
| 2445 } |
| 2446 |
2413 // We just received some headers from the server. We may have asked for a range, | 2447 // We just received some headers from the server. We may have asked for a range, |
2414 // in which case partial_ has an object. This could be the first network request | 2448 // in which case partial_ has an object. This could be the first network request |
2415 // we make to fulfill the original request, or we may be already reading (from | 2449 // we make to fulfill the original request, or we may be already reading (from |
2416 // the net and / or the cache). If we are not expecting a certain response, we | 2450 // the net and / or the cache). If we are not expecting a certain response, we |
2417 // just bypass the cache for this request (but again, maybe we are reading), and | 2451 // just bypass the cache for this request (but again, maybe we are reading), and |
2418 // delete partial_ (so we are not able to "fix" the headers that we return to | 2452 // delete partial_ (so we are not able to "fix" the headers that we return to |
2419 // the user). This results in either a weird response for the caller (we don't | 2453 // the user). This results in either a weird response for the caller (we don't |
2420 // expect it after all), or maybe a range that was not exactly what it was asked | 2454 // expect it after all), or maybe a range that was not exactly what it was asked |
2421 // for. | 2455 // for. |
2422 // | 2456 // |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2624 if (truncated) | 2658 if (truncated) |
2625 DCHECK_EQ(200, response_.headers->response_code()); | 2659 DCHECK_EQ(200, response_.headers->response_code()); |
2626 | 2660 |
2627 // When writing headers, we normally only write the non-transient headers. | 2661 // When writing headers, we normally only write the non-transient headers. |
2628 bool skip_transient_headers = true; | 2662 bool skip_transient_headers = true; |
2629 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); | 2663 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); |
2630 response_.Persist(data->pickle(), skip_transient_headers, truncated); | 2664 response_.Persist(data->pickle(), skip_transient_headers, truncated); |
2631 data->Done(); | 2665 data->Done(); |
2632 | 2666 |
2633 io_buf_len_ = data->pickle()->size(); | 2667 io_buf_len_ = data->pickle()->size(); |
| 2668 |
| 2669 uint8_t hints = 0; |
| 2670 // ### recomputing this too much? |
| 2671 if (response_.headers->GetFreshnessLifetimes(response_.response_time) |
| 2672 .freshness.is_zero()) |
| 2673 hints |= HttpCache::OBH_ZERO_LIFETIME; |
| 2674 std::string etag_ignored, last_modified_ignored; |
| 2675 if (!ResponseConditionalizable(&etag_ignored, &last_modified_ignored)) |
| 2676 hints |= HttpCache::OBH_RESPONSE_CANT_CONDITIONALIZE; |
| 2677 if (response_.unused_since_prefetch) |
| 2678 hints |= HttpCache::OBH_UNUSED_SINCE_PREFETCH; |
| 2679 cache_->GetCurrentBackend()->SetMemoryEntryData(cache_key_, hints); |
2634 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), | 2680 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), |
2635 io_buf_len_, io_callback_, true); | 2681 io_buf_len_, io_callback_, true); |
2636 } | 2682 } |
2637 | 2683 |
2638 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { | 2684 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { |
2639 if (!entry_) | 2685 if (!entry_) |
2640 return OK; | 2686 return OK; |
2641 if (net_log_.IsCapturing()) { | 2687 if (net_log_.IsCapturing()) { |
2642 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, | 2688 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, |
2643 result); | 2689 result); |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3017 } | 3063 } |
3018 | 3064 |
3019 void HttpCache::Transaction::TransitionToState(State state) { | 3065 void HttpCache::Transaction::TransitionToState(State state) { |
3020 // Ensure that the state is only set once per Do* state. | 3066 // Ensure that the state is only set once per Do* state. |
3021 DCHECK(in_do_loop_); | 3067 DCHECK(in_do_loop_); |
3022 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state; | 3068 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state; |
3023 next_state_ = state; | 3069 next_state_ = state; |
3024 } | 3070 } |
3025 | 3071 |
3026 } // namespace net | 3072 } // namespace net |
OLD | NEW |