| Index: net/http/http_cache_transaction.cc
|
| diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
|
| index f2fcf4cb7c47a5dd60ff53bcb0478b7e47c4238f..eed5d48148fd641b76e71be9e9a98ba5349c5901 100644
|
| --- a/net/http/http_cache_transaction.cc
|
| +++ b/net/http/http_cache_transaction.cc
|
| @@ -804,24 +804,6 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| case STATE_GET_BACKEND_COMPLETE:
|
| rv = DoGetBackendComplete(rv);
|
| break;
|
| - case STATE_SEND_REQUEST:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoSendRequest();
|
| - break;
|
| - case STATE_SEND_REQUEST_COMPLETE:
|
| - rv = DoSendRequestComplete(rv);
|
| - break;
|
| - case STATE_SUCCESSFUL_SEND_REQUEST:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoSuccessfulSendRequest();
|
| - break;
|
| - case STATE_NETWORK_READ:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoNetworkRead();
|
| - break;
|
| - case STATE_NETWORK_READ_COMPLETE:
|
| - rv = DoNetworkReadComplete(rv);
|
| - break;
|
| case STATE_INIT_ENTRY:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoInitEntry();
|
| @@ -833,13 +815,6 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| case STATE_OPEN_ENTRY_COMPLETE:
|
| rv = DoOpenEntryComplete(rv);
|
| break;
|
| - case STATE_CREATE_ENTRY:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoCreateEntry();
|
| - break;
|
| - case STATE_CREATE_ENTRY_COMPLETE:
|
| - rv = DoCreateEntryComplete(rv);
|
| - break;
|
| case STATE_DOOM_ENTRY:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoDoomEntry();
|
| @@ -847,6 +822,13 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| case STATE_DOOM_ENTRY_COMPLETE:
|
| rv = DoDoomEntryComplete(rv);
|
| break;
|
| + case STATE_CREATE_ENTRY:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoCreateEntry();
|
| + break;
|
| + case STATE_CREATE_ENTRY_COMPLETE:
|
| + rv = DoCreateEntryComplete(rv);
|
| + break;
|
| case STATE_ADD_TO_ENTRY:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoAddToEntry();
|
| @@ -854,6 +836,31 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| case STATE_ADD_TO_ENTRY_COMPLETE:
|
| rv = DoAddToEntryComplete(rv);
|
| break;
|
| + case STATE_CACHE_READ_RESPONSE:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoCacheReadResponse();
|
| + break;
|
| + case STATE_CACHE_READ_RESPONSE_COMPLETE:
|
| + rv = DoCacheReadResponseComplete(rv);
|
| + break;
|
| + case STATE_TOGGLE_UNUSED_SINCE_PREFETCH:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoCacheToggleUnusedSincePrefetch();
|
| + break;
|
| + case STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE:
|
| + rv = DoCacheToggleUnusedSincePrefetchComplete(rv);
|
| + break;
|
| + case STATE_CACHE_DISPATCH_VALIDATION:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoCacheDispatchValidation();
|
| + break;
|
| + case STATE_CACHE_QUERY_DATA:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoCacheQueryData();
|
| + break;
|
| + case STATE_CACHE_QUERY_DATA_COMPLETE:
|
| + rv = DoCacheQueryDataComplete(rv);
|
| + break;
|
| case STATE_START_PARTIAL_CACHE_VALIDATION:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoStartPartialCacheValidation();
|
| @@ -861,6 +868,17 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION:
|
| rv = DoCompletePartialCacheValidation(rv);
|
| break;
|
| + case STATE_SEND_REQUEST:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoSendRequest();
|
| + break;
|
| + case STATE_SEND_REQUEST_COMPLETE:
|
| + rv = DoSendRequestComplete(rv);
|
| + break;
|
| + case STATE_SUCCESSFUL_SEND_REQUEST:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoSuccessfulSendRequest();
|
| + break;
|
| case STATE_UPDATE_CACHED_RESPONSE:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoUpdateCachedResponse();
|
| @@ -872,6 +890,17 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| DCHECK_EQ(OK, rv);
|
| rv = DoOverwriteCachedResponse();
|
| break;
|
| + case STATE_CACHE_WRITE_RESPONSE:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoCacheWriteResponse();
|
| + break;
|
| + case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoCacheWriteTruncatedResponse();
|
| + break;
|
| + case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
|
| + rv = DoCacheWriteResponseComplete(rv);
|
| + break;
|
| case STATE_TRUNCATE_CACHED_DATA:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoTruncateCachedData();
|
| @@ -890,35 +919,6 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| DCHECK_EQ(OK, rv);
|
| rv = DoPartialHeadersReceived();
|
| break;
|
| - case STATE_CACHE_READ_RESPONSE:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoCacheReadResponse();
|
| - break;
|
| - case STATE_CACHE_READ_RESPONSE_COMPLETE:
|
| - rv = DoCacheReadResponseComplete(rv);
|
| - break;
|
| - case STATE_CACHE_DISPATCH_VALIDATION:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoCacheDispatchValidation();
|
| - break;
|
| - case STATE_TOGGLE_UNUSED_SINCE_PREFETCH:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoCacheToggleUnusedSincePrefetch();
|
| - break;
|
| - case STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE:
|
| - rv = DoCacheToggleUnusedSincePrefetchComplete(rv);
|
| - break;
|
| - case STATE_CACHE_WRITE_RESPONSE:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoCacheWriteResponse();
|
| - break;
|
| - case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
|
| - DCHECK_EQ(OK, rv);
|
| - rv = DoCacheWriteTruncatedResponse();
|
| - break;
|
| - case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
|
| - rv = DoCacheWriteResponseComplete(rv);
|
| - break;
|
| case STATE_CACHE_READ_METADATA:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoCacheReadMetadata();
|
| @@ -926,12 +926,12 @@ int HttpCache::Transaction::DoLoop(int result) {
|
| case STATE_CACHE_READ_METADATA_COMPLETE:
|
| rv = DoCacheReadMetadataComplete(rv);
|
| break;
|
| - case STATE_CACHE_QUERY_DATA:
|
| + case STATE_NETWORK_READ:
|
| DCHECK_EQ(OK, rv);
|
| - rv = DoCacheQueryData();
|
| + rv = DoNetworkRead();
|
| break;
|
| - case STATE_CACHE_QUERY_DATA_COMPLETE:
|
| - rv = DoCacheQueryDataComplete(rv);
|
| + case STATE_NETWORK_READ_COMPLETE:
|
| + rv = DoNetworkReadComplete(rv);
|
| break;
|
| case STATE_CACHE_READ_DATA:
|
| DCHECK_EQ(OK, rv);
|
| @@ -1031,255 +1031,87 @@ int HttpCache::Transaction::DoGetBackendComplete(int result) {
|
| return OK;
|
| }
|
|
|
| -int HttpCache::Transaction::DoSendRequest() {
|
| - DCHECK(mode_ & WRITE || mode_ == NONE);
|
| - DCHECK(!network_trans_.get());
|
| -
|
| - send_request_since_ = TimeTicks::Now();
|
| -
|
| - // Create a network transaction.
|
| - int rv = cache_->network_layer_->CreateTransaction(priority_,
|
| - &network_trans_);
|
| - if (rv != OK)
|
| - return rv;
|
| - network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_);
|
| - network_trans_->SetBeforeProxyHeadersSentCallback(
|
| - before_proxy_headers_sent_callback_);
|
| -
|
| - // Old load timing information, if any, is now obsolete.
|
| - old_network_trans_load_timing_.reset();
|
| -
|
| - if (websocket_handshake_stream_base_create_helper_)
|
| - network_trans_->SetWebSocketHandshakeStreamCreateHelper(
|
| - websocket_handshake_stream_base_create_helper_);
|
| -
|
| - next_state_ = STATE_SEND_REQUEST_COMPLETE;
|
| - rv = network_trans_->Start(request_, io_callback_, net_log_);
|
| - return rv;
|
| -}
|
| +int HttpCache::Transaction::DoInitEntry() {
|
| + DCHECK(!new_entry_);
|
|
|
| -int HttpCache::Transaction::DoSendRequestComplete(int result) {
|
| if (!cache_.get())
|
| return ERR_UNEXPECTED;
|
|
|
| - // 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;
|
| + if (mode_ == WRITE) {
|
| + next_state_ = STATE_DOOM_ENTRY;
|
| return OK;
|
| }
|
|
|
| - const HttpResponseInfo* response = network_trans_->GetResponseInfo();
|
| - response_.network_accessed = response->network_accessed;
|
| -
|
| - // Do not record requests that have network errors or restarts.
|
| - UpdateTransactionPattern(PATTERN_NOT_COVERED);
|
| - if (IsCertificateError(result)) {
|
| - // If we get a certificate error, then there is a certificate in ssl_info,
|
| - // so GetResponseInfo() should never return NULL here.
|
| - DCHECK(response);
|
| - response_.ssl_info = response->ssl_info;
|
| - } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
|
| - DCHECK(response);
|
| - response_.cert_request_info = response->cert_request_info;
|
| - } else if (response_.was_cached) {
|
| - DoneWritingToEntry(true);
|
| - }
|
| -
|
| - return result;
|
| + next_state_ = STATE_OPEN_ENTRY;
|
| + return OK;
|
| }
|
|
|
| -// We received the response headers and there is no error.
|
| -int HttpCache::Transaction::DoSuccessfulSendRequest() {
|
| - DCHECK(!new_response_);
|
| - const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
|
| -
|
| - if (new_response->headers->response_code() == 401 ||
|
| - new_response->headers->response_code() == 407) {
|
| - auth_response_ = *new_response;
|
| - if (!reading_)
|
| - return OK;
|
| +int HttpCache::Transaction::DoOpenEntry() {
|
| + DCHECK(!new_entry_);
|
| + next_state_ = STATE_OPEN_ENTRY_COMPLETE;
|
| + cache_pending_ = true;
|
| + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
|
| + first_cache_access_since_ = TimeTicks::Now();
|
| + return cache_->OpenEntry(cache_key_, &new_entry_, this);
|
| +}
|
|
|
| - // We initiated a second request the caller doesn't know about. We should be
|
| - // able to authenticate this request because we should have authenticated
|
| - // this URL moments ago.
|
| - if (IsReadyToRestartForAuth()) {
|
| - DCHECK(!response_.auth_challenge.get());
|
| - next_state_ = STATE_SEND_REQUEST_COMPLETE;
|
| - // In theory we should check to see if there are new cookies, but there
|
| - // is no way to do that from here.
|
| - return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_);
|
| - }
|
| +int HttpCache::Transaction::DoOpenEntryComplete(int result) {
|
| + // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
|
| + // OK, otherwise the cache will end up with an active entry without any
|
| + // transaction attached.
|
| + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
|
| + cache_pending_ = false;
|
| + if (result == OK) {
|
| + next_state_ = STATE_ADD_TO_ENTRY;
|
| + return OK;
|
| + }
|
|
|
| - // We have to perform cleanup at this point so that at least the next
|
| - // request can succeed. We do not retry at this point, because data
|
| - // has been read and we have no way to gather credentials. We would
|
| - // fail again, and potentially loop. This can happen if the credentials
|
| - // expire while chrome is suspended.
|
| - if (entry_)
|
| - DoomPartialEntry(false);
|
| - mode_ = NONE;
|
| - partial_.reset();
|
| - ResetNetworkTransaction();
|
| - return ERR_CACHE_AUTH_FAILURE_AFTER_READ;
|
| + if (result == ERR_CACHE_RACE) {
|
| + next_state_ = STATE_INIT_ENTRY;
|
| + return OK;
|
| }
|
|
|
| - new_response_ = new_response;
|
| - if (!ValidatePartialResponse() && !auth_response_.headers.get()) {
|
| - // Something went wrong with this request and we have to restart it.
|
| - // 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();
|
| - new_response_ = NULL;
|
| + if (request_->method == "PUT" || request_->method == "DELETE" ||
|
| + (request_->method == "HEAD" && mode_ == READ_WRITE)) {
|
| + DCHECK(mode_ == READ_WRITE || mode_ == WRITE || request_->method == "HEAD");
|
| + mode_ = NONE;
|
| next_state_ = STATE_SEND_REQUEST;
|
| return OK;
|
| }
|
|
|
| - if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
|
| - // We have stored the full entry, but it changed and the server is
|
| - // sending a range. We have to delete the old entry.
|
| - UpdateTransactionPattern(PATTERN_NOT_COVERED);
|
| - DoneWritingToEntry(false);
|
| + if (mode_ == READ_WRITE) {
|
| + mode_ = WRITE;
|
| + next_state_ = STATE_CREATE_ENTRY;
|
| + return OK;
|
| + }
|
| + if (mode_ == UPDATE) {
|
| + // There is no cache entry to update; proceed without caching.
|
| + mode_ = NONE;
|
| + next_state_ = STATE_SEND_REQUEST;
|
| + return OK;
|
| }
|
|
|
| - if (mode_ == WRITE &&
|
| - transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) {
|
| - UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
|
| - }
|
| -
|
| - // Invalidate any cached GET with a successful PUT or DELETE.
|
| - if (mode_ == WRITE &&
|
| - (request_->method == "PUT" || request_->method == "DELETE")) {
|
| - if (NonErrorResponse(new_response->headers->response_code())) {
|
| - int ret = cache_->DoomEntry(cache_key_, NULL);
|
| - DCHECK_EQ(OK, ret);
|
| - }
|
| - cache_->DoneWritingToEntry(entry_, true);
|
| - entry_ = NULL;
|
| - mode_ = NONE;
|
| - }
|
| -
|
| - // Invalidate any cached GET with a successful POST.
|
| - if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) &&
|
| - request_->method == "POST" &&
|
| - NonErrorResponse(new_response->headers->response_code())) {
|
| - cache_->DoomMainEntryForUrl(request_->url);
|
| - }
|
| -
|
| - RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
|
| -
|
| - if (new_response_->headers->response_code() == 416 &&
|
| - (request_->method == "GET" || request_->method == "POST")) {
|
| - // If there is an active entry it may be destroyed with this transaction.
|
| - response_ = *new_response_;
|
| - return OK;
|
| - }
|
| -
|
| - // Are we expecting a response to a conditional query?
|
| - if (mode_ == READ_WRITE || mode_ == UPDATE) {
|
| - if (new_response->headers->response_code() == 304 || handling_206_) {
|
| - UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED);
|
| - next_state_ = STATE_UPDATE_CACHED_RESPONSE;
|
| - return OK;
|
| - }
|
| - UpdateTransactionPattern(PATTERN_ENTRY_UPDATED);
|
| - mode_ = WRITE;
|
| - }
|
| -
|
| - next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
|
| - return OK;
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoNetworkRead() {
|
| - next_state_ = STATE_NETWORK_READ_COMPLETE;
|
| - return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoNetworkReadComplete(int result) {
|
| - DCHECK(mode_ & WRITE || mode_ == NONE);
|
| -
|
| - if (!cache_.get())
|
| - return ERR_UNEXPECTED;
|
| -
|
| - // If there is an error or we aren't saving the data, we are done; just wait
|
| - // until the destructor runs to see if we can keep the data.
|
| - if (mode_ == NONE || result < 0)
|
| - return result;
|
| -
|
| - next_state_ = STATE_CACHE_WRITE_DATA;
|
| - return result;
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoInitEntry() {
|
| - DCHECK(!new_entry_);
|
| -
|
| - if (!cache_.get())
|
| - return ERR_UNEXPECTED;
|
| -
|
| - if (mode_ == WRITE) {
|
| - next_state_ = STATE_DOOM_ENTRY;
|
| - return OK;
|
| - }
|
| -
|
| - next_state_ = STATE_OPEN_ENTRY;
|
| - return OK;
|
| + // The entry does not exist, and we are not permitted to create a new entry,
|
| + // so we must fail.
|
| + return ERR_CACHE_MISS;
|
| }
|
|
|
| -int HttpCache::Transaction::DoOpenEntry() {
|
| - DCHECK(!new_entry_);
|
| - next_state_ = STATE_OPEN_ENTRY_COMPLETE;
|
| +int HttpCache::Transaction::DoDoomEntry() {
|
| + next_state_ = STATE_DOOM_ENTRY_COMPLETE;
|
| cache_pending_ = true;
|
| - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
|
| - first_cache_access_since_ = TimeTicks::Now();
|
| - return cache_->OpenEntry(cache_key_, &new_entry_, this);
|
| + if (first_cache_access_since_.is_null())
|
| + first_cache_access_since_ = TimeTicks::Now();
|
| + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY);
|
| + return cache_->DoomEntry(cache_key_, this);
|
| }
|
|
|
| -int HttpCache::Transaction::DoOpenEntryComplete(int result) {
|
| - // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
|
| - // OK, otherwise the cache will end up with an active entry without any
|
| - // transaction attached.
|
| - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
|
| +int HttpCache::Transaction::DoDoomEntryComplete(int result) {
|
| + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result);
|
| + next_state_ = STATE_CREATE_ENTRY;
|
| cache_pending_ = false;
|
| - if (result == OK) {
|
| - next_state_ = STATE_ADD_TO_ENTRY;
|
| - return OK;
|
| - }
|
| -
|
| - if (result == ERR_CACHE_RACE) {
|
| + if (result == ERR_CACHE_RACE)
|
| next_state_ = STATE_INIT_ENTRY;
|
| - return OK;
|
| - }
|
| -
|
| - if (request_->method == "PUT" || request_->method == "DELETE" ||
|
| - (request_->method == "HEAD" && mode_ == READ_WRITE)) {
|
| - DCHECK(mode_ == READ_WRITE || mode_ == WRITE || request_->method == "HEAD");
|
| - mode_ = NONE;
|
| - next_state_ = STATE_SEND_REQUEST;
|
| - return OK;
|
| - }
|
| -
|
| - if (mode_ == READ_WRITE) {
|
| - mode_ = WRITE;
|
| - next_state_ = STATE_CREATE_ENTRY;
|
| - return OK;
|
| - }
|
| - if (mode_ == UPDATE) {
|
| - // There is no cache entry to update; proceed without caching.
|
| - mode_ = NONE;
|
| - next_state_ = STATE_SEND_REQUEST;
|
| - return OK;
|
| - }
|
| -
|
| - // The entry does not exist, and we are not permitted to create a new entry,
|
| - // so we must fail.
|
| - return ERR_CACHE_MISS;
|
| + return OK;
|
| }
|
|
|
| int HttpCache::Transaction::DoCreateEntry() {
|
| @@ -1318,24 +1150,6 @@ int HttpCache::Transaction::DoCreateEntryComplete(int result) {
|
| return OK;
|
| }
|
|
|
| -int HttpCache::Transaction::DoDoomEntry() {
|
| - next_state_ = STATE_DOOM_ENTRY_COMPLETE;
|
| - cache_pending_ = true;
|
| - if (first_cache_access_since_.is_null())
|
| - first_cache_access_since_ = TimeTicks::Now();
|
| - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY);
|
| - return cache_->DoomEntry(cache_key_, this);
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoDoomEntryComplete(int result) {
|
| - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result);
|
| - next_state_ = STATE_CREATE_ENTRY;
|
| - cache_pending_ = false;
|
| - if (result == ERR_CACHE_RACE)
|
| - next_state_ = STATE_INIT_ENTRY;
|
| - return OK;
|
| -}
|
| -
|
| int HttpCache::Transaction::DoAddToEntry() {
|
| DCHECK(new_entry_);
|
| cache_pending_ = true;
|
| @@ -1427,39 +1241,315 @@ int HttpCache::Transaction::DoAddToEntryComplete(int result) {
|
| return OK;
|
| }
|
|
|
| +int HttpCache::Transaction::DoCacheReadResponse() {
|
| + DCHECK(entry_);
|
| + next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
|
| +
|
| + io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
|
| + read_buf_ = new IOBuffer(io_buf_len_);
|
| +
|
| + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
|
| + return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
|
| + io_buf_len_, io_callback_);
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
|
| + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
|
| + if (result != io_buf_len_ ||
|
| + !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, &response_,
|
| + &truncated_)) {
|
| + return OnCacheReadError(result, true);
|
| + }
|
| +
|
| + // cert_cache() will be null if the CertCacheTrial field trial is disabled.
|
| + if (cache_->cert_cache() && response_.ssl_info.is_valid())
|
| + ReadCertChain();
|
| +
|
| + // Some resources may have slipped in as truncated when they're not.
|
| + int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
|
| + if (response_.headers->GetContentLength() == current_size)
|
| + truncated_ = false;
|
| +
|
| + if ((response_.unused_since_prefetch &&
|
| + !(request_->load_flags & LOAD_PREFETCH)) ||
|
| + (!response_.unused_since_prefetch &&
|
| + (request_->load_flags & LOAD_PREFETCH))) {
|
| + // Either this is the first use of an entry since it was prefetched or
|
| + // this is a prefetch. The value of response.unused_since_prefetch is valid
|
| + // for this transaction but the bit needs to be flipped in storage.
|
| + next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH;
|
| + return OK;
|
| + }
|
| +
|
| + next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
|
| + return OK;
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch() {
|
| + // Write back the toggled value for the next use of this entry.
|
| + response_.unused_since_prefetch = !response_.unused_since_prefetch;
|
| +
|
| + // TODO(jkarlin): If DoUpdateCachedResponse is also called for this
|
| + // transaction then metadata will be written to cache twice. If prefetching
|
| + // becomes more common, consider combining the writes.
|
| + target_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE;
|
| + next_state_ = STATE_CACHE_WRITE_RESPONSE;
|
| + return OK;
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete(
|
| + int result) {
|
| + // Restore the original value for this transaction.
|
| + response_.unused_since_prefetch = !response_.unused_since_prefetch;
|
| + next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
|
| + return OK;
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheDispatchValidation() {
|
| + // We now have access to the cache entry.
|
| + //
|
| + // o if we are a reader for the transaction, then we can start reading the
|
| + // cache entry.
|
| + //
|
| + // o if we can read or write, then we should check if the cache entry needs
|
| + // to be validated and then issue a network request if needed or just read
|
| + // from the cache if the cache entry is already valid.
|
| + //
|
| + // o if we are set to UPDATE, then we are handling an externally
|
| + // conditionalized request (if-modified-since / if-none-match). We check
|
| + // if the request headers define a validation request.
|
| + //
|
| + int result = ERR_FAILED;
|
| + switch (mode_) {
|
| + case READ:
|
| + UpdateTransactionPattern(PATTERN_ENTRY_USED);
|
| + result = BeginCacheRead();
|
| + break;
|
| + case READ_WRITE:
|
| + result = BeginPartialCacheValidation();
|
| + break;
|
| + case UPDATE:
|
| + result = BeginExternallyConditionalizedRequest();
|
| + break;
|
| + case WRITE:
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheQueryData() {
|
| + next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
|
| + return entry_->disk_entry->ReadyForSparseIO(io_callback_);
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
|
| + DCHECK_EQ(OK, result);
|
| + if (!cache_.get())
|
| + return ERR_UNEXPECTED;
|
| +
|
| + return ValidateEntryHeadersAndContinue();
|
| +}
|
| +
|
| // We may end up here multiple times for a given request.
|
| int HttpCache::Transaction::DoStartPartialCacheValidation() {
|
| if (mode_ == NONE)
|
| return OK;
|
|
|
| - next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
|
| - return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_);
|
| -}
|
| + next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
|
| + return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_);
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
|
| + if (!result) {
|
| + // This is the end of the request.
|
| + if (mode_ & WRITE) {
|
| + DoneWritingToEntry(true);
|
| + } else {
|
| + cache_->DoneReadingFromEntry(entry_, this);
|
| + entry_ = NULL;
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + if (result < 0)
|
| + return result;
|
| +
|
| + partial_->PrepareCacheValidation(entry_->disk_entry,
|
| + &custom_request_->extra_headers);
|
| +
|
| + if (reading_ && partial_->IsCurrentRangeCached()) {
|
| + next_state_ = STATE_CACHE_READ_DATA;
|
| + return OK;
|
| + }
|
| +
|
| + return BeginCacheValidation();
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoSendRequest() {
|
| + DCHECK(mode_ & WRITE || mode_ == NONE);
|
| + DCHECK(!network_trans_.get());
|
| +
|
| + send_request_since_ = TimeTicks::Now();
|
| +
|
| + // Create a network transaction.
|
| + int rv =
|
| + cache_->network_layer_->CreateTransaction(priority_, &network_trans_);
|
| + if (rv != OK)
|
| + return rv;
|
| + network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_);
|
| + network_trans_->SetBeforeProxyHeadersSentCallback(
|
| + before_proxy_headers_sent_callback_);
|
| +
|
| + // Old load timing information, if any, is now obsolete.
|
| + old_network_trans_load_timing_.reset();
|
| +
|
| + if (websocket_handshake_stream_base_create_helper_)
|
| + network_trans_->SetWebSocketHandshakeStreamCreateHelper(
|
| + websocket_handshake_stream_base_create_helper_);
|
| +
|
| + next_state_ = STATE_SEND_REQUEST_COMPLETE;
|
| + rv = network_trans_->Start(request_, io_callback_, net_log_);
|
| + return rv;
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoSendRequestComplete(int result) {
|
| + if (!cache_.get())
|
| + return ERR_UNEXPECTED;
|
| +
|
| + // 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;
|
| + }
|
| +
|
| + const HttpResponseInfo* response = network_trans_->GetResponseInfo();
|
| + response_.network_accessed = response->network_accessed;
|
| +
|
| + // Do not record requests that have network errors or restarts.
|
| + UpdateTransactionPattern(PATTERN_NOT_COVERED);
|
| + if (IsCertificateError(result)) {
|
| + // If we get a certificate error, then there is a certificate in ssl_info,
|
| + // so GetResponseInfo() should never return NULL here.
|
| + DCHECK(response);
|
| + response_.ssl_info = response->ssl_info;
|
| + } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
|
| + DCHECK(response);
|
| + response_.cert_request_info = response->cert_request_info;
|
| + } else if (response_.was_cached) {
|
| + DoneWritingToEntry(true);
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +// We received the response headers and there is no error.
|
| +int HttpCache::Transaction::DoSuccessfulSendRequest() {
|
| + DCHECK(!new_response_);
|
| + const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
|
| +
|
| + if (new_response->headers->response_code() == 401 ||
|
| + new_response->headers->response_code() == 407) {
|
| + auth_response_ = *new_response;
|
| + if (!reading_)
|
| + return OK;
|
| +
|
| + // We initiated a second request the caller doesn't know about. We should be
|
| + // able to authenticate this request because we should have authenticated
|
| + // this URL moments ago.
|
| + if (IsReadyToRestartForAuth()) {
|
| + DCHECK(!response_.auth_challenge.get());
|
| + next_state_ = STATE_SEND_REQUEST_COMPLETE;
|
| + // In theory we should check to see if there are new cookies, but there
|
| + // is no way to do that from here.
|
| + return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_);
|
| + }
|
| +
|
| + // We have to perform cleanup at this point so that at least the next
|
| + // request can succeed. We do not retry at this point, because data
|
| + // has been read and we have no way to gather credentials. We would
|
| + // fail again, and potentially loop. This can happen if the credentials
|
| + // expire while chrome is suspended.
|
| + if (entry_)
|
| + DoomPartialEntry(false);
|
| + mode_ = NONE;
|
| + partial_.reset();
|
| + ResetNetworkTransaction();
|
| + return ERR_CACHE_AUTH_FAILURE_AFTER_READ;
|
| + }
|
| +
|
| + new_response_ = new_response;
|
| + if (!ValidatePartialResponse() && !auth_response_.headers.get()) {
|
| + // Something went wrong with this request and we have to restart it.
|
| + // 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();
|
| + new_response_ = NULL;
|
| + next_state_ = STATE_SEND_REQUEST;
|
| + return OK;
|
| + }
|
| +
|
| + if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
|
| + // We have stored the full entry, but it changed and the server is
|
| + // sending a range. We have to delete the old entry.
|
| + UpdateTransactionPattern(PATTERN_NOT_COVERED);
|
| + DoneWritingToEntry(false);
|
| + }
|
|
|
| -int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
|
| - if (!result) {
|
| - // This is the end of the request.
|
| - if (mode_ & WRITE) {
|
| - DoneWritingToEntry(true);
|
| - } else {
|
| - cache_->DoneReadingFromEntry(entry_, this);
|
| - entry_ = NULL;
|
| + if (mode_ == WRITE &&
|
| + transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) {
|
| + UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
|
| + }
|
| +
|
| + // Invalidate any cached GET with a successful PUT or DELETE.
|
| + if (mode_ == WRITE &&
|
| + (request_->method == "PUT" || request_->method == "DELETE")) {
|
| + if (NonErrorResponse(new_response->headers->response_code())) {
|
| + int ret = cache_->DoomEntry(cache_key_, NULL);
|
| + DCHECK_EQ(OK, ret);
|
| }
|
| - return result;
|
| + cache_->DoneWritingToEntry(entry_, true);
|
| + entry_ = NULL;
|
| + mode_ = NONE;
|
| }
|
|
|
| - if (result < 0)
|
| - return result;
|
| + // Invalidate any cached GET with a successful POST.
|
| + if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) &&
|
| + request_->method == "POST" &&
|
| + NonErrorResponse(new_response->headers->response_code())) {
|
| + cache_->DoomMainEntryForUrl(request_->url);
|
| + }
|
|
|
| - partial_->PrepareCacheValidation(entry_->disk_entry,
|
| - &custom_request_->extra_headers);
|
| + RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
|
|
|
| - if (reading_ && partial_->IsCurrentRangeCached()) {
|
| - next_state_ = STATE_CACHE_READ_DATA;
|
| + if (new_response_->headers->response_code() == 416 &&
|
| + (request_->method == "GET" || request_->method == "POST")) {
|
| + // If there is an active entry it may be destroyed with this transaction.
|
| + response_ = *new_response_;
|
| return OK;
|
| }
|
|
|
| - return BeginCacheValidation();
|
| + // Are we expecting a response to a conditional query?
|
| + if (mode_ == READ_WRITE || mode_ == UPDATE) {
|
| + if (new_response->headers->response_code() == 304 || handling_206_) {
|
| + UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED);
|
| + next_state_ = STATE_UPDATE_CACHED_RESPONSE;
|
| + return OK;
|
| + }
|
| + UpdateTransactionPattern(PATTERN_ENTRY_UPDATED);
|
| + mode_ = WRITE;
|
| + }
|
| +
|
| + next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
|
| + return OK;
|
| }
|
|
|
| // We received 304 or 206 and we want to update the cached response headers.
|
| @@ -1570,6 +1660,44 @@ int HttpCache::Transaction::DoOverwriteCachedResponse() {
|
| return OK;
|
| }
|
|
|
| +int HttpCache::Transaction::DoCacheWriteResponse() {
|
| + // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
|
| + tracked_objects::ScopedTracker tracking_profile(
|
| + FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| + "422516 HttpCache::Transaction::DoCacheWriteResponse"));
|
| +
|
| + if (entry_) {
|
| + if (net_log_.IsCapturing())
|
| + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
|
| + }
|
| + return WriteResponseInfoToEntry(false);
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
|
| + if (entry_) {
|
| + if (net_log_.IsCapturing())
|
| + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
|
| + }
|
| + return WriteResponseInfoToEntry(true);
|
| +}
|
| +
|
| +int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
|
| + next_state_ = target_state_;
|
| + target_state_ = STATE_NONE;
|
| + if (!entry_)
|
| + return OK;
|
| + if (net_log_.IsCapturing()) {
|
| + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
|
| + result);
|
| + }
|
| +
|
| + // Balance the AddRef from WriteResponseInfoToEntry.
|
| + if (result != io_buf_len_) {
|
| + DLOG(ERROR) << "failed to write response info to cache";
|
| + DoneWritingToEntry(false);
|
| + }
|
| + return OK;
|
| +}
|
| int HttpCache::Transaction::DoTruncateCachedData() {
|
| next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
|
| if (!entry_)
|
| @@ -1637,142 +1765,6 @@ int HttpCache::Transaction::DoPartialHeadersReceived() {
|
| return OK;
|
| }
|
|
|
| -int HttpCache::Transaction::DoCacheReadResponse() {
|
| - DCHECK(entry_);
|
| - next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
|
| -
|
| - io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
|
| - read_buf_ = new IOBuffer(io_buf_len_);
|
| -
|
| - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
|
| - return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
|
| - io_buf_len_, io_callback_);
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
|
| - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
|
| - if (result != io_buf_len_ ||
|
| - !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_,
|
| - &response_, &truncated_)) {
|
| - return OnCacheReadError(result, true);
|
| - }
|
| -
|
| - // cert_cache() will be null if the CertCacheTrial field trial is disabled.
|
| - if (cache_->cert_cache() && response_.ssl_info.is_valid())
|
| - ReadCertChain();
|
| -
|
| - // Some resources may have slipped in as truncated when they're not.
|
| - int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
|
| - if (response_.headers->GetContentLength() == current_size)
|
| - truncated_ = false;
|
| -
|
| - if ((response_.unused_since_prefetch &&
|
| - !(request_->load_flags & LOAD_PREFETCH)) ||
|
| - (!response_.unused_since_prefetch &&
|
| - (request_->load_flags & LOAD_PREFETCH))) {
|
| - // Either this is the first use of an entry since it was prefetched or
|
| - // this is a prefetch. The value of response.unused_since_prefetch is valid
|
| - // for this transaction but the bit needs to be flipped in storage.
|
| - next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH;
|
| - return OK;
|
| - }
|
| -
|
| - next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
|
| - return OK;
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoCacheDispatchValidation() {
|
| - // We now have access to the cache entry.
|
| - //
|
| - // o if we are a reader for the transaction, then we can start reading the
|
| - // cache entry.
|
| - //
|
| - // o if we can read or write, then we should check if the cache entry needs
|
| - // to be validated and then issue a network request if needed or just read
|
| - // from the cache if the cache entry is already valid.
|
| - //
|
| - // o if we are set to UPDATE, then we are handling an externally
|
| - // conditionalized request (if-modified-since / if-none-match). We check
|
| - // if the request headers define a validation request.
|
| - //
|
| - int result = ERR_FAILED;
|
| - switch (mode_) {
|
| - case READ:
|
| - UpdateTransactionPattern(PATTERN_ENTRY_USED);
|
| - result = BeginCacheRead();
|
| - break;
|
| - case READ_WRITE:
|
| - result = BeginPartialCacheValidation();
|
| - break;
|
| - case UPDATE:
|
| - result = BeginExternallyConditionalizedRequest();
|
| - break;
|
| - case WRITE:
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch() {
|
| - // Write back the toggled value for the next use of this entry.
|
| - response_.unused_since_prefetch = !response_.unused_since_prefetch;
|
| -
|
| - // TODO(jkarlin): If DoUpdateCachedResponse is also called for this
|
| - // transaction then metadata will be written to cache twice. If prefetching
|
| - // becomes more common, consider combining the writes.
|
| - target_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE;
|
| - next_state_ = STATE_CACHE_WRITE_RESPONSE;
|
| - return OK;
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete(
|
| - int result) {
|
| - // Restore the original value for this transaction.
|
| - response_.unused_since_prefetch = !response_.unused_since_prefetch;
|
| - next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
|
| - return OK;
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoCacheWriteResponse() {
|
| - // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
|
| - tracked_objects::ScopedTracker tracking_profile(
|
| - FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| - "422516 HttpCache::Transaction::DoCacheWriteResponse"));
|
| -
|
| - if (entry_) {
|
| - if (net_log_.IsCapturing())
|
| - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
|
| - }
|
| - return WriteResponseInfoToEntry(false);
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
|
| - if (entry_) {
|
| - if (net_log_.IsCapturing())
|
| - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
|
| - }
|
| - return WriteResponseInfoToEntry(true);
|
| -}
|
| -
|
| -int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
|
| - next_state_ = target_state_;
|
| - target_state_ = STATE_NONE;
|
| - if (!entry_)
|
| - return OK;
|
| - if (net_log_.IsCapturing()) {
|
| - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
|
| - result);
|
| - }
|
| -
|
| - // Balance the AddRef from WriteResponseInfoToEntry.
|
| - if (result != io_buf_len_) {
|
| - DLOG(ERROR) << "failed to write response info to cache";
|
| - DoneWritingToEntry(false);
|
| - }
|
| - return OK;
|
| -}
|
| -
|
| int HttpCache::Transaction::DoCacheReadMetadata() {
|
| DCHECK(entry_);
|
| DCHECK(!response_.metadata.get());
|
| @@ -1795,17 +1787,24 @@ int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
|
| return OK;
|
| }
|
|
|
| -int HttpCache::Transaction::DoCacheQueryData() {
|
| - next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
|
| - return entry_->disk_entry->ReadyForSparseIO(io_callback_);
|
| +int HttpCache::Transaction::DoNetworkRead() {
|
| + next_state_ = STATE_NETWORK_READ_COMPLETE;
|
| + return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
|
| }
|
|
|
| -int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
|
| - DCHECK_EQ(OK, result);
|
| +int HttpCache::Transaction::DoNetworkReadComplete(int result) {
|
| + DCHECK(mode_ & WRITE || mode_ == NONE);
|
| +
|
| if (!cache_.get())
|
| return ERR_UNEXPECTED;
|
|
|
| - return ValidateEntryHeadersAndContinue();
|
| + // If there is an error or we aren't saving the data, we are done; just wait
|
| + // until the destructor runs to see if we can keep the data.
|
| + if (mode_ == NONE || result < 0)
|
| + return result;
|
| +
|
| + next_state_ = STATE_CACHE_WRITE_DATA;
|
| + return result;
|
| }
|
|
|
| int HttpCache::Transaction::DoCacheReadData() {
|
| @@ -2612,7 +2611,6 @@ int HttpCache::Transaction::SetupEntryForRead() {
|
| return OK;
|
| }
|
|
|
| -
|
| int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
|
| read_buf_ = data;
|
| io_buf_len_ = data_len;
|
|
|