Index: net/http/http_cache_transaction.cc |
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc |
index 61d992f0c5812f8962803cd54d8a4446f95664ea..0a84680a11ac788b9438d0de038df4d75acbaeae 100644 |
--- a/net/http/http_cache_transaction.cc |
+++ b/net/http/http_cache_transaction.cc |
@@ -307,9 +307,7 @@ static bool HeaderMatches(const HttpRequestHeaders& headers, |
//----------------------------------------------------------------------------- |
-HttpCache::Transaction::Transaction( |
- RequestPriority priority, |
- HttpCache* cache) |
+HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache) |
: next_state_(STATE_NONE), |
request_(NULL), |
priority_(priority), |
@@ -330,6 +328,7 @@ HttpCache::Transaction::Transaction( |
vary_mismatch_(false), |
couldnt_conditionalize_request_(false), |
bypass_lock_for_test_(false), |
+ fail_conditionalization_for_test_(false), |
io_buf_len_(0), |
read_offset_(0), |
effective_load_flags_(0), |
@@ -1219,6 +1218,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() { |
// If we have an authentication response, we are exposed to weird things |
// hapenning if the user cancels the authentication before we receive |
// the new response. |
+ net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST); |
UpdateTransactionPattern(PATTERN_NOT_COVERED); |
response_ = HttpResponseInfo(); |
ResetNetworkTransaction(); |
@@ -1710,6 +1710,16 @@ int HttpCache::Transaction::DoOverwriteCachedResponse() { |
return OK; |
} |
+ if (handling_206_ && !CanResume(false)) { |
+ // There is no point in storing this resource because it will never be used. |
+ // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries. |
+ DoneWritingToEntry(false); |
+ if (partial_.get()) |
+ partial_->FixResponseHeaders(response_.headers.get(), true); |
+ next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; |
+ return OK; |
+ } |
+ |
target_state_ = STATE_TRUNCATE_CACHED_DATA; |
next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE : |
STATE_CACHE_WRITE_RESPONSE; |
@@ -1976,12 +1986,6 @@ int HttpCache::Transaction::DoCacheQueryDataComplete(int result) { |
FROM_HERE_WITH_EXPLICIT_FUNCTION( |
"422516 HttpCache::Transaction::DoCacheQueryDataComplete")); |
- if (result == ERR_NOT_IMPLEMENTED) { |
- // Restart the request overwriting the cache entry. |
- // TODO(pasko): remove this workaround as soon as the SimpleBackendImpl |
- // supports Sparse IO. |
- return DoRestartPartialRequest(); |
- } |
DCHECK_EQ(OK, result); |
if (!cache_.get()) |
return ERR_UNEXPECTED; |
@@ -2211,6 +2215,7 @@ void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log, |
bool range_found = false; |
bool external_validation_error = false; |
+ bool special_headers = false; |
if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange)) |
range_found = true; |
@@ -2218,6 +2223,7 @@ void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log, |
for (size_t i = 0; i < arraysize(kSpecialHeaders); ++i) { |
if (HeaderMatches(request_->extra_headers, kSpecialHeaders[i].search)) { |
effective_load_flags_ |= kSpecialHeaders[i].load_flag; |
+ special_headers = true; |
break; |
} |
} |
@@ -2238,6 +2244,15 @@ void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log, |
} |
} |
+ if (range_found || special_headers || external_validation_.initialized) { |
+ // Log the headers before request_ is modified. |
+ std::string empty; |
+ net_log_.AddEvent( |
+ NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS, |
+ base::Bind(&HttpRequestHeaders::NetLogCallback, |
+ base::Unretained(&request_->extra_headers), &empty)); |
+ } |
+ |
// We don't support ranges and validation headers. |
if (range_found && external_validation_.initialized) { |
LOG(WARNING) << "Byte ranges AND validation headers found."; |
@@ -2570,10 +2585,11 @@ bool HttpCache::Transaction::ConditionalizeRequest() { |
return false; |
} |
- if (response_.headers->response_code() == 206 && |
- !response_.headers->HasStrongValidators()) { |
+ if (fail_conditionalization_for_test_) |
return false; |
- } |
+ |
+ DCHECK(response_.headers->response_code() != 206 || |
+ response_.headers->HasStrongValidators()); |
// Just use the first available ETag and/or Last-Modified header value. |
// TODO(darin): Or should we use the last? |
@@ -2712,9 +2728,13 @@ bool HttpCache::Transaction::ValidatePartialResponse() { |
return true; |
} else { |
// We asked for "If-Range: " so a 206 means just another range. |
- if (partial_response && partial_->ResponseHeadersOK(headers)) { |
- handling_206_ = true; |
- return true; |
+ if (partial_response) { |
+ if (partial_->ResponseHeadersOK(headers)) { |
+ handling_206_ = true; |
+ return true; |
+ } else { |
+ failure = true; |
+ } |
} |
if (!reading_ && !is_sparse_ && !partial_response) { |
@@ -2741,18 +2761,21 @@ bool HttpCache::Transaction::ValidatePartialResponse() { |
if (failure) { |
// We cannot truncate this entry, it has to be deleted. |
UpdateTransactionPattern(PATTERN_NOT_COVERED); |
- DoomPartialEntry(false); |
mode_ = NONE; |
- if (!reading_ && !partial_->IsLastRange()) { |
- // We'll attempt to issue another network request, this time without us |
- // messing up the headers. |
- partial_->RestoreHeaders(&custom_request_->extra_headers); |
- partial_.reset(); |
- truncated_ = false; |
- return false; |
+ if (is_sparse_ || truncated_) { |
+ // There was something cached to start with, either sparsed data (206), or |
+ // a truncated 200, which means that we probably modified the request, |
+ // adding a byte range or modifying the range requested by the caller. |
+ if (!reading_ && !partial_->IsLastRange()) { |
+ // We have not returned anything to the caller yet so it should be safe |
+ // to issue another network request, this time without us messing up the |
+ // headers. |
+ ResetPartialState(true); |
+ return false; |
+ } |
+ LOG(WARNING) << "Failed to revalidate partial entry"; |
} |
- LOG(WARNING) << "Failed to revalidate partial entry"; |
- partial_.reset(); |
+ DoomPartialEntry(true); |
return true; |
} |
@@ -2979,6 +3002,7 @@ void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { |
cache_->DoneWithEntry(entry_, this, false); |
entry_ = NULL; |
is_sparse_ = false; |
+ truncated_ = false; |
if (delete_object) |
partial_.reset(NULL); |
} |
@@ -3008,14 +3032,30 @@ int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { |
int HttpCache::Transaction::DoRestartPartialRequest() { |
// The stored data cannot be used. Get rid of it and restart this request. |
- // We need to also reset the |truncated_| flag as a new entry is created. |
- DoomPartialEntry(!range_requested_); |
+ net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST); |
+ |
+ // WRITE + Doom + STATE_INIT_ENTRY == STATE_CREATE_ENTRY (without an attempt |
+ // to Doom the entry again). |
mode_ = WRITE; |
- truncated_ = false; |
- next_state_ = STATE_INIT_ENTRY; |
+ ResetPartialState(!range_requested_); |
+ next_state_ = STATE_CREATE_ENTRY; |
return OK; |
} |
+void HttpCache::Transaction::ResetPartialState(bool delete_object) { |
+ partial_->RestoreHeaders(&custom_request_->extra_headers); |
+ DoomPartialEntry(delete_object); |
+ |
+ if (!delete_object) { |
+ // The simplest way to re-initialize partial_ is to create a new object. |
+ partial_.reset(new PartialData()); |
+ if (partial_->Init(request_->extra_headers)) |
+ partial_->SetHeaders(custom_request_->extra_headers); |
+ else |
+ partial_.reset(); |
+ } |
+} |
+ |
void HttpCache::Transaction::ResetNetworkTransaction() { |
DCHECK(!old_network_trans_load_timing_); |
DCHECK(network_trans_); |