| 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 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 const char* related_response_header_name; | 64 const char* related_response_header_name; |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 static const ValidationHeaderInfo kValidationHeaders[] = { | 67 static const ValidationHeaderInfo kValidationHeaders[] = { |
| 68 { "if-modified-since", "last-modified" }, | 68 { "if-modified-since", "last-modified" }, |
| 69 { "if-none-match", "etag" }, | 69 { "if-none-match", "etag" }, |
| 70 }; | 70 }; |
| 71 | 71 |
| 72 // Helper struct to pair a header name with its value, for | 72 // Helper struct to pair a header name with its value, for |
| 73 // headers used to validate cache entries. | 73 // headers used to validate cache entries. |
| 74 struct ValidationHeader { | 74 struct ValidationHeaders { |
| 75 enum {kInvalidIndex = -1}; | 75 ValidationHeaders() : initialized(false) {} |
| 76 | 76 |
| 77 ValidationHeader() : type_index(kInvalidIndex) {} | 77 std::string values[ARRAYSIZE_UNSAFE(kValidationHeaders)]; |
| 78 | 78 bool initialized; |
| 79 bool initialized() const { | |
| 80 return type_index != kInvalidIndex; | |
| 81 } | |
| 82 | |
| 83 const ValidationHeaderInfo& type_info() { | |
| 84 DCHECK(initialized()); | |
| 85 return kValidationHeaders[type_index]; | |
| 86 } | |
| 87 | |
| 88 // Index into |kValidationHeaders|. | |
| 89 int type_index; | |
| 90 std::string value; | |
| 91 }; | 79 }; |
| 92 | 80 |
| 93 // If the request includes one of these request headers, then avoid reusing | 81 // If the request includes one of these request headers, then avoid reusing |
| 94 // our cached copy if any. | 82 // our cached copy if any. |
| 95 static const HeaderNameAndValue kForceFetchHeaders[] = { | 83 static const HeaderNameAndValue kForceFetchHeaders[] = { |
| 96 { "cache-control", "no-cache" }, | 84 { "cache-control", "no-cache" }, |
| 97 { "pragma", "no-cache" }, | 85 { "pragma", "no-cache" }, |
| 98 { NULL, NULL } | 86 { NULL, NULL } |
| 99 }; | 87 }; |
| 100 | 88 |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 // Called to signal completion of the cache's WriteData method: | 352 // Called to signal completion of the cache's WriteData method: |
| 365 void OnCacheWriteCompleted(int result); | 353 void OnCacheWriteCompleted(int result); |
| 366 | 354 |
| 367 // Called to signal completion of the cache entry's ReadyForSparseIO method: | 355 // Called to signal completion of the cache entry's ReadyForSparseIO method: |
| 368 void OnCacheEntryReady(int result); | 356 void OnCacheEntryReady(int result); |
| 369 | 357 |
| 370 scoped_refptr<LoadLog> load_log_; | 358 scoped_refptr<LoadLog> load_log_; |
| 371 const HttpRequestInfo* request_; | 359 const HttpRequestInfo* request_; |
| 372 scoped_ptr<HttpRequestInfo> custom_request_; | 360 scoped_ptr<HttpRequestInfo> custom_request_; |
| 373 // If extra_headers specified a "if-modified-since" or "if-none-match", | 361 // If extra_headers specified a "if-modified-since" or "if-none-match", |
| 374 // |external_validation_| contains the value of that header. | 362 // |external_validation_| contains the value of those headers. |
| 375 ValidationHeader external_validation_; | 363 ValidationHeaders external_validation_; |
| 376 base::WeakPtr<HttpCache> cache_; | 364 base::WeakPtr<HttpCache> cache_; |
| 377 HttpCache::ActiveEntry* entry_; | 365 HttpCache::ActiveEntry* entry_; |
| 378 scoped_ptr<HttpTransaction> network_trans_; | 366 scoped_ptr<HttpTransaction> network_trans_; |
| 379 CompletionCallback* callback_; // Consumer's callback. | 367 CompletionCallback* callback_; // Consumer's callback. |
| 380 HttpResponseInfo response_; | 368 HttpResponseInfo response_; |
| 381 HttpResponseInfo auth_response_; | 369 HttpResponseInfo auth_response_; |
| 382 std::string cache_key_; | 370 std::string cache_key_; |
| 383 Mode mode_; | 371 Mode mode_; |
| 384 bool reading_; // We are already reading. | 372 bool reading_; // We are already reading. |
| 385 bool invalid_range_; // We may bypass the cache for this request. | 373 bool invalid_range_; // We may bypass the cache for this request. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 // requested cache access mode | 439 // requested cache access mode |
| 452 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { | 440 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { |
| 453 mode_ = READ; | 441 mode_ = READ; |
| 454 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { | 442 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { |
| 455 mode_ = WRITE; | 443 mode_ = WRITE; |
| 456 } else { | 444 } else { |
| 457 mode_ = READ_WRITE; | 445 mode_ = READ_WRITE; |
| 458 } | 446 } |
| 459 | 447 |
| 460 // Downgrade to UPDATE if the request has been externally conditionalized. | 448 // Downgrade to UPDATE if the request has been externally conditionalized. |
| 461 if (external_validation_.initialized()) { | 449 if (external_validation_.initialized) { |
| 462 if (mode_ & WRITE) { | 450 if (mode_ & WRITE) { |
| 463 // Strip off the READ_DATA bit (and maybe add back a READ_META bit | 451 // Strip off the READ_DATA bit (and maybe add back a READ_META bit |
| 464 // in case READ was off). | 452 // in case READ was off). |
| 465 mode_ = UPDATE; | 453 mode_ = UPDATE; |
| 466 } else { | 454 } else { |
| 467 mode_ = NONE; | 455 mode_ = NONE; |
| 468 } | 456 } |
| 469 } | 457 } |
| 470 } | 458 } |
| 471 | 459 |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 const HeaderNameAndValue* search; | 780 const HeaderNameAndValue* search; |
| 793 int load_flag; | 781 int load_flag; |
| 794 } kSpecialHeaders[] = { | 782 } kSpecialHeaders[] = { |
| 795 { kPassThroughHeaders, LOAD_DISABLE_CACHE }, | 783 { kPassThroughHeaders, LOAD_DISABLE_CACHE }, |
| 796 { kForceFetchHeaders, LOAD_BYPASS_CACHE }, | 784 { kForceFetchHeaders, LOAD_BYPASS_CACHE }, |
| 797 { kForceValidateHeaders, LOAD_VALIDATE_CACHE }, | 785 { kForceValidateHeaders, LOAD_VALIDATE_CACHE }, |
| 798 }; | 786 }; |
| 799 | 787 |
| 800 std::string new_extra_headers; | 788 std::string new_extra_headers; |
| 801 bool range_found = false; | 789 bool range_found = false; |
| 802 | 790 bool external_validation_error = false; |
| 803 // We will scan through the headers to see if any "if-modified-since" or | |
| 804 // "if-none-match" request headers were specified as part of extra_headers. | |
| 805 int num_validation_headers = 0; | |
| 806 ValidationHeader validation_header; | |
| 807 | 791 |
| 808 // scan request headers to see if we have any that would impact our load flags | 792 // scan request headers to see if we have any that would impact our load flags |
| 809 HttpUtil::HeadersIterator it(request_->extra_headers.begin(), | 793 HttpUtil::HeadersIterator it(request_->extra_headers.begin(), |
| 810 request_->extra_headers.end(), | 794 request_->extra_headers.end(), |
| 811 "\r\n"); | 795 "\r\n"); |
| 812 while (it.GetNext()) { | 796 while (it.GetNext()) { |
| 813 if (!LowerCaseEqualsASCII(it.name(), "range")) { | 797 if (!LowerCaseEqualsASCII(it.name(), "range")) { |
| 814 new_extra_headers.append(it.name_begin(), it.values_end()); | 798 new_extra_headers.append(it.name_begin(), it.values_end()); |
| 815 new_extra_headers.append("\r\n"); | 799 new_extra_headers.append("\r\n"); |
| 816 } else { | 800 } else { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 827 break; | 811 break; |
| 828 } | 812 } |
| 829 } | 813 } |
| 830 | 814 |
| 831 // Check for conditionalization headers which may correspond with a | 815 // Check for conditionalization headers which may correspond with a |
| 832 // cache validation request. | 816 // cache validation request. |
| 833 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); ++i) { | 817 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); ++i) { |
| 834 const ValidationHeaderInfo& info = kValidationHeaders[i]; | 818 const ValidationHeaderInfo& info = kValidationHeaders[i]; |
| 835 if (LowerCaseEqualsASCII(it.name_begin(), it.name_end(), | 819 if (LowerCaseEqualsASCII(it.name_begin(), it.name_end(), |
| 836 info.request_header_name)) { | 820 info.request_header_name)) { |
| 837 num_validation_headers++; | 821 if (!external_validation_.values[i].empty() || it.values().empty()) |
| 838 validation_header.type_index = i; | 822 external_validation_error = true; |
| 839 validation_header.value = it.values(); | 823 external_validation_.values[i] = it.values(); |
| 824 external_validation_.initialized = true; |
| 840 break; | 825 break; |
| 841 } | 826 } |
| 842 } | 827 } |
| 843 } | 828 } |
| 844 | 829 |
| 845 // We don't support ranges and validation headers. | 830 // We don't support ranges and validation headers. |
| 846 if (range_found && num_validation_headers) { | 831 if (range_found && external_validation_.initialized) { |
| 847 LOG(WARNING) << "Byte ranges AND validation headers found."; | 832 LOG(WARNING) << "Byte ranges AND validation headers found."; |
| 848 effective_load_flags_ |= LOAD_DISABLE_CACHE; | 833 effective_load_flags_ |= LOAD_DISABLE_CACHE; |
| 849 } | 834 } |
| 850 | 835 |
| 836 // If there is more than one validation header, we can't treat this request as |
| 837 // a cache validation, since we don't know for sure which header the server |
| 838 // will give us a response for (and they could be contradictory). |
| 839 if (external_validation_error) { |
| 840 LOG(WARNING) << "Multiple or malformed validation headers found."; |
| 841 effective_load_flags_ |= LOAD_DISABLE_CACHE; |
| 842 } |
| 843 |
| 851 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { | 844 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { |
| 852 partial_.reset(new PartialData); | 845 partial_.reset(new PartialData); |
| 853 if (partial_->Init(request_->extra_headers, new_extra_headers)) { | 846 if (partial_->Init(request_->extra_headers, new_extra_headers)) { |
| 854 // We will be modifying the actual range requested to the server, so | 847 // We will be modifying the actual range requested to the server, so |
| 855 // let's remove the header here. | 848 // let's remove the header here. |
| 856 custom_request_.reset(new HttpRequestInfo(*request_)); | 849 custom_request_.reset(new HttpRequestInfo(*request_)); |
| 857 request_ = custom_request_.get(); | 850 request_ = custom_request_.get(); |
| 858 custom_request_->extra_headers = new_extra_headers; | 851 custom_request_->extra_headers = new_extra_headers; |
| 859 } else { | 852 } else { |
| 860 // The range is invalid or we cannot handle it properly. | 853 // The range is invalid or we cannot handle it properly. |
| 861 LOG(WARNING) << "Invalid byte range found."; | 854 LOG(WARNING) << "Invalid byte range found."; |
| 862 effective_load_flags_ |= LOAD_DISABLE_CACHE; | 855 effective_load_flags_ |= LOAD_DISABLE_CACHE; |
| 863 partial_.reset(NULL); | 856 partial_.reset(NULL); |
| 864 } | 857 } |
| 865 } | 858 } |
| 866 | |
| 867 // If there is more than one validation header, we can't treat this request as | |
| 868 // a cache validation, since we don't know for sure which header the server | |
| 869 // will give us a response for (and they could be contradictory). | |
| 870 if (num_validation_headers > 1) { | |
| 871 LOG(WARNING) << "Multiple validation headers found."; | |
| 872 effective_load_flags_ |= LOAD_DISABLE_CACHE; | |
| 873 } | |
| 874 | |
| 875 if (num_validation_headers == 1) { | |
| 876 DCHECK(validation_header.initialized()); | |
| 877 external_validation_ = validation_header; | |
| 878 } | |
| 879 } | 859 } |
| 880 | 860 |
| 881 bool HttpCache::Transaction::ShouldPassThrough() { | 861 bool HttpCache::Transaction::ShouldPassThrough() { |
| 882 // We may have a null disk_cache if there is an error we cannot recover from, | 862 // We may have a null disk_cache if there is an error we cannot recover from, |
| 883 // like not enough disk space, or sharing violations. | 863 // like not enough disk space, or sharing violations. |
| 884 if (!cache_->disk_cache()) | 864 if (!cache_->disk_cache()) |
| 885 return true; | 865 return true; |
| 886 | 866 |
| 887 // When using the record/playback modes, we always use the cache | 867 // When using the record/playback modes, we always use the cache |
| 888 // and we never pass through. | 868 // and we never pass through. |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 if (rv < 0 && rv != ERR_IO_PENDING) | 1002 if (rv < 0 && rv != ERR_IO_PENDING) |
| 1023 HandleResult(rv); | 1003 HandleResult(rv); |
| 1024 return rv; | 1004 return rv; |
| 1025 } | 1005 } |
| 1026 | 1006 |
| 1027 return BeginCacheValidation(); | 1007 return BeginCacheValidation(); |
| 1028 } | 1008 } |
| 1029 | 1009 |
| 1030 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { | 1010 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { |
| 1031 DCHECK_EQ(UPDATE, mode_); | 1011 DCHECK_EQ(UPDATE, mode_); |
| 1032 DCHECK(external_validation_.initialized()); | 1012 DCHECK(external_validation_.initialized); |
| 1033 | 1013 |
| 1034 // Read the cached response. | 1014 // Read the cached response. |
| 1035 int rv = ReadResponseInfoFromEntry(); | 1015 int rv = ReadResponseInfoFromEntry(); |
| 1036 if (rv != OK) { | 1016 if (rv != OK) { |
| 1037 DCHECK(rv != ERR_IO_PENDING); | 1017 DCHECK(rv != ERR_IO_PENDING); |
| 1038 return HandleResult(rv); | 1018 return HandleResult(rv); |
| 1039 } | 1019 } |
| 1040 | 1020 |
| 1041 // Retrieve either the cached response's "etag" or "last-modified" header, | 1021 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); i++) { |
| 1042 // depending on which is applicable for the caller's request header. | 1022 if (external_validation_.values[i].empty()) |
| 1043 std::string validator; | 1023 continue; |
| 1044 response_.headers->EnumerateHeader( | 1024 // Retrieve either the cached response's "etag" or "last-modified" header. |
| 1045 NULL, | 1025 std::string validator; |
| 1046 external_validation_.type_info().related_response_header_name, | 1026 response_.headers->EnumerateHeader( |
| 1047 &validator); | 1027 NULL, |
| 1028 kValidationHeaders[i].related_response_header_name, |
| 1029 &validator); |
| 1048 | 1030 |
| 1049 if (response_.headers->response_code() != 200 || truncated_ || | 1031 if (response_.headers->response_code() != 200 || truncated_ || |
| 1050 validator.empty() || validator != external_validation_.value) { | 1032 validator.empty() || validator != external_validation_.values[i]) { |
| 1051 // The externally conditionalized request is not a validation request | 1033 // The externally conditionalized request is not a validation request |
| 1052 // for our existing cache entry. Proceed with caching disabled. | 1034 // for our existing cache entry. Proceed with caching disabled. |
| 1053 DoneWritingToEntry(true); | 1035 DoneWritingToEntry(true); |
| 1036 } |
| 1054 } | 1037 } |
| 1055 | 1038 |
| 1056 return BeginNetworkRequest(); | 1039 return BeginNetworkRequest(); |
| 1057 } | 1040 } |
| 1058 | 1041 |
| 1059 int HttpCache::Transaction::BeginNetworkRequest() { | 1042 int HttpCache::Transaction::BeginNetworkRequest() { |
| 1060 DCHECK(mode_ & WRITE || mode_ == NONE); | 1043 DCHECK(mode_ & WRITE || mode_ == NONE); |
| 1061 DCHECK(!network_trans_.get()); | 1044 DCHECK(!network_trans_.get()); |
| 1062 | 1045 |
| 1063 // Create a network transaction. | 1046 // Create a network transaction. |
| (...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2114 static_cast<net::HttpNetworkLayer*>(network_layer_.get()); | 2097 static_cast<net::HttpNetworkLayer*>(network_layer_.get()); |
| 2115 HttpNetworkSession* session = network->GetSession(); | 2098 HttpNetworkSession* session = network->GetSession(); |
| 2116 if (session) { | 2099 if (session) { |
| 2117 session->tcp_socket_pool()->CloseIdleSockets(); | 2100 session->tcp_socket_pool()->CloseIdleSockets(); |
| 2118 } | 2101 } |
| 2119 } | 2102 } |
| 2120 | 2103 |
| 2121 //----------------------------------------------------------------------------- | 2104 //----------------------------------------------------------------------------- |
| 2122 | 2105 |
| 2123 } // namespace net | 2106 } // namespace net |
| OLD | NEW |