| 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_transaction.h" | 5 #include "net/http/http_cache_transaction.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 | 8 |
| 9 #if defined(OS_POSIX) | 9 #if defined(OS_POSIX) |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| (...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 partial_.reset(new PartialData); | 590 partial_.reset(new PartialData); |
| 591 if (partial_->Init(request_->extra_headers)) { | 591 if (partial_->Init(request_->extra_headers)) { |
| 592 // We will be modifying the actual range requested to the server, so | 592 // We will be modifying the actual range requested to the server, so |
| 593 // let's remove the header here. | 593 // let's remove the header here. |
| 594 custom_request_.reset(new HttpRequestInfo(*request_)); | 594 custom_request_.reset(new HttpRequestInfo(*request_)); |
| 595 request_ = custom_request_.get(); | 595 request_ = custom_request_.get(); |
| 596 custom_request_->extra_headers = new_extra_headers; | 596 custom_request_->extra_headers = new_extra_headers; |
| 597 partial_->SetHeaders(new_extra_headers); | 597 partial_->SetHeaders(new_extra_headers); |
| 598 } else { | 598 } else { |
| 599 // The range is invalid or we cannot handle it properly. | 599 // The range is invalid or we cannot handle it properly. |
| 600 LOG(WARNING) << "Invalid byte range found."; | 600 LOG(INFO) << "Invalid byte range found."; |
| 601 effective_load_flags_ |= LOAD_DISABLE_CACHE; | 601 effective_load_flags_ |= LOAD_DISABLE_CACHE; |
| 602 partial_.reset(NULL); | 602 partial_.reset(NULL); |
| 603 } | 603 } |
| 604 } | 604 } |
| 605 } | 605 } |
| 606 | 606 |
| 607 bool HttpCache::Transaction::ShouldPassThrough() { | 607 bool HttpCache::Transaction::ShouldPassThrough() { |
| 608 // We may have a null disk_cache if there is an error we cannot recover from, | 608 // We may have a null disk_cache if there is an error we cannot recover from, |
| 609 // like not enough disk space, or sharing violations. | 609 // like not enough disk space, or sharing violations. |
| 610 if (!cache_->disk_cache_.get()) | 610 if (!cache_->disk_cache_.get()) |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 if (!etag_value.empty()) { | 905 if (!etag_value.empty()) { |
| 906 if (partial_.get() && !partial_->IsCurrentRangeCached()) { | 906 if (partial_.get() && !partial_->IsCurrentRangeCached()) { |
| 907 // We don't want to switch to WRITE mode if we don't have this block of a | 907 // We don't want to switch to WRITE mode if we don't have this block of a |
| 908 // byte-range request because we may have other parts cached. | 908 // byte-range request because we may have other parts cached. |
| 909 custom_request_->extra_headers.append("If-Range: "); | 909 custom_request_->extra_headers.append("If-Range: "); |
| 910 } else { | 910 } else { |
| 911 custom_request_->extra_headers.append("If-None-Match: "); | 911 custom_request_->extra_headers.append("If-None-Match: "); |
| 912 } | 912 } |
| 913 custom_request_->extra_headers.append(etag_value); | 913 custom_request_->extra_headers.append(etag_value); |
| 914 custom_request_->extra_headers.append("\r\n"); | 914 custom_request_->extra_headers.append("\r\n"); |
| 915 if (partial_.get() && !partial_->IsCurrentRangeCached()) | 915 if (partial_.get() && partial_->IsCurrentRangeCached()) |
| 916 return true; | 916 return true; |
| 917 } | 917 } |
| 918 | 918 |
| 919 if (!last_modified_value.empty()) { | 919 if (!last_modified_value.empty()) { |
| 920 if (partial_.get() && !partial_->IsCurrentRangeCached()) { | 920 if (partial_.get() && !partial_->IsCurrentRangeCached()) { |
| 921 custom_request_->extra_headers.append("If-Range: "); | 921 custom_request_->extra_headers.append("If-Range: "); |
| 922 } else { | 922 } else { |
| 923 custom_request_->extra_headers.append("If-Modified-Since: "); | 923 custom_request_->extra_headers.append("If-Modified-Since: "); |
| 924 } | 924 } |
| 925 custom_request_->extra_headers.append(last_modified_value); | 925 custom_request_->extra_headers.append(last_modified_value); |
| 926 custom_request_->extra_headers.append("\r\n"); | 926 custom_request_->extra_headers.append("\r\n"); |
| 927 } | 927 } |
| 928 | 928 |
| 929 return true; | 929 return true; |
| 930 } | 930 } |
| 931 | 931 |
| 932 // We just received some headers from the server. We may have asked for a range, | 932 // We just received some headers from the server. We may have asked for a range, |
| 933 // in which case partial_ has an object. This could be the first network request | 933 // in which case partial_ has an object. This could be the first network request |
| 934 // we make to fulfill the original request, or we may be already reading (from | 934 // we make to fulfill the original request, or we may be already reading (from |
| 935 // the net and / or the cache). If we are not expecting a certain response, we | 935 // the net and / or the cache). If we are not expecting a certain response, we |
| 936 // just bypass the cache for this request (but again, maybe we are reading), and | 936 // just bypass the cache for this request (but again, maybe we are reading), and |
| 937 // delete partial_ (so we are not able to "fix" the headers that we return to | 937 // delete partial_ (so we are not able to "fix" the headers that we return to |
| 938 // the user). This results in either a weird response for the caller (we don't | 938 // the user). This results in either a weird response for the caller (we don't |
| 939 // expect it after all), or maybe a range that was not exactly what it was asked | 939 // expect it after all), or maybe a range that was not exactly what it was asked |
| 940 // for. | 940 // for. |
| 941 // | 941 // |
| 942 // For example, if the original request is for 30KB and we have the last 20KB, | 942 // If the server is simply telling us that the resource has changed, we delete |
| 943 // we ask the server for the first 10KB. If the resourse has changed, we'll | 943 // the cached entry and restart the request as the caller intended (by returning |
| 944 // end up forwarding the 200 back to the user (so far so good). However, if | 944 // false from this method). However, we may not be able to do that at any point, |
| 945 // we have instead the first 10KB, we end up sending back a byte range response | 945 // for instance if we already returned the headers to the user. |
| 946 // for the first 10KB, because we never asked the server for the last part. It's | 946 // |
| 947 // just too complicated to restart the whole request from this point; and of | 947 // WARNING: Whenever this code returns false, it has to make sure that the next |
| 948 // course, maybe we already returned the headers. | 948 // time it is called it will return true so that we don't keep retrying the |
| 949 // request. |
| 949 bool HttpCache::Transaction::ValidatePartialResponse( | 950 bool HttpCache::Transaction::ValidatePartialResponse( |
| 950 const HttpResponseHeaders* headers) { | 951 const HttpResponseHeaders* headers, bool* partial_content) { |
| 951 int response_code = headers->response_code(); | 952 int response_code = headers->response_code(); |
| 952 bool partial_content = enable_range_support_ ? response_code == 206 : false; | 953 bool partial_response = enable_range_support_ ? response_code == 206 : false; |
| 954 *partial_content = false; |
| 953 | 955 |
| 954 if (!entry_) | 956 if (!entry_) |
| 955 return false; | 957 return true; |
| 956 | 958 |
| 957 if (invalid_range_) { | 959 if (invalid_range_) { |
| 958 // We gave up trying to match this request with the stored data. If the | 960 // We gave up trying to match this request with the stored data. If the |
| 959 // server is ok with the request, delete the entry, otherwise just ignore | 961 // server is ok with the request, delete the entry, otherwise just ignore |
| 960 // this request | 962 // this request |
| 961 if (partial_content || response_code == 200 || response_code == 304) { | 963 if (partial_response || response_code == 200 || response_code == 304) { |
| 962 DoomPartialEntry(true); | 964 DoomPartialEntry(true); |
| 963 mode_ = NONE; | 965 mode_ = NONE; |
| 964 } else { | 966 } else { |
| 965 IgnoreRangeRequest(); | 967 IgnoreRangeRequest(); |
| 966 } | 968 } |
| 967 return false; | 969 return true; |
| 968 } | 970 } |
| 969 | 971 |
| 970 if (!partial_.get()) { | 972 if (!partial_.get()) { |
| 971 // We are not expecting 206 but we may have one. | 973 // We are not expecting 206 but we may have one. |
| 972 if (partial_content) | 974 if (partial_response) |
| 973 IgnoreRangeRequest(); | 975 IgnoreRangeRequest(); |
| 974 | 976 |
| 975 return false; | 977 return true; |
| 976 } | 978 } |
| 977 | 979 |
| 978 // TODO(rvargas): Do we need to consider other results here?. | 980 // TODO(rvargas): Do we need to consider other results here?. |
| 979 bool failure = response_code == 200 || response_code == 416; | 981 bool failure = response_code == 200 || response_code == 416; |
| 980 | 982 |
| 981 if (partial_->IsCurrentRangeCached()) { | 983 if (partial_->IsCurrentRangeCached()) { |
| 982 // We asked for "If-None-Match: " so a 206 means a new object. | 984 // We asked for "If-None-Match: " so a 206 means a new object. |
| 983 if (partial_content) | 985 if (partial_response) |
| 984 failure = true; | 986 failure = true; |
| 985 | 987 |
| 986 if (response_code == 304 && partial_->ResponseHeadersOK(headers)) | 988 if (response_code == 304 && partial_->ResponseHeadersOK(headers)) |
| 987 return false; | 989 return true; |
| 988 } else { | 990 } else { |
| 989 // We asked for "If-Range: " so a 206 means just another range. | 991 // We asked for "If-Range: " so a 206 means just another range. |
| 990 if (partial_content && partial_->ResponseHeadersOK(headers)) | 992 if (partial_response && partial_->ResponseHeadersOK(headers)) { |
| 993 *partial_content = true; |
| 991 return true; | 994 return true; |
| 995 } |
| 992 | 996 |
| 993 // 304 is not expected here, but we'll spare the entry. | 997 // 304 is not expected here, but we'll spare the entry. |
| 994 } | 998 } |
| 995 | 999 |
| 996 if (failure) { | 1000 if (failure) { |
| 997 // We cannot truncate this entry, it has to be deleted. | 1001 // We cannot truncate this entry, it has to be deleted. |
| 998 DoomPartialEntry(true); | 1002 DoomPartialEntry(false); |
| 999 mode_ = NONE; | 1003 mode_ = NONE; |
| 1000 return false; | 1004 if (!reading_ && !partial_->IsLastRange()) { |
| 1005 // We'll attempt to issue another network request, this time without us |
| 1006 // messing up the headers. |
| 1007 partial_->RestoreHeaders(&custom_request_->extra_headers); |
| 1008 partial_.reset(); |
| 1009 truncated_ = false; |
| 1010 return false; |
| 1011 } |
| 1012 LOG(WARNING) << "Failed to revalidate partial entry"; |
| 1013 partial_.reset(); |
| 1014 return true; |
| 1001 } | 1015 } |
| 1002 | 1016 |
| 1003 IgnoreRangeRequest(); | 1017 IgnoreRangeRequest(); |
| 1004 return false; | 1018 return true; |
| 1005 } | 1019 } |
| 1006 | 1020 |
| 1007 void HttpCache::Transaction::IgnoreRangeRequest() { | 1021 void HttpCache::Transaction::IgnoreRangeRequest() { |
| 1008 // We have a problem. We may or may not be reading already (in which case we | 1022 // We have a problem. We may or may not be reading already (in which case we |
| 1009 // returned the headers), but we'll just pretend that this request is not | 1023 // returned the headers), but we'll just pretend that this request is not |
| 1010 // using the cache and see what happens. Most likely this is the first | 1024 // using the cache and see what happens. Most likely this is the first |
| 1011 // response from the server (it's not changing its mind midway, right?). | 1025 // response from the server (it's not changing its mind midway, right?). |
| 1012 if (mode_ & WRITE) { | 1026 if (mode_ & WRITE) { |
| 1013 DoneWritingToEntry(mode_ != WRITE); | 1027 DoneWritingToEntry(mode_ != WRITE); |
| 1014 } else if (mode_ & READ && entry_) { | 1028 } else if (mode_ & READ && entry_) { |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 HandleResult(ERR_UNEXPECTED); | 1270 HandleResult(ERR_UNEXPECTED); |
| 1257 return; | 1271 return; |
| 1258 } | 1272 } |
| 1259 | 1273 |
| 1260 if (result == OK) { | 1274 if (result == OK) { |
| 1261 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); | 1275 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); |
| 1262 if (new_response->headers->response_code() == 401 || | 1276 if (new_response->headers->response_code() == 401 || |
| 1263 new_response->headers->response_code() == 407) { | 1277 new_response->headers->response_code() == 407) { |
| 1264 auth_response_ = *new_response; | 1278 auth_response_ = *new_response; |
| 1265 } else { | 1279 } else { |
| 1266 bool partial_content = ValidatePartialResponse(new_response->headers); | 1280 bool partial_content; |
| 1281 if (!ValidatePartialResponse(new_response->headers, &partial_content) && |
| 1282 !auth_response_.headers && callback_) { |
| 1283 // Something went wrong with this request and we have to restart it. |
| 1284 // If there is no callback we'll return OK to the caller so we cannot |
| 1285 // restart the request. If we have an authentication response, we are |
| 1286 // exposed to weird things hapenning if the user cancels the |
| 1287 // authentication before we receive the new response. |
| 1288 network_trans_.reset(); |
| 1289 response_ = HttpResponseInfo(); |
| 1290 BeginNetworkRequest(); |
| 1291 return; |
| 1292 } |
| 1267 if (partial_content && mode_ == READ_WRITE && !truncated_ && | 1293 if (partial_content && mode_ == READ_WRITE && !truncated_ && |
| 1268 response_.headers->response_code() == 200) { | 1294 response_.headers->response_code() == 200) { |
| 1269 // We have stored the full entry, but it changed and the server is | 1295 // We have stored the full entry, but it changed and the server is |
| 1270 // sending a range. We have to delete the old entry. | 1296 // sending a range. We have to delete the old entry. |
| 1271 DoneWritingToEntry(false); | 1297 DoneWritingToEntry(false); |
| 1272 } | 1298 } |
| 1273 | 1299 |
| 1274 // Are we expecting a response to a conditional query? | 1300 // Are we expecting a response to a conditional query? |
| 1275 if (mode_ == READ_WRITE || mode_ == UPDATE) { | 1301 if (mode_ == READ_WRITE || mode_ == UPDATE) { |
| 1276 if (new_response->headers->response_code() == 304 || partial_content) { | 1302 if (new_response->headers->response_code() == 304 || partial_content) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1370 void HttpCache::Transaction::OnCacheWriteCompleted(int result) { | 1396 void HttpCache::Transaction::OnCacheWriteCompleted(int result) { |
| 1371 DoCacheWriteCompleted(result); | 1397 DoCacheWriteCompleted(result); |
| 1372 } | 1398 } |
| 1373 | 1399 |
| 1374 void HttpCache::Transaction::OnCacheEntryReady(int result) { | 1400 void HttpCache::Transaction::OnCacheEntryReady(int result) { |
| 1375 DCHECK_EQ(OK, result); | 1401 DCHECK_EQ(OK, result); |
| 1376 ValidateEntryHeadersAndContinue(true); | 1402 ValidateEntryHeadersAndContinue(true); |
| 1377 } | 1403 } |
| 1378 | 1404 |
| 1379 } // namespace net | 1405 } // namespace net |
| OLD | NEW |