Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: net/http/http_cache_transaction.cc

Issue 2959183002: Start work on splitting off the usage piece of in-memory index. This revision is just from the prev…
Patch Set: Rebase Created 3 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | net/http/http_cache_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
1054 if (result == OK) { 1054 if (result == OK) {
1055 TransitionToState(STATE_ADD_TO_ENTRY); 1055 TransitionToState(STATE_ADD_TO_ENTRY);
1056 return OK; 1056 return OK;
1057 } 1057 }
1058 1058
1059 if (result == ERR_CACHE_RACE) { 1059 if (result == ERR_CACHE_RACE) {
1060 TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED); 1060 TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
1061 return OK; 1061 return OK;
1062 } 1062 }
1063 1063
1064 if (result == ERR_CACHE_ENTRY_NOT_SUITABLE) {
1065 DCHECK_EQ(mode_, READ_WRITE);
1066 // Record this as CantConditionalize, but otherwise proceed as we would
1067 // below --- as OpenEntry has already dropped the old entry for us.
1068 couldnt_conditionalize_request_ = true;
1069 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
1070 }
1071
1064 if (method_ == "PUT" || method_ == "DELETE" || 1072 if (method_ == "PUT" || method_ == "DELETE" ||
1065 (method_ == "HEAD" && mode_ == READ_WRITE)) { 1073 (method_ == "HEAD" && mode_ == READ_WRITE)) {
1066 DCHECK(mode_ == READ_WRITE || mode_ == WRITE || method_ == "HEAD"); 1074 DCHECK(mode_ == READ_WRITE || mode_ == WRITE || method_ == "HEAD");
1067 mode_ = NONE; 1075 mode_ = NONE;
1068 TransitionToState(STATE_SEND_REQUEST); 1076 TransitionToState(STATE_SEND_REQUEST);
1069 return OK; 1077 return OK;
1070 } 1078 }
1071 1079
1072 if (mode_ == READ_WRITE) { 1080 if (mode_ == READ_WRITE) {
1073 mode_ = WRITE; 1081 mode_ = WRITE;
(...skipping 1477 matching lines...) Expand 10 before | Expand all | Expand 10 after
2551 stale_entry_freshness_ = lifetimes.freshness; 2559 stale_entry_freshness_ = lifetimes.freshness;
2552 stale_entry_age_ = response_.headers->GetCurrentAge( 2560 stale_entry_age_ = response_.headers->GetCurrentAge(
2553 response_.request_time, response_.response_time, 2561 response_.request_time, response_.response_time,
2554 cache_->clock_->Now()); 2562 cache_->clock_->Now());
2555 } 2563 }
2556 } 2564 }
2557 2565
2558 return validation_required_by_headers; 2566 return validation_required_by_headers;
2559 } 2567 }
2560 2568
2569 bool HttpCache::Transaction::ResponseConditionalizable(
2570 std::string* etag_value,
2571 std::string* last_modified_value) {
2572 DCHECK(response_.headers.get());
2573
2574 // This only makes sense for cached 200 or 206 responses.
2575 if (response_.headers->response_code() != 200 &&
2576 response_.headers->response_code() != 206) {
2577 return false;
2578 }
2579
2580 // Just use the first available ETag and/or Last-Modified header value.
2581 // TODO(darin): Or should we use the last?
2582
2583 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1))
2584 response_.headers->EnumerateHeader(NULL, "etag", etag_value);
2585
2586 response_.headers->EnumerateHeader(NULL, "last-modified",
2587 last_modified_value);
2588
2589 if (etag_value->empty() && last_modified_value->empty())
2590 return false;
2591
2592 return true;
2593 }
2594
2561 bool HttpCache::Transaction::ConditionalizeRequest() { 2595 bool HttpCache::Transaction::ConditionalizeRequest() {
2562 DCHECK(response_.headers.get()); 2596 DCHECK(response_.headers.get());
2563 2597
2564 if (method_ == "PUT" || method_ == "DELETE") 2598 if (method_ == "PUT" || method_ == "DELETE")
2565 return false; 2599 return false;
2566 2600
2567 // This only makes sense for cached 200 or 206 responses. 2601 if (fail_conditionalization_for_test_)
2568 if (response_.headers->response_code() != 200 &&
2569 response_.headers->response_code() != 206) {
2570 return false; 2602 return false;
2571 }
2572 2603
2573 if (fail_conditionalization_for_test_) 2604 std::string etag_value;
2605 std::string last_modified_value;
2606 if (!ResponseConditionalizable(&etag_value, &last_modified_value))
2574 return false; 2607 return false;
2575 2608
2576 DCHECK(response_.headers->response_code() != 206 || 2609 DCHECK(response_.headers->response_code() != 206 ||
2577 response_.headers->HasStrongValidators()); 2610 response_.headers->HasStrongValidators());
2578 2611
2579 // Just use the first available ETag and/or Last-Modified header value. 2612 if (vary_mismatch_) {
2580 // TODO(darin): Or should we use the last? 2613 // Can't rely on last-modified if vary is different.
2581 2614 last_modified_value.clear();
2582 std::string etag_value; 2615 if (etag_value.empty())
2583 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) 2616 return false;
2584 response_.headers->EnumerateHeader(NULL, "etag", &etag_value);
2585
2586 std::string last_modified_value;
2587 if (!vary_mismatch_) {
2588 response_.headers->EnumerateHeader(NULL, "last-modified",
2589 &last_modified_value);
2590 } 2617 }
2591 2618
2592 if (etag_value.empty() && last_modified_value.empty())
2593 return false;
2594
2595 if (!partial_) { 2619 if (!partial_) {
2596 // Need to customize the request, so this forces us to allocate :( 2620 // Need to customize the request, so this forces us to allocate :(
2597 custom_request_.reset(new HttpRequestInfo(*request_)); 2621 custom_request_.reset(new HttpRequestInfo(*request_));
2598 request_ = custom_request_.get(); 2622 request_ = custom_request_.get();
2599 } 2623 }
2600 DCHECK(custom_request_.get()); 2624 DCHECK(custom_request_.get());
2601 2625
2602 bool use_if_range = 2626 bool use_if_range =
2603 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_; 2627 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_;
2604 2628
(...skipping 19 matching lines...) Expand all
2624 HttpRequestHeaders::kIfRange, last_modified_value); 2648 HttpRequestHeaders::kIfRange, last_modified_value);
2625 } else { 2649 } else {
2626 custom_request_->extra_headers.SetHeader( 2650 custom_request_->extra_headers.SetHeader(
2627 HttpRequestHeaders::kIfModifiedSince, last_modified_value); 2651 HttpRequestHeaders::kIfModifiedSince, last_modified_value);
2628 } 2652 }
2629 } 2653 }
2630 2654
2631 return true; 2655 return true;
2632 } 2656 }
2633 2657
2658 bool HttpCache::Transaction::MaybeRejectBasedOnEntryInMemoryData(
2659 uint8_t in_memory_info) {
2660 // Not going to be clever with those...
2661 if (partial_)
2662 return false;
2663
2664 // Unclear how to reconcile trying to avoid opening the entry with UPDATE's
2665 // semantics.
2666 if (mode_ == UPDATE)
2667 return false;
2668
2669 // If we are loading ignoring cache validity (aka back button), obviously
2670 // can't reject things based on it.
2671 if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION)
2672 return false;
2673
2674 // This is a prefetch resource that hasn't been used yet; those get a slight
2675 // loosening of caching rules.
2676 if (in_memory_info & HttpCache::HINT_UNUSED_SINCE_PREFETCH)
2677 return false;
2678
2679 // We need the entry to have zero lifetime to be able to tell it's expired
2680 // w/o reading full headers --- an expiration date is hard to fit into a few
2681 // bits.
2682 if (!(in_memory_info & HttpCache::HINT_ZERO_LIFETIME))
2683 return false;
2684
2685 // We also need to know that the entry can't be used for a conditional request
2686 // (e.g. perhaps because it has neither ETag nor Last-Modified).
2687 //
2688 // This could potentially be refined to look at the actual request, since
2689 // it may be unconditionalizable for reasons not captured in the hint.
2690 if (!(in_memory_info & HttpCache::HINT_RESPONSE_CANT_CONDITIONALIZE))
2691 return false;
2692
2693 return true;
2694 }
2695
2634 // We just received some headers from the server. We may have asked for a range, 2696 // We just received some headers from the server. We may have asked for a range,
2635 // in which case partial_ has an object. This could be the first network request 2697 // in which case partial_ has an object. This could be the first network request
2636 // we make to fulfill the original request, or we may be already reading (from 2698 // we make to fulfill the original request, or we may be already reading (from
2637 // the net and / or the cache). If we are not expecting a certain response, we 2699 // the net and / or the cache). If we are not expecting a certain response, we
2638 // just bypass the cache for this request (but again, maybe we are reading), and 2700 // just bypass the cache for this request (but again, maybe we are reading), and
2639 // delete partial_ (so we are not able to "fix" the headers that we return to 2701 // delete partial_ (so we are not able to "fix" the headers that we return to
2640 // the user). This results in either a weird response for the caller (we don't 2702 // the user). This results in either a weird response for the caller (we don't
2641 // expect it after all), or maybe a range that was not exactly what it was asked 2703 // expect it after all), or maybe a range that was not exactly what it was asked
2642 // for. 2704 // for.
2643 // 2705 //
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
2846 if (truncated) 2908 if (truncated)
2847 DCHECK_EQ(200, response_.headers->response_code()); 2909 DCHECK_EQ(200, response_.headers->response_code());
2848 2910
2849 // When writing headers, we normally only write the non-transient headers. 2911 // When writing headers, we normally only write the non-transient headers.
2850 bool skip_transient_headers = true; 2912 bool skip_transient_headers = true;
2851 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); 2913 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
2852 response_.Persist(data->pickle(), skip_transient_headers, truncated); 2914 response_.Persist(data->pickle(), skip_transient_headers, truncated);
2853 data->Done(); 2915 data->Done();
2854 2916
2855 io_buf_len_ = data->pickle()->size(); 2917 io_buf_len_ = data->pickle()->size();
2918
2919 // Summarize some info on cacheability in memory.
2920 uint8_t hints = 0;
2921 if (response_.headers->GetFreshnessLifetimes(response_.response_time)
2922 .freshness.is_zero())
2923 hints |= HttpCache::HINT_ZERO_LIFETIME;
2924 std::string etag_ignored, last_modified_ignored;
2925 if (!ResponseConditionalizable(&etag_ignored, &last_modified_ignored))
2926 hints |= HttpCache::HINT_RESPONSE_CANT_CONDITIONALIZE;
2927 if (response_.unused_since_prefetch)
2928 hints |= HttpCache::HINT_UNUSED_SINCE_PREFETCH;
2929 cache_->GetCurrentBackend()->SetEntryInMemoryData(cache_key_, hints);
2930
2856 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), 2931 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
2857 io_buf_len_, io_callback_, true); 2932 io_buf_len_, io_callback_, true);
2858 } 2933 }
2859 2934
2860 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { 2935 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
2861 if (!entry_) 2936 if (!entry_)
2862 return OK; 2937 return OK;
2863 if (net_log_.IsCapturing()) { 2938 if (net_log_.IsCapturing()) {
2864 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 2939 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
2865 result); 2940 result);
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
3252 } 3327 }
3253 3328
3254 void HttpCache::Transaction::TransitionToState(State state) { 3329 void HttpCache::Transaction::TransitionToState(State state) {
3255 // Ensure that the state is only set once per Do* state. 3330 // Ensure that the state is only set once per Do* state.
3256 DCHECK(in_do_loop_); 3331 DCHECK(in_do_loop_);
3257 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state; 3332 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state;
3258 next_state_ = state; 3333 next_state_ = state;
3259 } 3334 }
3260 3335
3261 } // namespace net 3336 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | net/http/http_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698