| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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.h" | 5 #include "net/http/http_cache.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 | 10 |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 int RestartNetworkRequestWithAuth(const std::wstring& username, | 302 int RestartNetworkRequestWithAuth(const std::wstring& username, |
| 303 const std::wstring& password); | 303 const std::wstring& password); |
| 304 | 304 |
| 305 // Called to determine if we need to validate the cache entry before using it. | 305 // Called to determine if we need to validate the cache entry before using it. |
| 306 bool RequiresValidation(); | 306 bool RequiresValidation(); |
| 307 | 307 |
| 308 // Called to make the request conditional (to ask the server if the cached | 308 // Called to make the request conditional (to ask the server if the cached |
| 309 // copy is valid). Returns true if able to make the request conditional. | 309 // copy is valid). Returns true if able to make the request conditional. |
| 310 bool ConditionalizeRequest(); | 310 bool ConditionalizeRequest(); |
| 311 | 311 |
| 312 // Makes sure that a 206 response is expected. Returns a network error code. |
| 313 bool ValidatePartialResponse(const HttpResponseHeaders* headers); |
| 314 |
| 312 // Reads data from the network. | 315 // Reads data from the network. |
| 313 int ReadFromNetwork(IOBuffer* data, int data_len); | 316 int ReadFromNetwork(IOBuffer* data, int data_len); |
| 314 | 317 |
| 315 // Reads data from the cache entry. | 318 // Reads data from the cache entry. |
| 316 int ReadFromEntry(IOBuffer* data, int data_len); | 319 int ReadFromEntry(IOBuffer* data, int data_len); |
| 317 | 320 |
| 318 // Called to populate response_ from the cache entry. | 321 // Called to populate response_ from the cache entry. |
| 319 int ReadResponseInfoFromEntry(); | 322 int ReadResponseInfoFromEntry(); |
| 320 | 323 |
| 321 // Called to write data to the cache entry. If the write fails, then the | 324 // Called to write data to the cache entry. If the write fails, then the |
| 322 // cache entry is destroyed. Future calls to this function will just do | 325 // cache entry is destroyed. Future calls to this function will just do |
| 323 // nothing without side-effect. | 326 // nothing without side-effect. |
| 324 void WriteToEntry(int index, int offset, IOBuffer* data, int data_len); | 327 void WriteToEntry(int index, int offset, IOBuffer* data, int data_len); |
| 325 | 328 |
| 326 // Called to write response_ to the cache entry. | 329 // Called to write response_ to the cache entry. |
| 327 void WriteResponseInfoToEntry(); | 330 void WriteResponseInfoToEntry(); |
| 328 | 331 |
| 329 // Called to truncate response content in the entry. | 332 // Called to truncate response content in the entry. |
| 330 void TruncateResponseData(); | 333 void TruncateResponseData(); |
| 331 | 334 |
| 332 // Called to append response data to the cache entry. | 335 // Called to append response data to the cache entry. |
| 333 void AppendResponseDataToEntry(IOBuffer* data, int data_len); | 336 void AppendResponseDataToEntry(IOBuffer* data, int data_len); |
| 334 | 337 |
| 335 // Called when we are done writing to the cache entry. | 338 // Called when we are done writing to the cache entry. |
| 336 void DoneWritingToEntry(bool success); | 339 void DoneWritingToEntry(bool success); |
| 337 | 340 |
| 341 // Deletes the current partial cache entry (sparse), and optionally removes |
| 342 // the control object (partial_). |
| 343 void DoomPartialEntry(bool delete_object); |
| 344 |
| 338 // Performs the needed work after receiving data from the network. | 345 // Performs the needed work after receiving data from the network. |
| 339 int DoNetworkReadCompleted(int result); | 346 int DoNetworkReadCompleted(int result); |
| 340 | 347 |
| 341 // Performs the needed work after receiving data from the network, when | 348 // Performs the needed work after receiving data from the network, when |
| 342 // working with range requests. | 349 // working with range requests. |
| 343 int DoPartialNetworkReadCompleted(int result); | 350 int DoPartialNetworkReadCompleted(int result); |
| 344 | 351 |
| 345 // Performs the needed work after receiving data from the cache. | 352 // Performs the needed work after receiving data from the cache. |
| 346 int DoCacheReadCompleted(int result); | 353 int DoCacheReadCompleted(int result); |
| 347 | 354 |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 791 partial_.reset(new PartialData); | 798 partial_.reset(new PartialData); |
| 792 if (partial_->Init(request_->extra_headers, new_extra_headers)) { | 799 if (partial_->Init(request_->extra_headers, new_extra_headers)) { |
| 793 // We will be modifying the actual range requested to the server, so | 800 // We will be modifying the actual range requested to the server, so |
| 794 // let's remove the header here. | 801 // let's remove the header here. |
| 795 custom_request_.reset(new HttpRequestInfo(*request_)); | 802 custom_request_.reset(new HttpRequestInfo(*request_)); |
| 796 request_ = custom_request_.get(); | 803 request_ = custom_request_.get(); |
| 797 custom_request_->extra_headers = new_extra_headers; | 804 custom_request_->extra_headers = new_extra_headers; |
| 798 } else { | 805 } else { |
| 799 // The range is invalid or we cannot handle it properly. | 806 // The range is invalid or we cannot handle it properly. |
| 800 effective_load_flags_ |= LOAD_DISABLE_CACHE; | 807 effective_load_flags_ |= LOAD_DISABLE_CACHE; |
| 808 partial_.reset(NULL); |
| 801 } | 809 } |
| 802 } | 810 } |
| 803 | 811 |
| 804 // If there is more than one validation header, we can't treat this request as | 812 // If there is more than one validation header, we can't treat this request as |
| 805 // a cache validation, since we don't know for sure which header the server | 813 // a cache validation, since we don't know for sure which header the server |
| 806 // will give us a response for (and they could be contradictory). | 814 // will give us a response for (and they could be contradictory). |
| 807 if (num_validation_headers > 1) { | 815 if (num_validation_headers > 1) { |
| 808 LOG(WARNING) << "Multiple validation headers found."; | 816 LOG(WARNING) << "Multiple validation headers found."; |
| 809 effective_load_flags_ |= LOAD_DISABLE_CACHE; | 817 effective_load_flags_ |= LOAD_DISABLE_CACHE; |
| 810 } | 818 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 return HandleResult(rv); | 884 return HandleResult(rv); |
| 877 } | 885 } |
| 878 | 886 |
| 879 if (response_.headers->response_code() != 206) | 887 if (response_.headers->response_code() != 206) |
| 880 return BeginCacheValidation(); | 888 return BeginCacheValidation(); |
| 881 | 889 |
| 882 #if !defined(ENABLE_RANGE_SUPPORT) | 890 #if !defined(ENABLE_RANGE_SUPPORT) |
| 883 return BeginCacheValidation(); | 891 return BeginCacheValidation(); |
| 884 #endif | 892 #endif |
| 885 | 893 |
| 886 if (!partial_.get()) { | 894 bool byte_range_requested = partial_.get() != NULL; |
| 895 if (!byte_range_requested) { |
| 887 // The request is not for a range, but we have stored just ranges. | 896 // The request is not for a range, but we have stored just ranges. |
| 888 // TODO(rvargas): Add support for this case. | 897 partial_.reset(new PartialData()); |
| 889 NOTREACHED(); | 898 if (!custom_request_.get()) { |
| 899 custom_request_.reset(new HttpRequestInfo(*request_)); |
| 900 request_ = custom_request_.get(); |
| 901 DCHECK(custom_request_->extra_headers.empty()); |
| 902 } |
| 890 } | 903 } |
| 891 | 904 |
| 892 if (!partial_->UpdateFromStoredHeaders(response_.headers)) { | 905 if (!partial_->UpdateFromStoredHeaders(response_.headers, |
| 893 // TODO(rvargas): Handle this error. | 906 entry_->disk_entry)) { |
| 894 NOTREACHED(); | 907 // The stored data cannot be used. Get rid of it and restart this request. |
| 908 DoomPartialEntry(!byte_range_requested); |
| 909 mode_ = WRITE; |
| 910 return AddToEntry(); |
| 895 } | 911 } |
| 896 | 912 |
| 897 return ContinuePartialCacheValidation(); | 913 return ContinuePartialCacheValidation(); |
| 898 } | 914 } |
| 899 | 915 |
| 900 int HttpCache::Transaction::ContinuePartialCacheValidation() { | 916 int HttpCache::Transaction::ContinuePartialCacheValidation() { |
| 901 DCHECK(mode_ == READ_WRITE); | 917 DCHECK(mode_ == READ_WRITE); |
| 902 // TODO(rvargas): Avoid re-validation of each cached piece. | |
| 903 | |
| 904 int rv = partial_->PrepareCacheValidation(entry_->disk_entry, | 918 int rv = partial_->PrepareCacheValidation(entry_->disk_entry, |
| 905 &custom_request_->extra_headers); | 919 &custom_request_->extra_headers); |
| 906 | 920 |
| 907 if (!rv) { | 921 if (!rv) { |
| 908 // Don't invoke the callback before telling the cache we're done. | 922 // Don't invoke the callback before telling the cache we're done. |
| 909 return rv; | 923 return rv; |
| 910 } | 924 } |
| 911 | 925 |
| 912 if (rv < 0) { | 926 if (rv < 0) { |
| 913 DCHECK(rv != ERR_IO_PENDING); | 927 DCHECK(rv != ERR_IO_PENDING); |
| 914 return HandleResult(rv); | 928 return HandleResult(rv); |
| 915 } | 929 } |
| 916 | 930 |
| 931 if (reading_ && partial_->IsCurrentRangeCached()) { |
| 932 rv = ReadFromEntry(read_buf_, read_buf_len_); |
| 933 |
| 934 // We are supposed to hanlde errors here. |
| 935 if (rv < 0 && rv != ERR_IO_PENDING) |
| 936 HandleResult(rv); |
| 937 return rv; |
| 938 } |
| 939 |
| 917 return BeginCacheValidation(); | 940 return BeginCacheValidation(); |
| 918 } | 941 } |
| 919 | 942 |
| 920 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { | 943 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { |
| 921 DCHECK_EQ(UPDATE, mode_); | 944 DCHECK_EQ(UPDATE, mode_); |
| 922 DCHECK(external_validation_.initialized()); | 945 DCHECK(external_validation_.initialized()); |
| 923 | 946 |
| 924 // Read the cached response. | 947 // Read the cached response. |
| 925 int rv = ReadResponseInfoFromEntry(); | 948 int rv = ReadResponseInfoFromEntry(); |
| 926 if (rv != OK) { | 949 if (rv != OK) { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 } else { | 1096 } else { |
| 1074 custom_request_->extra_headers.append("If-Modified-Since: "); | 1097 custom_request_->extra_headers.append("If-Modified-Since: "); |
| 1075 } | 1098 } |
| 1076 custom_request_->extra_headers.append(last_modified_value); | 1099 custom_request_->extra_headers.append(last_modified_value); |
| 1077 custom_request_->extra_headers.append("\r\n"); | 1100 custom_request_->extra_headers.append("\r\n"); |
| 1078 } | 1101 } |
| 1079 | 1102 |
| 1080 return true; | 1103 return true; |
| 1081 } | 1104 } |
| 1082 | 1105 |
| 1106 bool HttpCache::Transaction::ValidatePartialResponse( |
| 1107 const HttpResponseHeaders* headers) { |
| 1108 #ifdef ENABLE_RANGE_SUPPORT |
| 1109 bool partial_content = headers->response_code() == 206; |
| 1110 #else |
| 1111 bool partial_content = false; |
| 1112 #endif |
| 1113 |
| 1114 bool failure = false; |
| 1115 if (!partial_content) { |
| 1116 if (!partial_.get()) |
| 1117 return false; |
| 1118 |
| 1119 // TODO(rvargas): Do we need to consider other results here?. |
| 1120 if (headers->response_code() == 200 || headers->response_code() == 416) |
| 1121 failure = true; |
| 1122 |
| 1123 if (!reading_ && failure) { |
| 1124 // We are expecting 206 or 304 because we asked for a range. Given that |
| 1125 // the server is refusing the request we'll remove the sparse entry. |
| 1126 DoomPartialEntry(true); |
| 1127 mode_ = NONE; |
| 1128 return false; |
| 1129 } |
| 1130 } |
| 1131 |
| 1132 if (!failure && partial_.get() && partial_->ResponseHeadersOK(headers)) |
| 1133 return true; |
| 1134 |
| 1135 // We have a problem. We may or may not be reading already (in which case we |
| 1136 // returned the headers), but we'll just pretend that this request is not |
| 1137 // using the cache and see what happens. Most likely this is the first |
| 1138 // response from the server (it's not changing its mind midway, right?). |
| 1139 if (mode_ & WRITE) { |
| 1140 DoneWritingToEntry(mode_ != WRITE); |
| 1141 } else if (mode_ & READ && entry_) { |
| 1142 cache_->DoneReadingFromEntry(entry_, this); |
| 1143 } |
| 1144 |
| 1145 entry_ = NULL; |
| 1146 mode_ = NONE; |
| 1147 return false; |
| 1148 } |
| 1149 |
| 1083 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { | 1150 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { |
| 1084 int rv = network_trans_->Read(data, data_len, &network_read_callback_); | 1151 int rv = network_trans_->Read(data, data_len, &network_read_callback_); |
| 1085 read_buf_ = data; | 1152 read_buf_ = data; |
| 1086 read_buf_len_ = data_len; | 1153 read_buf_len_ = data_len; |
| 1087 if (rv >= 0) | 1154 if (rv >= 0) |
| 1088 rv = DoNetworkReadCompleted(rv); | 1155 rv = DoNetworkReadCompleted(rv); |
| 1089 return rv; | 1156 return rv; |
| 1090 } | 1157 } |
| 1091 | 1158 |
| 1092 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { | 1159 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 | 1257 |
| 1191 if (cache_->mode() == RECORD) | 1258 if (cache_->mode() == RECORD) |
| 1192 DLOG(INFO) << "Recorded: " << request_->method << request_->url | 1259 DLOG(INFO) << "Recorded: " << request_->method << request_->url |
| 1193 << " status: " << response_.headers->response_code(); | 1260 << " status: " << response_.headers->response_code(); |
| 1194 | 1261 |
| 1195 cache_->DoneWritingToEntry(entry_, success); | 1262 cache_->DoneWritingToEntry(entry_, success); |
| 1196 entry_ = NULL; | 1263 entry_ = NULL; |
| 1197 mode_ = NONE; // switch to 'pass through' mode | 1264 mode_ = NONE; // switch to 'pass through' mode |
| 1198 } | 1265 } |
| 1199 | 1266 |
| 1267 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { |
| 1268 cache_->DoneWithEntry(entry_, this); |
| 1269 cache_->DoomEntry(cache_key_); |
| 1270 entry_ = NULL; |
| 1271 if (delete_object) |
| 1272 partial_.reset(NULL); |
| 1273 } |
| 1274 |
| 1200 void HttpCache::Transaction::OnNetworkInfoAvailable(int result) { | 1275 void HttpCache::Transaction::OnNetworkInfoAvailable(int result) { |
| 1201 DCHECK(result != ERR_IO_PENDING); | 1276 DCHECK(result != ERR_IO_PENDING); |
| 1202 | 1277 |
| 1203 if (revoked()) { | 1278 if (revoked()) { |
| 1204 HandleResult(ERR_UNEXPECTED); | 1279 HandleResult(ERR_UNEXPECTED); |
| 1205 return; | 1280 return; |
| 1206 } | 1281 } |
| 1207 | 1282 |
| 1208 if (result == OK) { | 1283 if (result == OK) { |
| 1209 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); | 1284 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); |
| 1210 if (new_response->headers->response_code() == 401 || | 1285 if (new_response->headers->response_code() == 401 || |
| 1211 new_response->headers->response_code() == 407) { | 1286 new_response->headers->response_code() == 407) { |
| 1212 auth_response_ = *new_response; | 1287 auth_response_ = *new_response; |
| 1213 } else { | 1288 } else { |
| 1214 #ifdef ENABLE_RANGE_SUPPORT | 1289 bool partial_content = ValidatePartialResponse(new_response->headers); |
| 1215 bool partial_content = new_response->headers->response_code() == 206; | 1290 |
| 1216 #else | |
| 1217 bool partial_content = false; | |
| 1218 #endif | |
| 1219 // TODO(rvargas): Validate partial_content vs partial_ and mode_ | |
| 1220 if (partial_content) { | |
| 1221 DCHECK(partial_.get()); | |
| 1222 if (!partial_->ResponseHeadersOK(new_response->headers)) { | |
| 1223 // TODO(rvargas): Handle this error. | |
| 1224 NOTREACHED(); | |
| 1225 } | |
| 1226 } | |
| 1227 // Are we expecting a response to a conditional query? | 1291 // Are we expecting a response to a conditional query? |
| 1228 if (mode_ == READ_WRITE || mode_ == UPDATE) { | 1292 if (mode_ == READ_WRITE || mode_ == UPDATE) { |
| 1229 if (new_response->headers->response_code() == 304 || partial_content) { | 1293 if (new_response->headers->response_code() == 304 || partial_content) { |
| 1230 // Update cached response based on headers in new_response. | 1294 // Update cached response based on headers in new_response. |
| 1231 // TODO(wtc): should we update cached certificate | 1295 // TODO(wtc): should we update cached certificate |
| 1232 // (response_.ssl_info), too? | 1296 // (response_.ssl_info), too? |
| 1233 response_.headers->Update(*new_response->headers); | 1297 response_.headers->Update(*new_response->headers); |
| 1234 if (response_.headers->HasHeaderValue("cache-control", "no-store")) { | 1298 if (response_.headers->HasHeaderValue("cache-control", "no-store")) { |
| 1235 cache_->DoomEntry(cache_key_); | 1299 cache_->DoomEntry(cache_key_); |
| 1236 } else { | 1300 } else { |
| (...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1961 static_cast<net::HttpNetworkLayer*>(network_layer_.get()); | 2025 static_cast<net::HttpNetworkLayer*>(network_layer_.get()); |
| 1962 HttpNetworkSession* session = network->GetSession(); | 2026 HttpNetworkSession* session = network->GetSession(); |
| 1963 if (session) { | 2027 if (session) { |
| 1964 session->connection_pool()->CloseIdleSockets(); | 2028 session->connection_pool()->CloseIdleSockets(); |
| 1965 } | 2029 } |
| 1966 } | 2030 } |
| 1967 | 2031 |
| 1968 //----------------------------------------------------------------------------- | 2032 //----------------------------------------------------------------------------- |
| 1969 | 2033 |
| 1970 } // namespace net | 2034 } // namespace net |
| OLD | NEW |