Chromium Code Reviews| 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 2418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2429 stale_entry_freshness_ = lifetimes.freshness; | 2429 stale_entry_freshness_ = lifetimes.freshness; |
| 2430 stale_entry_age_ = response_.headers->GetCurrentAge( | 2430 stale_entry_age_ = response_.headers->GetCurrentAge( |
| 2431 response_.request_time, response_.response_time, | 2431 response_.request_time, response_.response_time, |
| 2432 cache_->clock_->Now()); | 2432 cache_->clock_->Now()); |
| 2433 } | 2433 } |
| 2434 } | 2434 } |
| 2435 | 2435 |
| 2436 return validation_required_by_headers; | 2436 return validation_required_by_headers; |
| 2437 } | 2437 } |
| 2438 | 2438 |
| 2439 bool HttpCache::Transaction::ResponseConditionalizable( | |
| 2440 std::string* etag_value, | |
| 2441 std::string* last_modified_value) { | |
| 2442 DCHECK(response_.headers.get()); | |
| 2443 | |
| 2444 // This only makes sense for cached 200 or 206 responses. | |
| 2445 if (response_.headers->response_code() != 200 && | |
| 2446 response_.headers->response_code() != 206) { | |
| 2447 return false; | |
| 2448 } | |
| 2449 | |
| 2450 // ### this looks scary. | |
| 2451 DCHECK(response_.headers->response_code() != 206 || | |
| 2452 response_.headers->HasStrongValidators()); | |
| 2453 | |
| 2454 // Just use the first available ETag and/or Last-Modified header value. | |
| 2455 // TODO(darin): Or should we use the last? | |
| 2456 | |
| 2457 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) | |
| 2458 response_.headers->EnumerateHeader(NULL, "etag", etag_value); | |
| 2459 | |
| 2460 response_.headers->EnumerateHeader(NULL, "last-modified", | |
| 2461 last_modified_value); | |
| 2462 | |
| 2463 if (etag_value->empty() && last_modified_value->empty()) | |
| 2464 return false; | |
| 2465 | |
| 2466 return true; | |
| 2467 } | |
| 2468 | |
| 2439 bool HttpCache::Transaction::ConditionalizeRequest() { | 2469 bool HttpCache::Transaction::ConditionalizeRequest() { |
| 2440 DCHECK(response_.headers.get()); | 2470 DCHECK(response_.headers.get()); |
| 2441 | 2471 |
| 2442 if (method_ == "PUT" || method_ == "DELETE") | 2472 if (method_ == "PUT" || method_ == "DELETE") |
| 2443 return false; | 2473 return false; |
| 2444 | 2474 |
| 2445 // This only makes sense for cached 200 or 206 responses. | |
| 2446 if (response_.headers->response_code() != 200 && | |
| 2447 response_.headers->response_code() != 206) { | |
| 2448 return false; | |
| 2449 } | |
| 2450 | |
| 2451 if (fail_conditionalization_for_test_) | 2475 if (fail_conditionalization_for_test_) |
| 2452 return false; | 2476 return false; |
| 2453 | 2477 |
| 2454 DCHECK(response_.headers->response_code() != 206 || | 2478 std::string etag_value; |
| 2455 response_.headers->HasStrongValidators()); | 2479 std::string last_modified_value; |
| 2480 if (!ResponseConditionalizable(&etag_value, &last_modified_value)) | |
| 2481 return false; | |
| 2456 | 2482 |
| 2457 // Just use the first available ETag and/or Last-Modified header value. | 2483 if (vary_mismatch_) { |
| 2458 // TODO(darin): Or should we use the last? | 2484 // Can't rely on last-modified if vary is different. |
| 2459 | 2485 last_modified_value.clear(); |
| 2460 std::string etag_value; | 2486 if (etag_value.empty()) |
| 2461 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) | 2487 return false; |
| 2462 response_.headers->EnumerateHeader(NULL, "etag", &etag_value); | |
| 2463 | |
| 2464 std::string last_modified_value; | |
| 2465 if (!vary_mismatch_) { | |
| 2466 response_.headers->EnumerateHeader(NULL, "last-modified", | |
| 2467 &last_modified_value); | |
| 2468 } | 2488 } |
| 2469 | 2489 |
| 2470 if (etag_value.empty() && last_modified_value.empty()) | |
| 2471 return false; | |
| 2472 | |
| 2473 if (!partial_) { | 2490 if (!partial_) { |
| 2474 // Need to customize the request, so this forces us to allocate :( | 2491 // Need to customize the request, so this forces us to allocate :( |
| 2475 custom_request_.reset(new HttpRequestInfo(*request_)); | 2492 custom_request_.reset(new HttpRequestInfo(*request_)); |
| 2476 request_ = custom_request_.get(); | 2493 request_ = custom_request_.get(); |
| 2477 } | 2494 } |
| 2478 DCHECK(custom_request_.get()); | 2495 DCHECK(custom_request_.get()); |
| 2479 | 2496 |
| 2480 bool use_if_range = | 2497 bool use_if_range = |
| 2481 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_; | 2498 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_; |
| 2482 | 2499 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 2502 HttpRequestHeaders::kIfRange, last_modified_value); | 2519 HttpRequestHeaders::kIfRange, last_modified_value); |
| 2503 } else { | 2520 } else { |
| 2504 custom_request_->extra_headers.SetHeader( | 2521 custom_request_->extra_headers.SetHeader( |
| 2505 HttpRequestHeaders::kIfModifiedSince, last_modified_value); | 2522 HttpRequestHeaders::kIfModifiedSince, last_modified_value); |
| 2506 } | 2523 } |
| 2507 } | 2524 } |
| 2508 | 2525 |
| 2509 return true; | 2526 return true; |
| 2510 } | 2527 } |
| 2511 | 2528 |
| 2529 bool HttpCache::Transaction::MaybeRejectBasedOnMemoryEntryData( | |
| 2530 uint8_t in_memory_info) { | |
| 2531 // Not going to be clever with those... though is it even set here? | |
| 2532 if (partial_) | |
| 2533 return false; | |
| 2534 | |
| 2535 // We can tell that some entries in cache may be unusable under present | |
| 2536 // circumstances if: | |
| 2537 // 1) We aren't using everything because of LOAD_SKIP_CACHE_VALIDATION. | |
| 2538 // 2) We aren't holding on to results of an unused prefetch. | |
| 2539 // 3) The entry has zero freshness (so it's known to be expired!) | |
| 2540 // 4) We know the entry can't be revalidated | |
| 2541 // (we may be able to match more things here). | |
| 2542 if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION) | |
| 2543 return false; | |
| 2544 | |
| 2545 if (in_memory_info & HttpCache::OBH_UNUSED_SINCE_PREFETCH) | |
| 2546 return false; | |
| 2547 | |
| 2548 if (!(in_memory_info & HttpCache::OBH_ZERO_LIFETIME)) | |
| 2549 return false; | |
| 2550 | |
| 2551 if (!(in_memory_info & OBH_RESPONSE_CANT_CONDITIONALIZE)) | |
| 2552 return false; | |
| 2553 | |
| 2554 cache_pending_ = false; | |
| 2555 couldnt_conditionalize_request_ = true; | |
| 2556 response_.was_cached = true; | |
| 2557 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE); | |
| 2558 // ### ugh, this is bad, but just sketching. | |
| 2559 // TransitionToState(STATE_SEND_REQUEST); | |
| 2560 next_state_ = STATE_SEND_REQUEST; | |
|
Maks Orlovich
2017/06/14 19:59:29
So I just realized that this implementation is bog
| |
| 2561 | |
| 2562 return true; | |
| 2563 } | |
| 2564 | |
| 2512 // We just received some headers from the server. We may have asked for a range, | 2565 // We just received some headers from the server. We may have asked for a range, |
| 2513 // in which case partial_ has an object. This could be the first network request | 2566 // in which case partial_ has an object. This could be the first network request |
| 2514 // we make to fulfill the original request, or we may be already reading (from | 2567 // we make to fulfill the original request, or we may be already reading (from |
| 2515 // the net and / or the cache). If we are not expecting a certain response, we | 2568 // the net and / or the cache). If we are not expecting a certain response, we |
| 2516 // just bypass the cache for this request (but again, maybe we are reading), and | 2569 // just bypass the cache for this request (but again, maybe we are reading), and |
| 2517 // delete partial_ (so we are not able to "fix" the headers that we return to | 2570 // delete partial_ (so we are not able to "fix" the headers that we return to |
| 2518 // the user). This results in either a weird response for the caller (we don't | 2571 // the user). This results in either a weird response for the caller (we don't |
| 2519 // expect it after all), or maybe a range that was not exactly what it was asked | 2572 // expect it after all), or maybe a range that was not exactly what it was asked |
| 2520 // for. | 2573 // for. |
| 2521 // | 2574 // |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2724 if (truncated) | 2777 if (truncated) |
| 2725 DCHECK_EQ(200, response_.headers->response_code()); | 2778 DCHECK_EQ(200, response_.headers->response_code()); |
| 2726 | 2779 |
| 2727 // When writing headers, we normally only write the non-transient headers. | 2780 // When writing headers, we normally only write the non-transient headers. |
| 2728 bool skip_transient_headers = true; | 2781 bool skip_transient_headers = true; |
| 2729 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); | 2782 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); |
| 2730 response_.Persist(data->pickle(), skip_transient_headers, truncated); | 2783 response_.Persist(data->pickle(), skip_transient_headers, truncated); |
| 2731 data->Done(); | 2784 data->Done(); |
| 2732 | 2785 |
| 2733 io_buf_len_ = data->pickle()->size(); | 2786 io_buf_len_ = data->pickle()->size(); |
| 2787 | |
| 2788 uint8_t hints = 0; | |
| 2789 // ### recomputing this too much? | |
| 2790 if (response_.headers->GetFreshnessLifetimes(response_.response_time) | |
| 2791 .freshness.is_zero()) | |
| 2792 hints |= HttpCache::OBH_ZERO_LIFETIME; | |
| 2793 std::string etag_ignored, last_modified_ignored; | |
| 2794 if (!ResponseConditionalizable(&etag_ignored, &last_modified_ignored)) | |
| 2795 hints |= HttpCache::OBH_RESPONSE_CANT_CONDITIONALIZE; | |
| 2796 if (response_.unused_since_prefetch) | |
| 2797 hints |= HttpCache::OBH_UNUSED_SINCE_PREFETCH; | |
| 2798 cache_->GetCurrentBackend()->SetMemoryEntryData(cache_key_, hints); | |
| 2734 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), | 2799 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), |
| 2735 io_buf_len_, io_callback_, true); | 2800 io_buf_len_, io_callback_, true); |
| 2736 } | 2801 } |
| 2737 | 2802 |
| 2738 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { | 2803 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { |
| 2739 if (!entry_) | 2804 if (!entry_) |
| 2740 return OK; | 2805 return OK; |
| 2741 if (net_log_.IsCapturing()) { | 2806 if (net_log_.IsCapturing()) { |
| 2742 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, | 2807 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, |
| 2743 result); | 2808 result); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3124 } | 3189 } |
| 3125 | 3190 |
| 3126 void HttpCache::Transaction::TransitionToState(State state) { | 3191 void HttpCache::Transaction::TransitionToState(State state) { |
| 3127 // Ensure that the state is only set once per Do* state. | 3192 // Ensure that the state is only set once per Do* state. |
| 3128 DCHECK(in_do_loop_); | 3193 DCHECK(in_do_loop_); |
| 3129 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state; | 3194 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state; |
| 3130 next_state_ = state; | 3195 next_state_ = state; |
| 3131 } | 3196 } |
| 3132 | 3197 |
| 3133 } // namespace net | 3198 } // namespace net |
| OLD | NEW |