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" | 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |