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 |