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