| 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(INFO) << "Invalid byte range found."; | 600 LOG(WARNING) << "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 // If the server is simply telling us that the resource has changed, we delete | 942 // For example, if the original request is for 30KB and we have the last 20KB, |
| 943 // the cached entry and restart the request as the caller intended (by returning | 943 // we ask the server for the first 10KB. If the resourse has changed, we'll |
| 944 // false from this method). However, we may not be able to do that at any point, | 944 // end up forwarding the 200 back to the user (so far so good). However, if |
| 945 // for instance if we already returned the headers to the user. | 945 // we have instead the first 10KB, we end up sending back a byte range response |
| 946 // | 946 // for the first 10KB, because we never asked the server for the last part. It's |
| 947 // WARNING: Whenever this code returns false, it has to make sure that the next | 947 // just too complicated to restart the whole request from this point; and of |
| 948 // time it is called it will return true so that we don't keep retrying the | 948 // course, maybe we already returned the headers. |
| 949 // request. | |
| 950 bool HttpCache::Transaction::ValidatePartialResponse( | 949 bool HttpCache::Transaction::ValidatePartialResponse( |
| 951 const HttpResponseHeaders* headers, bool* partial_content) { | 950 const HttpResponseHeaders* headers) { |
| 952 int response_code = headers->response_code(); | 951 int response_code = headers->response_code(); |
| 953 bool partial_response = enable_range_support_ ? response_code == 206 : false; | 952 bool partial_content = enable_range_support_ ? response_code == 206 : false; |
| 954 *partial_content = false; | |
| 955 | 953 |
| 956 if (!entry_) | 954 if (!entry_) |
| 957 return true; | 955 return false; |
| 958 | 956 |
| 959 if (invalid_range_) { | 957 if (invalid_range_) { |
| 960 // We gave up trying to match this request with the stored data. If the | 958 // We gave up trying to match this request with the stored data. If the |
| 961 // server is ok with the request, delete the entry, otherwise just ignore | 959 // server is ok with the request, delete the entry, otherwise just ignore |
| 962 // this request | 960 // this request |
| 963 if (partial_response || response_code == 200 || response_code == 304) { | 961 if (partial_content || response_code == 200 || response_code == 304) { |
| 964 DoomPartialEntry(true); | 962 DoomPartialEntry(true); |
| 965 mode_ = NONE; | 963 mode_ = NONE; |
| 966 } else { | 964 } else { |
| 967 IgnoreRangeRequest(); | 965 IgnoreRangeRequest(); |
| 968 } | 966 } |
| 969 return true; | 967 return false; |
| 970 } | 968 } |
| 971 | 969 |
| 972 if (!partial_.get()) { | 970 if (!partial_.get()) { |
| 973 // We are not expecting 206 but we may have one. | 971 // We are not expecting 206 but we may have one. |
| 974 if (partial_response) | 972 if (partial_content) |
| 975 IgnoreRangeRequest(); | 973 IgnoreRangeRequest(); |
| 976 | 974 |
| 977 return true; | 975 return false; |
| 978 } | 976 } |
| 979 | 977 |
| 980 // TODO(rvargas): Do we need to consider other results here?. | 978 // TODO(rvargas): Do we need to consider other results here?. |
| 981 bool failure = response_code == 200 || response_code == 416; | 979 bool failure = response_code == 200 || response_code == 416; |
| 982 | 980 |
| 983 if (partial_->IsCurrentRangeCached()) { | 981 if (partial_->IsCurrentRangeCached()) { |
| 984 // We asked for "If-None-Match: " so a 206 means a new object. | 982 // We asked for "If-None-Match: " so a 206 means a new object. |
| 985 if (partial_response) | 983 if (partial_content) |
| 986 failure = true; | 984 failure = true; |
| 987 | 985 |
| 988 if (response_code == 304 && partial_->ResponseHeadersOK(headers)) | 986 if (response_code == 304 && partial_->ResponseHeadersOK(headers)) |
| 989 return true; | 987 return false; |
| 990 } else { | 988 } else { |
| 991 // We asked for "If-Range: " so a 206 means just another range. | 989 // We asked for "If-Range: " so a 206 means just another range. |
| 992 if (partial_response && partial_->ResponseHeadersOK(headers)) { | 990 if (partial_content && partial_->ResponseHeadersOK(headers)) |
| 993 *partial_content = true; | |
| 994 return true; | 991 return true; |
| 995 } | |
| 996 | 992 |
| 997 // 304 is not expected here, but we'll spare the entry. | 993 // 304 is not expected here, but we'll spare the entry. |
| 998 } | 994 } |
| 999 | 995 |
| 1000 if (failure) { | 996 if (failure) { |
| 1001 // We cannot truncate this entry, it has to be deleted. | 997 // We cannot truncate this entry, it has to be deleted. |
| 1002 DoomPartialEntry(false); | 998 DoomPartialEntry(true); |
| 1003 mode_ = NONE; | 999 mode_ = NONE; |
| 1004 if (!reading_ && !partial_->IsLastRange()) { | 1000 return false; |
| 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 return false; | |
| 1010 } | |
| 1011 LOG(WARNING) << "Failed to revalidate partial entry"; | |
| 1012 partial_.reset(); | |
| 1013 return true; | |
| 1014 } | 1001 } |
| 1015 | 1002 |
| 1016 IgnoreRangeRequest(); | 1003 IgnoreRangeRequest(); |
| 1017 return true; | 1004 return false; |
| 1018 } | 1005 } |
| 1019 | 1006 |
| 1020 void HttpCache::Transaction::IgnoreRangeRequest() { | 1007 void HttpCache::Transaction::IgnoreRangeRequest() { |
| 1021 // We have a problem. We may or may not be reading already (in which case we | 1008 // We have a problem. We may or may not be reading already (in which case we |
| 1022 // returned the headers), but we'll just pretend that this request is not | 1009 // returned the headers), but we'll just pretend that this request is not |
| 1023 // using the cache and see what happens. Most likely this is the first | 1010 // using the cache and see what happens. Most likely this is the first |
| 1024 // response from the server (it's not changing its mind midway, right?). | 1011 // response from the server (it's not changing its mind midway, right?). |
| 1025 if (mode_ & WRITE) { | 1012 if (mode_ & WRITE) { |
| 1026 DoneWritingToEntry(mode_ != WRITE); | 1013 DoneWritingToEntry(mode_ != WRITE); |
| 1027 } else if (mode_ & READ && entry_) { | 1014 } else if (mode_ & READ && entry_) { |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 HandleResult(ERR_UNEXPECTED); | 1256 HandleResult(ERR_UNEXPECTED); |
| 1270 return; | 1257 return; |
| 1271 } | 1258 } |
| 1272 | 1259 |
| 1273 if (result == OK) { | 1260 if (result == OK) { |
| 1274 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); | 1261 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); |
| 1275 if (new_response->headers->response_code() == 401 || | 1262 if (new_response->headers->response_code() == 401 || |
| 1276 new_response->headers->response_code() == 407) { | 1263 new_response->headers->response_code() == 407) { |
| 1277 auth_response_ = *new_response; | 1264 auth_response_ = *new_response; |
| 1278 } else { | 1265 } else { |
| 1279 bool partial_content; | 1266 bool partial_content = ValidatePartialResponse(new_response->headers); |
| 1280 if (!ValidatePartialResponse(new_response->headers, &partial_content)) { | |
| 1281 // Something went wrong with this request and we have to restart it. | |
| 1282 network_trans_.reset(); | |
| 1283 BeginNetworkRequest(); | |
| 1284 return; | |
| 1285 } | |
| 1286 if (partial_content && mode_ == READ_WRITE && !truncated_ && | 1267 if (partial_content && mode_ == READ_WRITE && !truncated_ && |
| 1287 response_.headers->response_code() == 200) { | 1268 response_.headers->response_code() == 200) { |
| 1288 // We have stored the full entry, but it changed and the server is | 1269 // We have stored the full entry, but it changed and the server is |
| 1289 // sending a range. We have to delete the old entry. | 1270 // sending a range. We have to delete the old entry. |
| 1290 DoneWritingToEntry(false); | 1271 DoneWritingToEntry(false); |
| 1291 } | 1272 } |
| 1292 | 1273 |
| 1293 // Are we expecting a response to a conditional query? | 1274 // Are we expecting a response to a conditional query? |
| 1294 if (mode_ == READ_WRITE || mode_ == UPDATE) { | 1275 if (mode_ == READ_WRITE || mode_ == UPDATE) { |
| 1295 if (new_response->headers->response_code() == 304 || partial_content) { | 1276 if (new_response->headers->response_code() == 304 || partial_content) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 void HttpCache::Transaction::OnCacheWriteCompleted(int result) { | 1370 void HttpCache::Transaction::OnCacheWriteCompleted(int result) { |
| 1390 DoCacheWriteCompleted(result); | 1371 DoCacheWriteCompleted(result); |
| 1391 } | 1372 } |
| 1392 | 1373 |
| 1393 void HttpCache::Transaction::OnCacheEntryReady(int result) { | 1374 void HttpCache::Transaction::OnCacheEntryReady(int result) { |
| 1394 DCHECK_EQ(OK, result); | 1375 DCHECK_EQ(OK, result); |
| 1395 ValidateEntryHeadersAndContinue(true); | 1376 ValidateEntryHeadersAndContinue(true); |
| 1396 } | 1377 } |
| 1397 | 1378 |
| 1398 } // namespace net | 1379 } // namespace net |
| OLD | NEW |