Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: net/http/http_cache_transaction.cc

Issue 12086021: Allow automatic use of stale cache entries if site is unreachable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed redirect behavior. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698