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

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: Moved new flag to nearer other flags in same file. 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
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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 target_state_(STATE_NONE), 142 target_state_(STATE_NONE),
134 reading_(false), 143 reading_(false),
135 invalid_range_(false), 144 invalid_range_(false),
136 truncated_(false), 145 truncated_(false),
137 is_sparse_(false), 146 is_sparse_(false),
138 range_requested_(false), 147 range_requested_(false),
139 handling_206_(false), 148 handling_206_(false),
140 cache_pending_(false), 149 cache_pending_(false),
141 done_reading_(false), 150 done_reading_(false),
142 vary_mismatch_(false), 151 vary_mismatch_(false),
152 couldnt_conditionalize_request_(false),
143 io_buf_len_(0), 153 io_buf_len_(0),
144 read_offset_(0), 154 read_offset_(0),
145 effective_load_flags_(0), 155 effective_load_flags_(0),
146 write_len_(0), 156 write_len_(0),
147 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 157 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
148 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( 158 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
149 base::Bind(&Transaction::OnIOComplete, 159 base::Bind(&Transaction::OnIOComplete,
150 weak_factory_.GetWeakPtr()))), 160 weak_factory_.GetWeakPtr()))),
151 transaction_pattern_(PATTERN_UNDEFINED), 161 transaction_pattern_(PATTERN_UNDEFINED),
152 defer_cache_sensitivity_delay_(false), 162 defer_cache_sensitivity_delay_(false),
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 rv = network_trans_->Start(request_, io_callback_, net_log_); 813 rv = network_trans_->Start(request_, io_callback_, net_log_);
804 return rv; 814 return rv;
805 } 815 }
806 816
807 int HttpCache::Transaction::DoSendRequestComplete(int result) { 817 int HttpCache::Transaction::DoSendRequestComplete(int result) {
808 ReportNetworkActionFinish(); 818 ReportNetworkActionFinish();
809 819
810 if (!cache_) 820 if (!cache_)
811 return ERR_UNEXPECTED; 821 return ERR_UNEXPECTED;
812 822
823 // If requested, and we have a readable cache entry, and we have
824 // an error indicating that we're offline as opposed to in contact
825 // with a bad server, read from cache anyway.
826 if ((effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) &&
827 IsOfflineError(result) && mode_ == READ_WRITE && entry_ && !partial_) {
828 UpdateTransactionPattern(PATTERN_NOT_COVERED);
829 response_.server_data_unavailable = true;
830 return SetupEntryForRead();
831 }
832
833 // If we tried to conditionalize the request and failed, we know
834 // we won't be reading from the cache after this point.
835 if (couldnt_conditionalize_request_)
836 mode_ = WRITE;
837
813 if (result == OK) { 838 if (result == OK) {
814 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; 839 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
815 return OK; 840 return OK;
816 } 841 }
817 842
818 // Do not record requests that have network errors or restarts. 843 // Do not record requests that have network errors or restarts.
819 UpdateTransactionPattern(PATTERN_NOT_COVERED); 844 UpdateTransactionPattern(PATTERN_NOT_COVERED);
820 if (IsCertificateError(result)) { 845 if (IsCertificateError(result)) {
821 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 846 const HttpResponseInfo* response = network_trans_->GetResponseInfo();
822 // If we get a certificate error, then there is a certificate in ssl_info, 847 // 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
1756 if (partial_.get() && (is_sparse_ || truncated_) && 1781 if (partial_.get() && (is_sparse_ || truncated_) &&
1757 (!partial_->IsCurrentRangeCached() || invalid_range_)) { 1782 (!partial_->IsCurrentRangeCached() || invalid_range_)) {
1758 // Force revalidation for sparse or truncated entries. Note that we don't 1783 // Force revalidation for sparse or truncated entries. Note that we don't
1759 // want to ignore the regular validation logic just because a byte range was 1784 // want to ignore the regular validation logic just because a byte range was
1760 // part of the request. 1785 // part of the request.
1761 skip_validation = false; 1786 skip_validation = false;
1762 } 1787 }
1763 1788
1764 if (skip_validation) { 1789 if (skip_validation) {
1765 UpdateTransactionPattern(PATTERN_ENTRY_USED); 1790 UpdateTransactionPattern(PATTERN_ENTRY_USED);
1766 if (partial_.get()) { 1791 return SetupEntryForRead();
1767 if (truncated_ || is_sparse_ || !invalid_range_) {
1768 // We are going to return the saved response headers to the caller, so
1769 // we may need to adjust them first.
1770 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1771 return OK;
1772 } else {
1773 partial_.reset();
1774 }
1775 }
1776 cache_->ConvertWriterToReader(entry_);
1777 mode_ = READ;
1778
1779 if (entry_->disk_entry->GetDataSize(kMetadataIndex))
1780 next_state_ = STATE_CACHE_READ_METADATA;
1781 } else { 1792 } else {
1782 // Make the network request conditional, to see if we may reuse our cached 1793 // Make the network request conditional, to see if we may reuse our cached
1783 // response. If we cannot do so, then we just resort to a normal fetch. 1794 // response. If we cannot do so, then we just resort to a normal fetch.
1784 // Our mode remains READ_WRITE for a conditional request. We'll switch to 1795 // Our mode remains READ_WRITE for a conditional request. Even if the
1785 // either READ or WRITE mode once we hear back from the server. 1796 // conditionalization fails, we don't switch to WRITE mode until we
1797 // know we won't be falling back to using the cache entry in the
1798 // LOAD_FROM_CACHE_IF_OFFLINE case.
1786 if (!ConditionalizeRequest()) { 1799 if (!ConditionalizeRequest()) {
1800 couldnt_conditionalize_request_ = true;
1787 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); 1801 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE);
1788 if (partial_.get()) 1802 if (partial_.get())
1789 return DoRestartPartialRequest(); 1803 return DoRestartPartialRequest();
1790 1804
1791 DCHECK_NE(206, response_.headers->response_code()); 1805 DCHECK_NE(206, response_.headers->response_code());
1792 mode_ = WRITE;
1793 } 1806 }
1794 next_state_ = STATE_SEND_REQUEST; 1807 next_state_ = STATE_SEND_REQUEST;
1795 } 1808 }
1796 return OK; 1809 return OK;
1797 } 1810 }
1798 1811
1799 int HttpCache::Transaction::BeginPartialCacheValidation() { 1812 int HttpCache::Transaction::BeginPartialCacheValidation() {
1800 DCHECK(mode_ == READ_WRITE); 1813 DCHECK(mode_ == READ_WRITE);
1801 1814
1802 if (response_.headers->response_code() != 206 && !partial_.get() && 1815 if (response_.headers->response_code() != 206 && !partial_.get() &&
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
2138 partial_.reset(NULL); 2151 partial_.reset(NULL);
2139 entry_ = NULL; 2152 entry_ = NULL;
2140 mode_ = NONE; 2153 mode_ = NONE;
2141 } 2154 }
2142 2155
2143 void HttpCache::Transaction::FailRangeRequest() { 2156 void HttpCache::Transaction::FailRangeRequest() {
2144 response_ = *new_response_; 2157 response_ = *new_response_;
2145 partial_->FixResponseHeaders(response_.headers, false); 2158 partial_->FixResponseHeaders(response_.headers, false);
2146 } 2159 }
2147 2160
2161 int HttpCache::Transaction::SetupEntryForRead() {
2162 network_trans_.reset();
2163 if (partial_.get()) {
2164 if (truncated_ || is_sparse_ || !invalid_range_) {
2165 // We are going to return the saved response headers to the caller, so
2166 // we may need to adjust them first.
2167 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
2168 return OK;
2169 } else {
2170 partial_.reset();
2171 }
2172 }
2173 cache_->ConvertWriterToReader(entry_);
2174 mode_ = READ;
2175
2176 if (entry_->disk_entry->GetDataSize(kMetadataIndex))
2177 next_state_ = STATE_CACHE_READ_METADATA;
2178 return OK;
2179 }
2180
2181
2148 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { 2182 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
2149 read_buf_ = data; 2183 read_buf_ = data;
2150 io_buf_len_ = data_len; 2184 io_buf_len_ = data_len;
2151 next_state_ = STATE_NETWORK_READ; 2185 next_state_ = STATE_NETWORK_READ;
2152 return DoLoop(OK); 2186 return DoLoop(OK);
2153 } 2187 }
2154 2188
2155 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { 2189 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) {
2156 read_buf_ = data; 2190 read_buf_ = data;
2157 io_buf_len_ = data_len; 2191 io_buf_len_ = data_len;
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
2573 entry_path += " -> "; 2607 entry_path += " -> ";
2574 entry_path += state_names[*it]; 2608 entry_path += state_names[*it];
2575 } 2609 }
2576 LOG(WARNING) << "Path state transitions for " << cache_key_ 2610 LOG(WARNING) << "Path state transitions for " << cache_key_
2577 << ": " << entry_path; 2611 << ": " << entry_path;
2578 } 2612 }
2579 2613
2580 #endif 2614 #endif
2581 2615
2582 } // namespace net 2616 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698