| 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 |