Index: net/http/http_cache_transaction.cc |
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc |
index 3c9953930bcac27131eb50894d2fec174f78b26f..8d0c8d52acc4bf6a702e71a3158c914268641623 100644 |
--- a/net/http/http_cache_transaction.cc |
+++ b/net/http/http_cache_transaction.cc |
@@ -53,6 +53,15 @@ bool NonErrorResponse(int status_code) { |
return status_code_range == 2 || status_code_range == 3; |
} |
+// Error codes that will be considered indicative of a page being offline/ |
+// unreachable for LOAD_FROM_CACHE_IF_OFFLINE. |
+bool IsOfflineError(int error) { |
+ return (error == net::ERR_NAME_NOT_RESOLVED || |
+ error == net::ERR_INTERNET_DISCONNECTED || |
+ error == net::ERR_ADDRESS_UNREACHABLE || |
+ error == net::ERR_CONNECTION_TIMED_OUT); |
+} |
+ |
} // namespace |
namespace net { |
@@ -140,6 +149,7 @@ HttpCache::Transaction::Transaction( |
cache_pending_(false), |
done_reading_(false), |
vary_mismatch_(false), |
+ couldnt_conditionalize_request_(false), |
io_buf_len_(0), |
read_offset_(0), |
effective_load_flags_(0), |
@@ -810,6 +820,29 @@ int HttpCache::Transaction::DoSendRequestComplete(int result) { |
if (!cache_) |
return ERR_UNEXPECTED; |
+ // If requested, and we have a readable cache entry, and we have |
+ // an error indicating that we're offline as opposed to in contact |
+ // with a bad server, read from cache anyway. |
+ if ((effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) && |
+ IsOfflineError(result) && mode_ == READ_WRITE && entry_ && !partial_) { |
+ network_trans_.reset(); |
+ UpdateTransactionPattern(PATTERN_NOT_COVERED); |
+ |
+ cache_->ConvertWriterToReader(entry_); |
+ mode_ = READ; |
+ response_.was_cache_override = true; |
+ |
+ // If there is metadata, read it. Otherwise, we're done. |
+ if (entry_->disk_entry->GetDataSize(kMetadataIndex)) |
+ next_state_ = STATE_CACHE_READ_METADATA; |
+ return OK; |
+ } |
+ |
+ // If we tried to conditionalize the request and failed, we know |
+ // we won't be reading from the cache after this point. |
+ if (couldnt_conditionalize_request_) |
+ mode_ = WRITE; |
+ |
if (result == OK) { |
next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; |
return OK; |
@@ -1781,15 +1814,17 @@ int HttpCache::Transaction::BeginCacheValidation() { |
} else { |
// Make the network request conditional, to see if we may reuse our cached |
// response. If we cannot do so, then we just resort to a normal fetch. |
- // Our mode remains READ_WRITE for a conditional request. We'll switch to |
- // either READ or WRITE mode once we hear back from the server. |
+ // Our mode remains READ_WRITE for a conditional request. Even if the |
+ // conditionalization fails, we don't switch to WRITE mode until we |
+ // no we won't be falling back to using the cache entry in the |
rvargas (doing something else)
2013/03/06 03:11:48
typo: no we
Randy Smith (Not in Mondays)
2013/03/06 22:55:55
Done.
|
+ // LOAD_FROM_CACHE_IF_OFFLINE case. |
if (!ConditionalizeRequest()) { |
+ couldnt_conditionalize_request_ = true; |
UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); |
if (partial_.get()) |
return DoRestartPartialRequest(); |
DCHECK_NE(206, response_.headers->response_code()); |
- mode_ = WRITE; |
} |
next_state_ = STATE_SEND_REQUEST; |
} |