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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 } | 166 } |
167 | 167 |
168 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6 | 168 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6 |
169 // a "non-error response" is one with a 2xx (Successful) or 3xx | 169 // a "non-error response" is one with a 2xx (Successful) or 3xx |
170 // (Redirection) status code. | 170 // (Redirection) status code. |
171 bool NonErrorResponse(int status_code) { | 171 bool NonErrorResponse(int status_code) { |
172 int status_code_range = status_code / 100; | 172 int status_code_range = status_code / 100; |
173 return status_code_range == 2 || status_code_range == 3; | 173 return status_code_range == 2 || status_code_range == 3; |
174 } | 174 } |
175 | 175 |
176 // Error codes that will be considered indicative of a page being offline/ | |
177 // unreachable for LOAD_FROM_CACHE_IF_OFFLINE. | |
178 bool IsOfflineError(int error) { | |
179 return ( | |
180 error == ERR_NAME_NOT_RESOLVED || error == ERR_INTERNET_DISCONNECTED || | |
181 error == ERR_ADDRESS_UNREACHABLE || error == ERR_CONNECTION_TIMED_OUT); | |
182 } | |
183 | |
184 // Enum for UMA, indicating the status (with regard to offline mode) of | |
185 // a particular request. | |
186 enum RequestOfflineStatus { | |
187 // A cache transaction hit in cache (data was present and not stale) | |
188 // and returned it. | |
189 OFFLINE_STATUS_FRESH_CACHE, | |
190 | |
191 // A network request was required for a cache entry, and it succeeded. | |
192 OFFLINE_STATUS_NETWORK_SUCCEEDED, | |
193 | |
194 // A network request was required for a cache entry, and it failed with | |
195 // a non-offline error. | |
196 OFFLINE_STATUS_NETWORK_FAILED, | |
197 | |
198 // A network request was required for a cache entry, it failed with an | |
199 // offline error, and we could serve stale data if | |
200 // LOAD_FROM_CACHE_IF_OFFLINE was set. | |
201 OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE, | |
202 | |
203 // A network request was required for a cache entry, it failed with | |
204 // an offline error, and there was no servable data in cache (even | |
205 // stale data). | |
206 OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE, | |
207 | |
208 OFFLINE_STATUS_MAX_ENTRIES | |
209 }; | |
210 | |
211 void RecordOfflineStatus(int load_flags, RequestOfflineStatus status) { | |
212 // Restrict to main frame to keep statistics close to | |
213 // "would have shown them something useful if offline mode was enabled". | |
214 if (load_flags & LOAD_MAIN_FRAME) { | |
215 UMA_HISTOGRAM_ENUMERATION("HttpCache.OfflineStatus", status, | |
216 OFFLINE_STATUS_MAX_ENTRIES); | |
217 } | |
218 } | |
219 | |
220 void RecordNoStoreHeaderHistogram(int load_flags, | 176 void RecordNoStoreHeaderHistogram(int load_flags, |
221 const HttpResponseInfo* response) { | 177 const HttpResponseInfo* response) { |
222 if (load_flags & LOAD_MAIN_FRAME) { | 178 if (load_flags & LOAD_MAIN_FRAME) { |
223 UMA_HISTOGRAM_BOOLEAN( | 179 UMA_HISTOGRAM_BOOLEAN( |
224 "Net.MainFrameNoStore", | 180 "Net.MainFrameNoStore", |
225 response->headers->HasHeaderValue("cache-control", "no-store")); | 181 response->headers->HasHeaderValue("cache-control", "no-store")); |
226 } | 182 } |
227 } | 183 } |
228 | 184 |
229 base::Value* NetLogAsyncRevalidationInfoCallback( | 185 base::Value* NetLogAsyncRevalidationInfoCallback( |
(...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 | 1064 |
1109 next_state_ = STATE_SEND_REQUEST_COMPLETE; | 1065 next_state_ = STATE_SEND_REQUEST_COMPLETE; |
1110 rv = network_trans_->Start(request_, io_callback_, net_log_); | 1066 rv = network_trans_->Start(request_, io_callback_, net_log_); |
1111 return rv; | 1067 return rv; |
1112 } | 1068 } |
1113 | 1069 |
1114 int HttpCache::Transaction::DoSendRequestComplete(int result) { | 1070 int HttpCache::Transaction::DoSendRequestComplete(int result) { |
1115 if (!cache_.get()) | 1071 if (!cache_.get()) |
1116 return ERR_UNEXPECTED; | 1072 return ERR_UNEXPECTED; |
1117 | 1073 |
1118 // If requested, and we have a readable cache entry, and we have | |
1119 // an error indicating that we're offline as opposed to in contact | |
1120 // with a bad server, read from cache anyway. | |
1121 if (IsOfflineError(result)) { | |
1122 if (mode_ == READ_WRITE && entry_ && !partial_) { | |
1123 RecordOfflineStatus(effective_load_flags_, | |
1124 OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE); | |
1125 if (effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) { | |
1126 UpdateTransactionPattern(PATTERN_NOT_COVERED); | |
1127 response_.server_data_unavailable = true; | |
1128 return SetupEntryForRead(); | |
1129 } | |
1130 } else { | |
1131 RecordOfflineStatus(effective_load_flags_, | |
1132 OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE); | |
1133 } | |
1134 } else { | |
1135 RecordOfflineStatus(effective_load_flags_, | |
1136 (result == OK ? OFFLINE_STATUS_NETWORK_SUCCEEDED : | |
1137 OFFLINE_STATUS_NETWORK_FAILED)); | |
1138 } | |
1139 | |
1140 // If we tried to conditionalize the request and failed, we know | 1074 // If we tried to conditionalize the request and failed, we know |
1141 // we won't be reading from the cache after this point. | 1075 // we won't be reading from the cache after this point. |
1142 if (couldnt_conditionalize_request_) | 1076 if (couldnt_conditionalize_request_) |
1143 mode_ = WRITE; | 1077 mode_ = WRITE; |
1144 | 1078 |
1145 if (result == OK) { | 1079 if (result == OK) { |
1146 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; | 1080 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; |
1147 return OK; | 1081 return OK; |
1148 } | 1082 } |
1149 | 1083 |
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2218 (!partial_->IsCurrentRangeCached() || invalid_range_)) { | 2152 (!partial_->IsCurrentRangeCached() || invalid_range_)) { |
2219 // Force revalidation for sparse or truncated entries. Note that we don't | 2153 // Force revalidation for sparse or truncated entries. Note that we don't |
2220 // want to ignore the regular validation logic just because a byte range was | 2154 // want to ignore the regular validation logic just because a byte range was |
2221 // part of the request. | 2155 // part of the request. |
2222 skip_validation = false; | 2156 skip_validation = false; |
2223 } | 2157 } |
2224 | 2158 |
2225 if (skip_validation) { | 2159 if (skip_validation) { |
2226 // TODO(ricea): Is this pattern okay for asynchronous revalidations? | 2160 // TODO(ricea): Is this pattern okay for asynchronous revalidations? |
2227 UpdateTransactionPattern(PATTERN_ENTRY_USED); | 2161 UpdateTransactionPattern(PATTERN_ENTRY_USED); |
2228 RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE); | |
2229 return SetupEntryForRead(); | 2162 return SetupEntryForRead(); |
2230 } else { | 2163 } else { |
2231 // Make the network request conditional, to see if we may reuse our cached | 2164 // Make the network request conditional, to see if we may reuse our cached |
2232 // response. If we cannot do so, then we just resort to a normal fetch. | 2165 // response. If we cannot do so, then we just resort to a normal fetch. |
2233 // Our mode remains READ_WRITE for a conditional request. Even if the | 2166 // Our mode remains READ_WRITE for a conditional request. Even if the |
2234 // conditionalization fails, we don't switch to WRITE mode until we | 2167 // conditionalization fails, we don't switch to WRITE mode until we |
2235 // know we won't be falling back to using the cache entry in the | 2168 // know we won't be falling back to using the cache entry in the |
2236 // LOAD_FROM_CACHE_IF_OFFLINE case. | 2169 // LOAD_FROM_CACHE_IF_OFFLINE case. |
2237 if (!ConditionalizeRequest()) { | 2170 if (!ConditionalizeRequest()) { |
2238 couldnt_conditionalize_request_ = true; | 2171 couldnt_conditionalize_request_ = true; |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3031 default: | 2964 default: |
3032 NOTREACHED(); | 2965 NOTREACHED(); |
3033 } | 2966 } |
3034 } | 2967 } |
3035 | 2968 |
3036 void HttpCache::Transaction::OnIOComplete(int result) { | 2969 void HttpCache::Transaction::OnIOComplete(int result) { |
3037 DoLoop(result); | 2970 DoLoop(result); |
3038 } | 2971 } |
3039 | 2972 |
3040 } // namespace net | 2973 } // namespace net |
OLD | NEW |