| 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_);
|
|
|