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

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

Issue 12310075: Cache failover to LOAD_PREFERRING_CACHE if network response suggests offline. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporated comments. Created 7 years, 9 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 | Annotate | Revision Log
« 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" 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>
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 namespace { 46 namespace {
47 47
48 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6 48 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
49 // a "non-error response" is one with a 2xx (Successful) or 3xx 49 // a "non-error response" is one with a 2xx (Successful) or 3xx
50 // (Redirection) status code. 50 // (Redirection) status code.
51 bool NonErrorResponse(int status_code) { 51 bool NonErrorResponse(int status_code) {
52 int status_code_range = status_code / 100; 52 int status_code_range = status_code / 100;
53 return status_code_range == 2 || status_code_range == 3; 53 return status_code_range == 2 || status_code_range == 3;
54 } 54 }
55 55
56 // Error codes that will be considered indicative of a page being offline/
57 // unreachable for LOAD_FROM_CACHE_IF_OFFLINE.
58 bool IsOfflineError(int error) {
59 return (error == net::ERR_NAME_NOT_RESOLVED ||
60 error == net::ERR_INTERNET_DISCONNECTED ||
61 error == net::ERR_ADDRESS_UNREACHABLE ||
62 error == net::ERR_CONNECTION_TIMED_OUT);
63 }
64
56 } // namespace 65 } // namespace
57 66
58 namespace net { 67 namespace net {
59 68
60 struct HeaderNameAndValue { 69 struct HeaderNameAndValue {
61 const char* name; 70 const char* name;
62 const char* value; 71 const char* value;
63 }; 72 };
64 73
65 // If the request includes one of these request headers, then avoid caching 74 // If the request includes one of these request headers, then avoid caching
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 target_state_(STATE_NONE), 144 target_state_(STATE_NONE),
136 reading_(false), 145 reading_(false),
137 invalid_range_(false), 146 invalid_range_(false),
138 truncated_(false), 147 truncated_(false),
139 is_sparse_(false), 148 is_sparse_(false),
140 range_requested_(false), 149 range_requested_(false),
141 handling_206_(false), 150 handling_206_(false),
142 cache_pending_(false), 151 cache_pending_(false),
143 done_reading_(false), 152 done_reading_(false),
144 vary_mismatch_(false), 153 vary_mismatch_(false),
154 couldnt_conditionalize_request_(false),
145 io_buf_len_(0), 155 io_buf_len_(0),
146 read_offset_(0), 156 read_offset_(0),
147 effective_load_flags_(0), 157 effective_load_flags_(0),
148 write_len_(0), 158 write_len_(0),
149 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 159 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
150 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( 160 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
151 base::Bind(&Transaction::OnIOComplete, 161 base::Bind(&Transaction::OnIOComplete,
152 weak_factory_.GetWeakPtr()))), 162 weak_factory_.GetWeakPtr()))),
153 transaction_pattern_(PATTERN_UNDEFINED), 163 transaction_pattern_(PATTERN_UNDEFINED),
154 defer_cache_sensitivity_delay_(false), 164 defer_cache_sensitivity_delay_(false),
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 rv = network_trans_->Start(request_, io_callback_, net_log_); 816 rv = network_trans_->Start(request_, io_callback_, net_log_);
807 return rv; 817 return rv;
808 } 818 }
809 819
810 int HttpCache::Transaction::DoSendRequestComplete(int result) { 820 int HttpCache::Transaction::DoSendRequestComplete(int result) {
811 ReportNetworkActionFinish(); 821 ReportNetworkActionFinish();
812 822
813 if (!cache_) 823 if (!cache_)
814 return ERR_UNEXPECTED; 824 return ERR_UNEXPECTED;
815 825
826 // If requested, and we have a readable cache entry, and we have
827 // an error indicating that we're offline as opposed to in contact
828 // with a bad server, read from cache anyway.
829 if ((effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) &&
830 IsOfflineError(result) && mode_ == READ_WRITE && entry_ && !partial_) {
831 UpdateTransactionPattern(PATTERN_NOT_COVERED);
832 response_.server_data_unavailable = true;
833 return SetupEntryForRead();
834 }
835
836 // If we tried to conditionalize the request and failed, we know
837 // we won't be reading from the cache after this point.
838 if (couldnt_conditionalize_request_)
839 mode_ = WRITE;
840
816 if (result == OK) { 841 if (result == OK) {
817 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; 842 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
818 return OK; 843 return OK;
819 } 844 }
820 845
821 // Do not record requests that have network errors or restarts. 846 // Do not record requests that have network errors or restarts.
822 UpdateTransactionPattern(PATTERN_NOT_COVERED); 847 UpdateTransactionPattern(PATTERN_NOT_COVERED);
823 if (IsCertificateError(result)) { 848 if (IsCertificateError(result)) {
824 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 849 const HttpResponseInfo* response = network_trans_->GetResponseInfo();
825 // If we get a certificate error, then there is a certificate in ssl_info, 850 // If we get a certificate error, then there is a certificate in ssl_info,
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after
1759 if (partial_.get() && (is_sparse_ || truncated_) && 1784 if (partial_.get() && (is_sparse_ || truncated_) &&
1760 (!partial_->IsCurrentRangeCached() || invalid_range_)) { 1785 (!partial_->IsCurrentRangeCached() || invalid_range_)) {
1761 // Force revalidation for sparse or truncated entries. Note that we don't 1786 // Force revalidation for sparse or truncated entries. Note that we don't
1762 // want to ignore the regular validation logic just because a byte range was 1787 // want to ignore the regular validation logic just because a byte range was
1763 // part of the request. 1788 // part of the request.
1764 skip_validation = false; 1789 skip_validation = false;
1765 } 1790 }
1766 1791
1767 if (skip_validation) { 1792 if (skip_validation) {
1768 UpdateTransactionPattern(PATTERN_ENTRY_USED); 1793 UpdateTransactionPattern(PATTERN_ENTRY_USED);
1769 if (partial_.get()) { 1794 return SetupEntryForRead();
1770 if (truncated_ || is_sparse_ || !invalid_range_) {
1771 // We are going to return the saved response headers to the caller, so
1772 // we may need to adjust them first.
1773 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1774 return OK;
1775 } else {
1776 partial_.reset();
1777 }
1778 }
1779 cache_->ConvertWriterToReader(entry_);
1780 mode_ = READ;
1781
1782 if (entry_->disk_entry->GetDataSize(kMetadataIndex))
1783 next_state_ = STATE_CACHE_READ_METADATA;
1784 } else { 1795 } else {
1785 // Make the network request conditional, to see if we may reuse our cached 1796 // Make the network request conditional, to see if we may reuse our cached
1786 // response. If we cannot do so, then we just resort to a normal fetch. 1797 // response. If we cannot do so, then we just resort to a normal fetch.
1787 // Our mode remains READ_WRITE for a conditional request. We'll switch to 1798 // Our mode remains READ_WRITE for a conditional request. Even if the
1788 // either READ or WRITE mode once we hear back from the server. 1799 // conditionalization fails, we don't switch to WRITE mode until we
1800 // know we won't be falling back to using the cache entry in the
1801 // LOAD_FROM_CACHE_IF_OFFLINE case.
1789 if (!ConditionalizeRequest()) { 1802 if (!ConditionalizeRequest()) {
1803 couldnt_conditionalize_request_ = true;
1790 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); 1804 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE);
1791 if (partial_.get()) 1805 if (partial_.get())
1792 return DoRestartPartialRequest(); 1806 return DoRestartPartialRequest();
1793 1807
1794 DCHECK_NE(206, response_.headers->response_code()); 1808 DCHECK_NE(206, response_.headers->response_code());
1795 mode_ = WRITE;
1796 } 1809 }
1797 next_state_ = STATE_SEND_REQUEST; 1810 next_state_ = STATE_SEND_REQUEST;
1798 } 1811 }
1799 return OK; 1812 return OK;
1800 } 1813 }
1801 1814
1802 int HttpCache::Transaction::BeginPartialCacheValidation() { 1815 int HttpCache::Transaction::BeginPartialCacheValidation() {
1803 DCHECK(mode_ == READ_WRITE); 1816 DCHECK(mode_ == READ_WRITE);
1804 1817
1805 if (response_.headers->response_code() != 206 && !partial_.get() && 1818 if (response_.headers->response_code() != 206 && !partial_.get() &&
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
2141 partial_.reset(NULL); 2154 partial_.reset(NULL);
2142 entry_ = NULL; 2155 entry_ = NULL;
2143 mode_ = NONE; 2156 mode_ = NONE;
2144 } 2157 }
2145 2158
2146 void HttpCache::Transaction::FailRangeRequest() { 2159 void HttpCache::Transaction::FailRangeRequest() {
2147 response_ = *new_response_; 2160 response_ = *new_response_;
2148 partial_->FixResponseHeaders(response_.headers, false); 2161 partial_->FixResponseHeaders(response_.headers, false);
2149 } 2162 }
2150 2163
2164 int HttpCache::Transaction::SetupEntryForRead() {
2165 network_trans_.reset();
2166 if (partial_.get()) {
2167 if (truncated_ || is_sparse_ || !invalid_range_) {
2168 // We are going to return the saved response headers to the caller, so
2169 // we may need to adjust them first.
2170 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
2171 return OK;
2172 } else {
2173 partial_.reset();
2174 }
2175 }
2176 cache_->ConvertWriterToReader(entry_);
2177 mode_ = READ;
2178
2179 if (entry_->disk_entry->GetDataSize(kMetadataIndex))
2180 next_state_ = STATE_CACHE_READ_METADATA;
2181 return OK;
2182 }
2183
2184
2151 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { 2185 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
2152 read_buf_ = data; 2186 read_buf_ = data;
2153 io_buf_len_ = data_len; 2187 io_buf_len_ = data_len;
2154 next_state_ = STATE_NETWORK_READ; 2188 next_state_ = STATE_NETWORK_READ;
2155 return DoLoop(OK); 2189 return DoLoop(OK);
2156 } 2190 }
2157 2191
2158 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { 2192 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) {
2159 read_buf_ = data; 2193 read_buf_ = data;
2160 io_buf_len_ = data_len; 2194 io_buf_len_ = data_len;
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
2576 entry_path += " -> "; 2610 entry_path += " -> ";
2577 entry_path += state_names[*it]; 2611 entry_path += state_names[*it];
2578 } 2612 }
2579 LOG(WARNING) << "Path state transitions for " << cache_key_ 2613 LOG(WARNING) << "Path state transitions for " << cache_key_
2580 << ": " << entry_path; 2614 << ": " << entry_path;
2581 } 2615 }
2582 2616
2583 #endif 2617 #endif
2584 2618
2585 } // namespace net 2619 } // 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