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 |