OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "build/build_config.h" | 7 #include "build/build_config.h" |
8 | 8 |
9 #if defined(OS_POSIX) | 9 #if defined(OS_POSIX) |
10 #include <unistd.h> | 10 #include <unistd.h> |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 target_state_(STATE_NONE), | 139 target_state_(STATE_NONE), |
140 reading_(false), | 140 reading_(false), |
141 invalid_range_(false), | 141 invalid_range_(false), |
142 truncated_(false), | 142 truncated_(false), |
143 is_sparse_(false), | 143 is_sparse_(false), |
144 range_requested_(false), | 144 range_requested_(false), |
145 handling_206_(false), | 145 handling_206_(false), |
146 cache_pending_(false), | 146 cache_pending_(false), |
147 done_reading_(false), | 147 done_reading_(false), |
148 vary_mismatch_(false), | 148 vary_mismatch_(false), |
| 149 couldnt_conditionalize_request_(false), |
149 io_buf_len_(0), | 150 io_buf_len_(0), |
150 read_offset_(0), | 151 read_offset_(0), |
151 effective_load_flags_(0), | 152 effective_load_flags_(0), |
152 write_len_(0), | 153 write_len_(0), |
153 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 154 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
154 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( | 155 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( |
155 base::Bind(&Transaction::OnIOComplete, | 156 base::Bind(&Transaction::OnIOComplete, |
156 weak_factory_.GetWeakPtr()))), | 157 weak_factory_.GetWeakPtr()))), |
157 transaction_pattern_(PATTERN_UNDEFINED), | 158 transaction_pattern_(PATTERN_UNDEFINED), |
158 bytes_read_from_cache_(0), | 159 bytes_read_from_cache_(0), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 } | 194 } |
194 } | 195 } |
195 | 196 |
196 // Cancel any outstanding callbacks before we drop our reference to the | 197 // Cancel any outstanding callbacks before we drop our reference to the |
197 // HttpCache. This probably isn't strictly necessary, but might as well. | 198 // HttpCache. This probably isn't strictly necessary, but might as well. |
198 weak_factory_.InvalidateWeakPtrs(); | 199 weak_factory_.InvalidateWeakPtrs(); |
199 | 200 |
200 // We could still have a cache read or write in progress, so we just null the | 201 // We could still have a cache read or write in progress, so we just null the |
201 // cache_ pointer to signal that we are dead. See DoCacheReadCompleted. | 202 // cache_ pointer to signal that we are dead. See DoCacheReadCompleted. |
202 cache_.reset(); | 203 cache_.reset(); |
| 204 |
| 205 #if !defined(NDEBUG) |
| 206 // Dump the state transitions. |
| 207 DumpStatePath(); |
| 208 #endif |
203 } | 209 } |
204 | 210 |
205 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, | 211 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, |
206 const CompletionCallback& callback) { | 212 const CompletionCallback& callback) { |
207 DCHECK(buf); | 213 DCHECK(buf); |
208 DCHECK_GT(buf_len, 0); | 214 DCHECK_GT(buf_len, 0); |
209 DCHECK(!callback.is_null()); | 215 DCHECK(!callback.is_null()); |
210 if (!cache_ || !entry_) | 216 if (!cache_ || !entry_) |
211 return ERR_UNEXPECTED; | 217 return ERR_UNEXPECTED; |
212 | 218 |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 // | 562 // |
557 // Read() 3: | 563 // Read() 3: |
558 // CacheReadData* -> StartPartialCacheValidation -> | 564 // CacheReadData* -> StartPartialCacheValidation -> |
559 // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* -> | 565 // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* -> |
560 // SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse | 566 // SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse |
561 // -> PartialHeadersReceived -> NetworkRead* -> CacheWriteData* | 567 // -> PartialHeadersReceived -> NetworkRead* -> CacheWriteData* |
562 // | 568 // |
563 int HttpCache::Transaction::DoLoop(int result) { | 569 int HttpCache::Transaction::DoLoop(int result) { |
564 DCHECK(next_state_ != STATE_NONE); | 570 DCHECK(next_state_ != STATE_NONE); |
565 | 571 |
| 572 |
566 int rv = result; | 573 int rv = result; |
567 do { | 574 do { |
| 575 state_path_.push_back(next_state_); |
| 576 |
568 State state = next_state_; | 577 State state = next_state_; |
569 next_state_ = STATE_NONE; | 578 next_state_ = STATE_NONE; |
570 switch (state) { | 579 switch (state) { |
571 case STATE_GET_BACKEND: | 580 case STATE_GET_BACKEND: |
572 DCHECK_EQ(OK, rv); | 581 DCHECK_EQ(OK, rv); |
573 rv = DoGetBackend(); | 582 rv = DoGetBackend(); |
574 break; | 583 break; |
575 case STATE_GET_BACKEND_COMPLETE: | 584 case STATE_GET_BACKEND_COMPLETE: |
576 rv = DoGetBackendComplete(rv); | 585 rv = DoGetBackendComplete(rv); |
577 break; | 586 break; |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 rv = network_trans_->Start(request_, io_callback_, net_log_); | 813 rv = network_trans_->Start(request_, io_callback_, net_log_); |
805 return rv; | 814 return rv; |
806 } | 815 } |
807 | 816 |
808 int HttpCache::Transaction::DoSendRequestComplete(int result) { | 817 int HttpCache::Transaction::DoSendRequestComplete(int result) { |
809 ReportNetworkActionFinish(); | 818 ReportNetworkActionFinish(); |
810 | 819 |
811 if (!cache_) | 820 if (!cache_) |
812 return ERR_UNEXPECTED; | 821 return ERR_UNEXPECTED; |
813 | 822 |
| 823 // If requested, and we have a readable cache entry, and we have |
| 824 // an error indicating that we're offline as opposed to in contact |
| 825 // with a bad server, read from cache anyway. |
| 826 if (effective_load_flags_ & LOAD_CACHE_RETURN_IF_OFFLINE && |
| 827 mode_ == READ_WRITE && entry_ && !partial_ && result != OK) { |
| 828 switch (result) { |
| 829 // Errors that mean we didn't have a connection to the host. |
| 830 // Go ahead and read from the cache anyway. |
| 831 case ERR_NAME_NOT_RESOLVED: |
| 832 case ERR_INTERNET_DISCONNECTED: |
| 833 case ERR_ADDRESS_UNREACHABLE: |
| 834 case ERR_CONNECTION_TIMED_OUT: |
| 835 network_trans_.reset(); |
| 836 cache_->ConvertWriterToReader(entry_); |
| 837 mode_ = READ; |
| 838 |
| 839 // If there is metadata, read it. Otherwise, we're done. |
| 840 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) |
| 841 next_state_ = STATE_CACHE_READ_METADATA; |
| 842 return OK; |
| 843 default: |
| 844 break; |
| 845 } |
| 846 } |
| 847 |
| 848 // If we tried to conditionalize the request and failed, we know |
| 849 // we won't be reading from the cache after this point. |
| 850 if (couldnt_conditionalize_request_) |
| 851 mode_ = WRITE; |
| 852 |
814 if (result == OK) { | 853 if (result == OK) { |
815 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; | 854 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; |
816 return OK; | 855 return OK; |
817 } | 856 } |
818 | 857 |
819 // Do not record requests that have network errors or restarts. | 858 // Do not record requests that have network errors or restarts. |
820 UpdateTransactionPattern(PATTERN_NOT_COVERED); | 859 UpdateTransactionPattern(PATTERN_NOT_COVERED); |
821 if (IsCertificateError(result)) { | 860 if (IsCertificateError(result)) { |
822 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); | 861 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); |
823 // If we get a certificate error, then there is a certificate in ssl_info, | 862 // If we get a certificate error, then there is a certificate in ssl_info, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 | 929 |
891 if (mode_ != NONE && request_->method == "POST" && | 930 if (mode_ != NONE && request_->method == "POST" && |
892 NonErrorResponse(new_response->headers->response_code())) { | 931 NonErrorResponse(new_response->headers->response_code())) { |
893 cache_->DoomMainEntryForUrl(request_->url); | 932 cache_->DoomMainEntryForUrl(request_->url); |
894 } | 933 } |
895 | 934 |
896 // Are we expecting a response to a conditional query? | 935 // Are we expecting a response to a conditional query? |
897 if (mode_ == READ_WRITE || mode_ == UPDATE) { | 936 if (mode_ == READ_WRITE || mode_ == UPDATE) { |
898 if (new_response->headers->response_code() == 304 || handling_206_) { | 937 if (new_response->headers->response_code() == 304 || handling_206_) { |
899 UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED); | 938 UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED); |
| 939 // TODO(rdsmith): we just 304ed, so we have good data, but now we |
| 940 // are falling into this update state cos we want the new headers |
| 941 // and the freshness they can give us. |
900 next_state_ = STATE_UPDATE_CACHED_RESPONSE; | 942 next_state_ = STATE_UPDATE_CACHED_RESPONSE; |
901 return OK; | 943 return OK; |
902 } | 944 } |
903 UpdateTransactionPattern(PATTERN_ENTRY_UPDATED); | 945 UpdateTransactionPattern(PATTERN_ENTRY_UPDATED); |
904 mode_ = WRITE; | 946 mode_ = WRITE; |
905 } | 947 } |
906 | 948 |
907 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; | 949 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; |
908 return OK; | 950 return OK; |
909 } | 951 } |
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1784 mode_ = READ; | 1826 mode_ = READ; |
1785 | 1827 |
1786 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) | 1828 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) |
1787 next_state_ = STATE_CACHE_READ_METADATA; | 1829 next_state_ = STATE_CACHE_READ_METADATA; |
1788 } else { | 1830 } else { |
1789 // Make the network request conditional, to see if we may reuse our cached | 1831 // Make the network request conditional, to see if we may reuse our cached |
1790 // response. If we cannot do so, then we just resort to a normal fetch. | 1832 // response. If we cannot do so, then we just resort to a normal fetch. |
1791 // Our mode remains READ_WRITE for a conditional request. We'll switch to | 1833 // Our mode remains READ_WRITE for a conditional request. We'll switch to |
1792 // either READ or WRITE mode once we hear back from the server. | 1834 // either READ or WRITE mode once we hear back from the server. |
1793 if (!ConditionalizeRequest()) { | 1835 if (!ConditionalizeRequest()) { |
| 1836 couldnt_conditionalize_request_ = true; |
1794 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); | 1837 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); |
1795 if (partial_.get()) | 1838 if (partial_.get()) |
1796 return DoRestartPartialRequest(); | 1839 return DoRestartPartialRequest(); |
1797 | 1840 |
1798 DCHECK_NE(206, response_.headers->response_code()); | 1841 DCHECK_NE(206, response_.headers->response_code()); |
1799 mode_ = WRITE; | 1842 // We don't want to switch mode to WRITE here as in offline |
| 1843 // mode we may still need to read from the cache. Instead |
| 1844 // we record and test on whether we could conditionalize the |
| 1845 // request. |
1800 } | 1846 } |
1801 next_state_ = STATE_SEND_REQUEST; | 1847 next_state_ = STATE_SEND_REQUEST; |
1802 } | 1848 } |
1803 return OK; | 1849 return OK; |
1804 } | 1850 } |
1805 | 1851 |
1806 int HttpCache::Transaction::BeginPartialCacheValidation() { | 1852 int HttpCache::Transaction::BeginPartialCacheValidation() { |
1807 DCHECK(mode_ == READ_WRITE); | 1853 DCHECK(mode_ == READ_WRITE); |
1808 | 1854 |
1809 if (response_.headers->response_code() != 206 && !partial_.get() && | 1855 if (response_.headers->response_code() != 206 && !partial_.get() && |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2556 } | 2602 } |
2557 } | 2603 } |
2558 | 2604 |
2559 int HttpCache::Transaction::ResetCacheIOStart(int return_value) { | 2605 int HttpCache::Transaction::ResetCacheIOStart(int return_value) { |
2560 DCHECK(cache_io_start_.is_null()); | 2606 DCHECK(cache_io_start_.is_null()); |
2561 if (return_value == ERR_IO_PENDING) | 2607 if (return_value == ERR_IO_PENDING) |
2562 cache_io_start_ = base::TimeTicks::Now(); | 2608 cache_io_start_ = base::TimeTicks::Now(); |
2563 return return_value; | 2609 return return_value; |
2564 } | 2610 } |
2565 | 2611 |
| 2612 #if !defined(NDEBUG) |
| 2613 |
| 2614 // This list must be kept in sync with the HttpCache::Transaction::State enum. |
| 2615 |
| 2616 static const char *state_names[] = { |
| 2617 "NONE", |
| 2618 "GET_BACKEND", |
| 2619 "GET_BACKEND_COMPLETE", |
| 2620 "SEND_REQUEST", |
| 2621 "SEND_REQUEST_COMPLETE", |
| 2622 "SUCCESSFUL_SEND_REQUEST", |
| 2623 "NETWORK_READ", |
| 2624 "NETWORK_READ_COMPLETE", |
| 2625 "INIT_ENTRY", |
| 2626 "OPEN_ENTRY", |
| 2627 "OPEN_ENTRY_COMPLETE", |
| 2628 "CREATE_ENTRY", |
| 2629 "CREATE_ENTRY_COMPLETE", |
| 2630 "DOOM_ENTRY", |
| 2631 "DOOM_ENTRY_COMPLETE", |
| 2632 "ADD_TO_ENTRY", |
| 2633 "ADD_TO_ENTRY_COMPLETE", |
| 2634 "ADD_TO_ENTRY_COMPLETE_AFTER_DELAY", |
| 2635 "START_PARTIAL_CACHE_VALIDATION", |
| 2636 "COMPLETE_PARTIAL_CACHE_VALIDATION", |
| 2637 "UPDATE_CACHED_RESPONSE", |
| 2638 "UPDATE_CACHED_RESPONSE_COMPLETE", |
| 2639 "OVERWRITE_CACHED_RESPONSE", |
| 2640 "TRUNCATE_CACHED_DATA", |
| 2641 "TRUNCATE_CACHED_DATA_COMPLETE", |
| 2642 "TRUNCATE_CACHED_METADATA", |
| 2643 "TRUNCATE_CACHED_METADATA_COMPLETE", |
| 2644 "PARTIAL_HEADERS_RECEIVED", |
| 2645 "CACHE_READ_RESPONSE", |
| 2646 "CACHE_READ_RESPONSE_COMPLETE", |
| 2647 "CACHE_WRITE_RESPONSE", |
| 2648 "CACHE_WRITE_TRUNCATED_RESPONSE", |
| 2649 "CACHE_WRITE_RESPONSE_COMPLETE", |
| 2650 "CACHE_READ_METADATA", |
| 2651 "CACHE_READ_METADATA_COMPLETE", |
| 2652 "CACHE_QUERY_DATA", |
| 2653 "CACHE_QUERY_DATA_COMPLETE", |
| 2654 "CACHE_READ_DATA", |
| 2655 "CACHE_READ_DATA_COMPLETE", |
| 2656 "CACHE_WRITE_DATA", |
| 2657 "CACHE_WRITE_DATA_COMPLETE", |
| 2658 }; |
| 2659 |
| 2660 |
| 2661 void HttpCache::Transaction::DumpStatePath() { |
| 2662 std::string entry_path; |
| 2663 for (std::vector<int>::const_iterator it = state_path_.begin(); |
| 2664 it != state_path_.end(); ++it) { |
| 2665 if (it != state_path_.begin()) |
| 2666 entry_path += " -> "; |
| 2667 entry_path += state_names[*it]; |
| 2668 } |
| 2669 LOG(WARNING) << "Path state transitions for " << cache_key_ |
| 2670 << ": " << entry_path; |
| 2671 } |
| 2672 |
| 2673 #endif |
| 2674 |
2566 } // namespace net | 2675 } // namespace net |
OLD | NEW |