Home | History | Annotate | Download | only in http
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/http/http_cache_transaction.h"
      6 
      7 #include "build/build_config.h"
      8 
      9 #if defined(OS_POSIX)
     10 #include <unistd.h>
     11 #endif
     12 
     13 #include <string>
     14 
     15 #include "base/compiler_specific.h"
     16 #include "base/memory/ref_counted.h"
     17 #include "base/metrics/field_trial.h"
     18 #include "base/metrics/histogram.h"
     19 #include "base/string_util.h"
     20 #include "base/time.h"
     21 #include "net/base/cert_status_flags.h"
     22 #include "net/base/io_buffer.h"
     23 #include "net/base/load_flags.h"
     24 #include "net/base/net_errors.h"
     25 #include "net/base/net_log.h"
     26 #include "net/base/network_delegate.h"
     27 #include "net/base/ssl_cert_request_info.h"
     28 #include "net/base/ssl_config_service.h"
     29 #include "net/disk_cache/disk_cache.h"
     30 #include "net/http/disk_cache_based_ssl_host_info.h"
     31 #include "net/http/http_network_session.h"
     32 #include "net/http/http_request_info.h"
     33 #include "net/http/http_response_headers.h"
     34 #include "net/http/http_transaction.h"
     35 #include "net/http/http_util.h"
     36 #include "net/http/partial_data.h"
     37 
     38 using base::Time;
     39 
     40 namespace net {
     41 
     42 struct HeaderNameAndValue {
     43   const char* name;
     44   const char* value;
     45 };
     46 
     47 // If the request includes one of these request headers, then avoid caching
     48 // to avoid getting confused.
     49 static const HeaderNameAndValue kPassThroughHeaders[] = {
     50   { "if-unmodified-since", NULL },  // causes unexpected 412s
     51   { "if-match", NULL },             // causes unexpected 412s
     52   { "if-range", NULL },
     53   { NULL, NULL }
     54 };
     55 
     56 struct ValidationHeaderInfo {
     57   const char* request_header_name;
     58   const char* related_response_header_name;
     59 };
     60 
     61 static const ValidationHeaderInfo kValidationHeaders[] = {
     62   { "if-modified-since", "last-modified" },
     63   { "if-none-match", "etag" },
     64 };
     65 
     66 // If the request includes one of these request headers, then avoid reusing
     67 // our cached copy if any.
     68 static const HeaderNameAndValue kForceFetchHeaders[] = {
     69   { "cache-control", "no-cache" },
     70   { "pragma", "no-cache" },
     71   { NULL, NULL }
     72 };
     73 
     74 // If the request includes one of these request headers, then force our
     75 // cached copy (if any) to be revalidated before reusing it.
     76 static const HeaderNameAndValue kForceValidateHeaders[] = {
     77   { "cache-control", "max-age=0" },
     78   { NULL, NULL }
     79 };
     80 
     81 static bool HeaderMatches(const HttpRequestHeaders& headers,
     82                           const HeaderNameAndValue* search) {
     83   for (; search->name; ++search) {
     84     std::string header_value;
     85     if (!headers.GetHeader(search->name, &header_value))
     86       continue;
     87 
     88     if (!search->value)
     89       return true;
     90 
     91     HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ',');
     92     while (v.GetNext()) {
     93       if (LowerCaseEqualsASCII(v.value_begin(), v.value_end(), search->value))
     94         return true;
     95     }
     96   }
     97   return false;
     98 }
     99 
    100 //-----------------------------------------------------------------------------
    101 
    102 HttpCache::Transaction::Transaction(HttpCache* cache)
    103     : next_state_(STATE_NONE),
    104       request_(NULL),
    105       cache_(cache->AsWeakPtr()),
    106       entry_(NULL),
    107       new_entry_(NULL),
    108       network_trans_(NULL),
    109       callback_(NULL),
    110       new_response_(NULL),
    111       mode_(NONE),
    112       target_state_(STATE_NONE),
    113       reading_(false),
    114       invalid_range_(false),
    115       truncated_(false),
    116       is_sparse_(false),
    117       server_responded_206_(false),
    118       cache_pending_(false),
    119       read_offset_(0),
    120       effective_load_flags_(0),
    121       write_len_(0),
    122       final_upload_progress_(0),
    123       ALLOW_THIS_IN_INITIALIZER_LIST(
    124           io_callback_(this, &Transaction::OnIOComplete)),
    125       ALLOW_THIS_IN_INITIALIZER_LIST(
    126           cache_callback_(new CancelableCompletionCallback<Transaction>(
    127               this, &Transaction::OnIOComplete))),
    128       ALLOW_THIS_IN_INITIALIZER_LIST(
    129           write_headers_callback_(new CancelableCompletionCallback<Transaction>(
    130               this, &Transaction::OnIOComplete))) {
    131   COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
    132                  arraysize(kValidationHeaders),
    133                  Invalid_number_of_validation_headers);
    134 }
    135 
    136 HttpCache::Transaction::~Transaction() {
    137   // We may have to issue another IO, but we should never invoke the callback_
    138   // after this point.
    139   callback_ = NULL;
    140 
    141   if (cache_) {
    142     if (entry_) {
    143       bool cancel_request = reading_;
    144       if (cancel_request) {
    145         if (partial_.get()) {
    146           entry_->disk_entry->CancelSparseIO();
    147         } else {
    148           cancel_request &= (response_.headers->response_code() == 200);
    149         }
    150       }
    151 
    152       cache_->DoneWithEntry(entry_, this, cancel_request);
    153     } else if (cache_pending_) {
    154       cache_->RemovePendingTransaction(this);
    155     }
    156   }
    157 
    158   // If there is an outstanding callback, mark it as cancelled so running it
    159   // does nothing.
    160   cache_callback_->Cancel();
    161   write_headers_callback_->Cancel();
    162 
    163   // We could still have a cache read or write in progress, so we just null the
    164   // cache_ pointer to signal that we are dead.  See DoCacheReadCompleted.
    165   cache_.reset();
    166 }
    167 
    168 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
    169                                           CompletionCallback* callback) {
    170   DCHECK(buf);
    171   DCHECK_GT(buf_len, 0);
    172   DCHECK(callback);
    173   if (!cache_ || !entry_)
    174     return ERR_UNEXPECTED;
    175 
    176   // We don't need to track this operation for anything.
    177   // It could be possible to check if there is something already written and
    178   // avoid writing again (it should be the same, right?), but let's allow the
    179   // caller to "update" the contents with something new.
    180   return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
    181                                        callback, true);
    182 }
    183 
    184 bool HttpCache::Transaction::AddTruncatedFlag() {
    185   DCHECK(mode_ & WRITE);
    186 
    187   // Don't set the flag for sparse entries.
    188   if (partial_.get() && !truncated_)
    189     return true;
    190 
    191   if (!CanResume(true))
    192     return false;
    193 
    194   truncated_ = true;
    195   target_state_ = STATE_NONE;
    196   next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
    197   DoLoop(OK);
    198   return true;
    199 }
    200 
    201 LoadState HttpCache::Transaction::GetWriterLoadState() const {
    202   if (network_trans_.get())
    203     return network_trans_->GetLoadState();
    204   if (entry_ || !request_)
    205     return LOAD_STATE_IDLE;
    206   return LOAD_STATE_WAITING_FOR_CACHE;
    207 }
    208 
    209 const BoundNetLog& HttpCache::Transaction::net_log() const {
    210   return net_log_;
    211 }
    212 
    213 int HttpCache::Transaction::Start(const HttpRequestInfo* request,
    214                                   CompletionCallback* callback,
    215                                   const BoundNetLog& net_log) {
    216   DCHECK(request);
    217   DCHECK(callback);
    218 
    219   // Ensure that we only have one asynchronous call at a time.
    220   DCHECK(!callback_);
    221   DCHECK(!reading_);
    222   DCHECK(!network_trans_.get());
    223   DCHECK(!entry_);
    224 
    225   if (!cache_)
    226     return ERR_UNEXPECTED;
    227 
    228   SetRequest(net_log, request);
    229 
    230   // We have to wait until the backend is initialized so we start the SM.
    231   next_state_ = STATE_GET_BACKEND;
    232   int rv = DoLoop(OK);
    233 
    234   // Setting this here allows us to check for the existence of a callback_ to
    235   // determine if we are still inside Start.
    236   if (rv == ERR_IO_PENDING)
    237     callback_ = callback;
    238 
    239   return rv;
    240 }
    241 
    242 int HttpCache::Transaction::RestartIgnoringLastError(
    243     CompletionCallback* callback) {
    244   DCHECK(callback);
    245 
    246   // Ensure that we only have one asynchronous call at a time.
    247   DCHECK(!callback_);
    248 
    249   if (!cache_)
    250     return ERR_UNEXPECTED;
    251 
    252   int rv = RestartNetworkRequest();
    253 
    254   if (rv == ERR_IO_PENDING)
    255     callback_ = callback;
    256 
    257   return rv;
    258 }
    259 
    260 int HttpCache::Transaction::RestartWithCertificate(
    261     X509Certificate* client_cert,
    262     CompletionCallback* callback) {
    263   DCHECK(callback);
    264 
    265   // Ensure that we only have one asynchronous call at a time.
    266   DCHECK(!callback_);
    267 
    268   if (!cache_)
    269     return ERR_UNEXPECTED;
    270 
    271   int rv = RestartNetworkRequestWithCertificate(client_cert);
    272 
    273   if (rv == ERR_IO_PENDING)
    274     callback_ = callback;
    275 
    276   return rv;
    277 }
    278 
    279 int HttpCache::Transaction::RestartWithAuth(
    280     const string16& username,
    281     const string16& password,
    282     CompletionCallback* callback) {
    283   DCHECK(auth_response_.headers);
    284   DCHECK(callback);
    285 
    286   // Ensure that we only have one asynchronous call at a time.
    287   DCHECK(!callback_);
    288 
    289   if (!cache_)
    290     return ERR_UNEXPECTED;
    291 
    292   // Clear the intermediate response since we are going to start over.
    293   auth_response_ = HttpResponseInfo();
    294 
    295   int rv = RestartNetworkRequestWithAuth(username, password);
    296 
    297   if (rv == ERR_IO_PENDING)
    298     callback_ = callback;
    299 
    300   return rv;
    301 }
    302 
    303 bool HttpCache::Transaction::IsReadyToRestartForAuth() {
    304   if (!network_trans_.get())
    305     return false;
    306   return network_trans_->IsReadyToRestartForAuth();
    307 }
    308 
    309 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
    310                                  CompletionCallback* callback) {
    311   DCHECK(buf);
    312   DCHECK_GT(buf_len, 0);
    313   DCHECK(callback);
    314 
    315   DCHECK(!callback_);
    316 
    317   if (!cache_)
    318     return ERR_UNEXPECTED;
    319 
    320   // If we have an intermediate auth response at this point, then it means the
    321   // user wishes to read the network response (the error page).  If there is a
    322   // previous response in the cache then we should leave it intact.
    323   if (auth_response_.headers && mode_ != NONE) {
    324     DCHECK(mode_ & WRITE);
    325     DoneWritingToEntry(mode_ == READ_WRITE);
    326     mode_ = NONE;
    327   }
    328 
    329   reading_ = true;
    330   int rv;
    331 
    332   switch (mode_) {
    333     case READ_WRITE:
    334       DCHECK(partial_.get());
    335       if (!network_trans_.get()) {
    336         // We are just reading from the cache, but we may be writing later.
    337         rv = ReadFromEntry(buf, buf_len);
    338         break;
    339       }
    340     case NONE:
    341     case WRITE:
    342       DCHECK(network_trans_.get());
    343       rv = ReadFromNetwork(buf, buf_len);
    344       break;
    345     case READ:
    346       rv = ReadFromEntry(buf, buf_len);
    347       break;
    348     default:
    349       NOTREACHED();
    350       rv = ERR_FAILED;
    351   }
    352 
    353   if (rv == ERR_IO_PENDING) {
    354     DCHECK(!callback_);
    355     callback_ = callback;
    356   }
    357   return rv;
    358 }
    359 
    360 void HttpCache::Transaction::StopCaching() {
    361 }
    362 
    363 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
    364   // Null headers means we encountered an error or haven't a response yet
    365   if (auth_response_.headers)
    366     return &auth_response_;
    367   return (response_.headers || response_.ssl_info.cert ||
    368           response_.cert_request_info) ? &response_ : NULL;
    369 }
    370 
    371 LoadState HttpCache::Transaction::GetLoadState() const {
    372   LoadState state = GetWriterLoadState();
    373   if (state != LOAD_STATE_WAITING_FOR_CACHE)
    374     return state;
    375 
    376   if (cache_)
    377     return cache_->GetLoadStateForPendingTransaction(this);
    378 
    379   return LOAD_STATE_IDLE;
    380 }
    381 
    382 uint64 HttpCache::Transaction::GetUploadProgress() const {
    383   if (network_trans_.get())
    384     return network_trans_->GetUploadProgress();
    385   return final_upload_progress_;
    386 }
    387 
    388 //-----------------------------------------------------------------------------
    389 
    390 void HttpCache::Transaction::DoCallback(int rv) {
    391   DCHECK(rv != ERR_IO_PENDING);
    392   DCHECK(callback_);
    393 
    394   // Since Run may result in Read being called, clear callback_ up front.
    395   CompletionCallback* c = callback_;
    396   callback_ = NULL;
    397   c->Run(rv);
    398 }
    399 
    400 int HttpCache::Transaction::HandleResult(int rv) {
    401   DCHECK(rv != ERR_IO_PENDING);
    402   if (callback_)
    403     DoCallback(rv);
    404   return rv;
    405 }
    406 
    407 int HttpCache::Transaction::DoLoop(int result) {
    408   DCHECK(next_state_ != STATE_NONE);
    409 
    410   int rv = result;
    411   do {
    412     State state = next_state_;
    413     next_state_ = STATE_NONE;
    414     switch (state) {
    415       case STATE_GET_BACKEND:
    416         DCHECK_EQ(OK, rv);
    417         rv = DoGetBackend();
    418         break;
    419       case STATE_GET_BACKEND_COMPLETE:
    420         rv = DoGetBackendComplete(rv);
    421         break;
    422       case STATE_SEND_REQUEST:
    423         DCHECK_EQ(OK, rv);
    424         rv = DoSendRequest();
    425         break;
    426       case STATE_SEND_REQUEST_COMPLETE:
    427         rv = DoSendRequestComplete(rv);
    428         break;
    429       case STATE_SUCCESSFUL_SEND_REQUEST:
    430         DCHECK_EQ(OK, rv);
    431         rv = DoSuccessfulSendRequest();
    432         break;
    433       case STATE_NETWORK_READ:
    434         DCHECK_EQ(OK, rv);
    435         rv = DoNetworkRead();
    436         break;
    437       case STATE_NETWORK_READ_COMPLETE:
    438         rv = DoNetworkReadComplete(rv);
    439         break;
    440       case STATE_INIT_ENTRY:
    441         DCHECK_EQ(OK, rv);
    442         rv = DoInitEntry();
    443         break;
    444       case STATE_OPEN_ENTRY:
    445         DCHECK_EQ(OK, rv);
    446         rv = DoOpenEntry();
    447         break;
    448       case STATE_OPEN_ENTRY_COMPLETE:
    449         rv = DoOpenEntryComplete(rv);
    450         break;
    451       case STATE_CREATE_ENTRY:
    452         DCHECK_EQ(OK, rv);
    453         rv = DoCreateEntry();
    454         break;
    455       case STATE_CREATE_ENTRY_COMPLETE:
    456         rv = DoCreateEntryComplete(rv);
    457         break;
    458       case STATE_DOOM_ENTRY:
    459         DCHECK_EQ(OK, rv);
    460         rv = DoDoomEntry();
    461         break;
    462       case STATE_DOOM_ENTRY_COMPLETE:
    463         rv = DoDoomEntryComplete(rv);
    464         break;
    465       case STATE_ADD_TO_ENTRY:
    466         DCHECK_EQ(OK, rv);
    467         rv = DoAddToEntry();
    468         break;
    469       case STATE_ADD_TO_ENTRY_COMPLETE:
    470         rv = DoAddToEntryComplete(rv);
    471         break;
    472       case STATE_NOTIFY_BEFORE_SEND_HEADERS:
    473         DCHECK_EQ(OK, rv);
    474         rv = DoNotifyBeforeSendHeaders();
    475         break;
    476       case STATE_NOTIFY_BEFORE_SEND_HEADERS_COMPLETE:
    477         rv = DoNotifyBeforeSendHeadersComplete(rv);
    478         break;
    479       case STATE_START_PARTIAL_CACHE_VALIDATION:
    480         DCHECK_EQ(OK, rv);
    481         rv = DoStartPartialCacheValidation();
    482         break;
    483       case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION:
    484         rv = DoCompletePartialCacheValidation(rv);
    485         break;
    486       case STATE_UPDATE_CACHED_RESPONSE:
    487         DCHECK_EQ(OK, rv);
    488         rv = DoUpdateCachedResponse();
    489         break;
    490       case STATE_UPDATE_CACHED_RESPONSE_COMPLETE:
    491         rv = DoUpdateCachedResponseComplete(rv);
    492         break;
    493       case STATE_OVERWRITE_CACHED_RESPONSE:
    494         DCHECK_EQ(OK, rv);
    495         rv = DoOverwriteCachedResponse();
    496         break;
    497       case STATE_TRUNCATE_CACHED_DATA:
    498         DCHECK_EQ(OK, rv);
    499         rv = DoTruncateCachedData();
    500         break;
    501       case STATE_TRUNCATE_CACHED_DATA_COMPLETE:
    502         rv = DoTruncateCachedDataComplete(rv);
    503         break;
    504       case STATE_TRUNCATE_CACHED_METADATA:
    505         DCHECK_EQ(OK, rv);
    506         rv = DoTruncateCachedMetadata();
    507         break;
    508       case STATE_TRUNCATE_CACHED_METADATA_COMPLETE:
    509         rv = DoTruncateCachedMetadataComplete(rv);
    510         break;
    511       case STATE_PARTIAL_HEADERS_RECEIVED:
    512         DCHECK_EQ(OK, rv);
    513         rv = DoPartialHeadersReceived();
    514         break;
    515       case STATE_CACHE_READ_RESPONSE:
    516         DCHECK_EQ(OK, rv);
    517         rv = DoCacheReadResponse();
    518         break;
    519       case STATE_CACHE_READ_RESPONSE_COMPLETE:
    520         rv = DoCacheReadResponseComplete(rv);
    521         break;
    522       case STATE_CACHE_WRITE_RESPONSE:
    523         DCHECK_EQ(OK, rv);
    524         rv = DoCacheWriteResponse();
    525         break;
    526       case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
    527         DCHECK_EQ(OK, rv);
    528         rv = DoCacheWriteTruncatedResponse();
    529         break;
    530       case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
    531         rv = DoCacheWriteResponseComplete(rv);
    532         break;
    533       case STATE_CACHE_READ_METADATA:
    534         DCHECK_EQ(OK, rv);
    535         rv = DoCacheReadMetadata();
    536         break;
    537       case STATE_CACHE_READ_METADATA_COMPLETE:
    538         rv = DoCacheReadMetadataComplete(rv);
    539         break;
    540       case STATE_CACHE_QUERY_DATA:
    541         DCHECK_EQ(OK, rv);
    542         rv = DoCacheQueryData();
    543         break;
    544       case STATE_CACHE_QUERY_DATA_COMPLETE:
    545         rv = DoCacheQueryDataComplete(rv);
    546         break;
    547       case STATE_CACHE_READ_DATA:
    548         DCHECK_EQ(OK, rv);
    549         rv = DoCacheReadData();
    550         break;
    551       case STATE_CACHE_READ_DATA_COMPLETE:
    552         rv = DoCacheReadDataComplete(rv);
    553         break;
    554       case STATE_CACHE_WRITE_DATA:
    555         rv = DoCacheWriteData(rv);
    556         break;
    557       case STATE_CACHE_WRITE_DATA_COMPLETE:
    558         rv = DoCacheWriteDataComplete(rv);
    559         break;
    560       default:
    561         NOTREACHED() << "bad state";
    562         rv = ERR_FAILED;
    563         break;
    564     }
    565   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    566 
    567   if (rv != ERR_IO_PENDING)
    568     HandleResult(rv);
    569 
    570   return rv;
    571 }
    572 
    573 int HttpCache::Transaction::DoGetBackend() {
    574   cache_pending_ = true;
    575   next_state_ = STATE_GET_BACKEND_COMPLETE;
    576   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND, NULL);
    577   return cache_->GetBackendForTransaction(this);
    578 }
    579 
    580 int HttpCache::Transaction::DoGetBackendComplete(int result) {
    581   DCHECK(result == OK || result == ERR_FAILED);
    582   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_GET_BACKEND,
    583                                     result);
    584   cache_pending_ = false;
    585 
    586   if (!ShouldPassThrough()) {
    587     cache_key_ = cache_->GenerateCacheKey(request_);
    588 
    589     // Requested cache access mode.
    590     if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
    591       mode_ = READ;
    592     } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
    593       mode_ = WRITE;
    594     } else {
    595       mode_ = READ_WRITE;
    596     }
    597 
    598     // Downgrade to UPDATE if the request has been externally conditionalized.
    599     if (external_validation_.initialized) {
    600       if (mode_ & WRITE) {
    601         // Strip off the READ_DATA bit (and maybe add back a READ_META bit
    602         // in case READ was off).
    603         mode_ = UPDATE;
    604       } else {
    605         mode_ = NONE;
    606       }
    607     }
    608   }
    609 
    610   // If must use cache, then we must fail.  This can happen for back/forward
    611   // navigations to a page generated via a form post.
    612   if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE)
    613     return ERR_CACHE_MISS;
    614 
    615   if (mode_ == NONE) {
    616     if (partial_.get())
    617       partial_->RestoreHeaders(&custom_request_->extra_headers);
    618     next_state_ = STATE_SEND_REQUEST;
    619   } else {
    620     next_state_ = STATE_INIT_ENTRY;
    621   }
    622 
    623   return OK;
    624 }
    625 
    626 int HttpCache::Transaction::DoSendRequest() {
    627   DCHECK(mode_ & WRITE || mode_ == NONE);
    628   DCHECK(!network_trans_.get());
    629 
    630   // Create a network transaction.
    631   int rv = cache_->network_layer_->CreateTransaction(&network_trans_);
    632   if (rv != OK)
    633     return rv;
    634 
    635   next_state_ = STATE_SEND_REQUEST_COMPLETE;
    636   rv = network_trans_->Start(request_, &io_callback_, net_log_);
    637   return rv;
    638 }
    639 
    640 int HttpCache::Transaction::DoSendRequestComplete(int result) {
    641   if (!cache_)
    642     return ERR_UNEXPECTED;
    643 
    644   if (result == OK) {
    645     next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
    646     return OK;
    647   }
    648 
    649   if (IsCertificateError(result)) {
    650     const HttpResponseInfo* response = network_trans_->GetResponseInfo();
    651     // If we get a certificate error, then there is a certificate in ssl_info,
    652     // so GetResponseInfo() should never returns NULL here.
    653     DCHECK(response);
    654     response_.ssl_info = response->ssl_info;
    655   } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
    656     const HttpResponseInfo* response = network_trans_->GetResponseInfo();
    657     DCHECK(response);
    658     response_.cert_request_info = response->cert_request_info;
    659   }
    660   return result;
    661 }
    662 
    663 // We received the response headers and there is no error.
    664 int HttpCache::Transaction::DoSuccessfulSendRequest() {
    665   DCHECK(!new_response_);
    666   const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
    667   if (new_response->headers->response_code() == 401 ||
    668       new_response->headers->response_code() == 407) {
    669     auth_response_ = *new_response;
    670     return OK;
    671   }
    672 
    673   new_response_ = new_response;
    674   if (!ValidatePartialResponse(&server_responded_206_) &&
    675       !auth_response_.headers) {
    676     // Something went wrong with this request and we have to restart it.
    677     // If we have an authentication response, we are exposed to weird things
    678     // hapenning if the user cancels the authentication before we receive
    679     // the new response.
    680     response_ = HttpResponseInfo();
    681     network_trans_.reset();
    682     new_response_ = NULL;
    683     next_state_ = STATE_SEND_REQUEST;
    684     return OK;
    685   }
    686   if (server_responded_206_ && mode_ == READ_WRITE && !truncated_ &&
    687       !is_sparse_) {
    688     // We have stored the full entry, but it changed and the server is
    689     // sending a range. We have to delete the old entry.
    690     DoneWritingToEntry(false);
    691   }
    692 
    693   if (new_response_->headers->response_code() == 416) {
    694     DCHECK_EQ(NONE, mode_);
    695     response_ = *new_response_;
    696     return OK;
    697   }
    698 
    699   // Are we expecting a response to a conditional query?
    700   if (mode_ == READ_WRITE || mode_ == UPDATE) {
    701     if (new_response->headers->response_code() == 304 ||
    702         server_responded_206_) {
    703       next_state_ = STATE_UPDATE_CACHED_RESPONSE;
    704       return OK;
    705     }
    706     mode_ = WRITE;
    707   }
    708 
    709   next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
    710   return OK;
    711 }
    712 
    713 int HttpCache::Transaction::DoNetworkRead() {
    714   next_state_ = STATE_NETWORK_READ_COMPLETE;
    715   return network_trans_->Read(read_buf_, io_buf_len_, &io_callback_);
    716 }
    717 
    718 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
    719   DCHECK(mode_ & WRITE || mode_ == NONE);
    720 
    721   if (!cache_)
    722     return ERR_UNEXPECTED;
    723 
    724   // If there is an error and we are saving the data, just tell the user about
    725   // it and wait until the destructor runs to see if we can keep the data.
    726   if (mode_ != NONE && result < 0)
    727     return result;
    728 
    729   next_state_ = STATE_CACHE_WRITE_DATA;
    730   return result;
    731 }
    732 
    733 int HttpCache::Transaction::DoInitEntry() {
    734   DCHECK(!new_entry_);
    735 
    736   if (!cache_)
    737     return ERR_UNEXPECTED;
    738 
    739   if (mode_ == WRITE) {
    740     next_state_ = STATE_DOOM_ENTRY;
    741     return OK;
    742   }
    743 
    744   next_state_ = STATE_OPEN_ENTRY;
    745   return OK;
    746 }
    747 
    748 int HttpCache::Transaction::DoOpenEntry() {
    749   DCHECK(!new_entry_);
    750   next_state_ = STATE_OPEN_ENTRY_COMPLETE;
    751   cache_pending_ = true;
    752   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, NULL);
    753   return cache_->OpenEntry(cache_key_, &new_entry_, this);
    754 }
    755 
    756 int HttpCache::Transaction::DoOpenEntryComplete(int result) {
    757   // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
    758   // OK, otherwise the cache will end up with an active entry without any
    759   // transaction attached.
    760   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
    761   cache_pending_ = false;
    762   if (result == OK) {
    763     next_state_ = STATE_ADD_TO_ENTRY;
    764     return OK;
    765   }
    766 
    767   if (result == ERR_CACHE_RACE) {
    768     next_state_ = STATE_INIT_ENTRY;
    769     return OK;
    770   }
    771 
    772   if (mode_ == READ_WRITE) {
    773     mode_ = WRITE;
    774     next_state_ = STATE_CREATE_ENTRY;
    775     return OK;
    776   }
    777   if (mode_ == UPDATE) {
    778     // There is no cache entry to update; proceed without caching.
    779     mode_ = NONE;
    780     next_state_ = STATE_SEND_REQUEST;
    781     return OK;
    782   }
    783   if (cache_->mode() == PLAYBACK)
    784     DVLOG(1) << "Playback Cache Miss: " << request_->url;
    785 
    786   // The entry does not exist, and we are not permitted to create a new entry,
    787   // so we must fail.
    788   return ERR_CACHE_MISS;
    789 }
    790 
    791 int HttpCache::Transaction::DoCreateEntry() {
    792   DCHECK(!new_entry_);
    793   next_state_ = STATE_CREATE_ENTRY_COMPLETE;
    794   cache_pending_ = true;
    795   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY, NULL);
    796   return cache_->CreateEntry(cache_key_, &new_entry_, this);
    797 }
    798 
    799 int HttpCache::Transaction::DoCreateEntryComplete(int result) {
    800   // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
    801   // OK, otherwise the cache will end up with an active entry without any
    802   // transaction attached.
    803   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
    804                                     result);
    805   cache_pending_ = false;
    806   next_state_ = STATE_ADD_TO_ENTRY;
    807 
    808   if (result == ERR_CACHE_RACE) {
    809     next_state_ = STATE_INIT_ENTRY;
    810     return OK;
    811   }
    812 
    813   if (result != OK) {
    814     // We have a race here: Maybe we failed to open the entry and decided to
    815     // create one, but by the time we called create, another transaction already
    816     // created the entry. If we want to eliminate this issue, we need an atomic
    817     // OpenOrCreate() method exposed by the disk cache.
    818     DLOG(WARNING) << "Unable to create cache entry";
    819     mode_ = NONE;
    820     if (partial_.get())
    821       partial_->RestoreHeaders(&custom_request_->extra_headers);
    822     next_state_ = STATE_SEND_REQUEST;
    823   }
    824   return OK;
    825 }
    826 
    827 int HttpCache::Transaction::DoDoomEntry() {
    828   next_state_ = STATE_DOOM_ENTRY_COMPLETE;
    829   cache_pending_ = true;
    830   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, NULL);
    831   return cache_->DoomEntry(cache_key_, this);
    832 }
    833 
    834 int HttpCache::Transaction::DoDoomEntryComplete(int result) {
    835   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result);
    836   next_state_ = STATE_CREATE_ENTRY;
    837   cache_pending_ = false;
    838   if (result == ERR_CACHE_RACE)
    839     next_state_ = STATE_INIT_ENTRY;
    840 
    841   return OK;
    842 }
    843 
    844 int HttpCache::Transaction::DoAddToEntry() {
    845   DCHECK(new_entry_);
    846   cache_pending_ = true;
    847   next_state_ = STATE_ADD_TO_ENTRY_COMPLETE;
    848   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY, NULL);
    849   DCHECK(entry_lock_waiting_since_.is_null());
    850   entry_lock_waiting_since_ = base::TimeTicks::Now();
    851   return cache_->AddTransactionToEntry(new_entry_, this);
    852 }
    853 
    854 int HttpCache::Transaction::DoAddToEntryComplete(int result) {
    855   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY,
    856                                     result);
    857 
    858   const base::TimeDelta entry_lock_wait =
    859       base::TimeTicks::Now() - entry_lock_waiting_since_;
    860   UMA_HISTOGRAM_TIMES("HttpCache.EntryLockWait", entry_lock_wait);
    861   static const bool prefetching_fieldtrial =
    862       base::FieldTrialList::Find("Prefetch") &&
    863       !base::FieldTrialList::Find("Prefetch")->group_name().empty();
    864   if (prefetching_fieldtrial) {
    865     UMA_HISTOGRAM_TIMES(
    866         base::FieldTrial::MakeName("HttpCache.EntryLockWait", "Prefetch"),
    867         entry_lock_wait);
    868   }
    869 
    870   entry_lock_waiting_since_ = base::TimeTicks();
    871   DCHECK(new_entry_);
    872   cache_pending_ = false;
    873 
    874   if (result == ERR_CACHE_RACE) {
    875     new_entry_ = NULL;
    876     next_state_ = STATE_INIT_ENTRY;
    877     return OK;
    878   }
    879 
    880   if (result != OK) {
    881     // If there is a failure, the cache should have taken care of new_entry_.
    882     NOTREACHED();
    883     new_entry_ = NULL;
    884     return result;
    885   }
    886 
    887   entry_ = new_entry_;
    888   new_entry_ = NULL;
    889 
    890   if (mode_ == WRITE) {
    891     if (partial_.get())
    892       partial_->RestoreHeaders(&custom_request_->extra_headers);
    893     next_state_ = STATE_SEND_REQUEST;
    894   } else {
    895     // We have to read the headers from the cached entry.
    896     DCHECK(mode_ & READ_META);
    897     next_state_ = STATE_CACHE_READ_RESPONSE;
    898   }
    899   return OK;
    900 }
    901 
    902 int HttpCache::Transaction::DoNotifyBeforeSendHeaders() {
    903   // Balanced in DoNotifyBeforeSendHeadersComplete.
    904   cache_callback_->AddRef();
    905   next_state_ = STATE_NOTIFY_BEFORE_SEND_HEADERS_COMPLETE;
    906 
    907   if (cache_->GetSession() && cache_->GetSession()->network_delegate()) {
    908     // TODO(mpcomplete): need to be able to modify these headers.
    909     HttpRequestHeaders headers = request_->extra_headers;
    910     return cache_->GetSession()->network_delegate()->NotifyBeforeSendHeaders(
    911         request_->request_id, cache_callback_, &headers);
    912   }
    913 
    914   return OK;
    915 }
    916 
    917 int HttpCache::Transaction::DoNotifyBeforeSendHeadersComplete(int result) {
    918   cache_callback_->Release();  // Balanced in DoNotifyBeforeSendHeaders.
    919 
    920   // We now have access to the cache entry.
    921   //
    922   //  o if we are a reader for the transaction, then we can start reading the
    923   //    cache entry.
    924   //
    925   //  o if we can read or write, then we should check if the cache entry needs
    926   //    to be validated and then issue a network request if needed or just read
    927   //    from the cache if the cache entry is already valid.
    928   //
    929   //  o if we are set to UPDATE, then we are handling an externally
    930   //    conditionalized request (if-modified-since / if-none-match). We check
    931   //    if the request headers define a validation request.
    932   //
    933   if (result == net::OK) {
    934     switch (mode_) {
    935       case READ:
    936         result = BeginCacheRead();
    937         break;
    938       case READ_WRITE:
    939         result = BeginPartialCacheValidation();
    940         break;
    941       case UPDATE:
    942         result = BeginExternallyConditionalizedRequest();
    943         break;
    944       case WRITE:
    945       default:
    946         NOTREACHED();
    947         result = ERR_FAILED;
    948     }
    949   }
    950   return result;
    951 }
    952 
    953 // We may end up here multiple times for a given request.
    954 int HttpCache::Transaction::DoStartPartialCacheValidation() {
    955   if (mode_ == NONE)
    956     return OK;
    957 
    958   next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
    959   return partial_->ShouldValidateCache(entry_->disk_entry, &io_callback_);
    960 }
    961 
    962 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
    963   if (!result) {
    964     // This is the end of the request.
    965     if (mode_ & WRITE) {
    966       DoneWritingToEntry(true);
    967     } else {
    968       cache_->DoneReadingFromEntry(entry_, this);
    969       entry_ = NULL;
    970     }
    971     return result;
    972   }
    973 
    974   if (result < 0)
    975     return result;
    976 
    977   partial_->PrepareCacheValidation(entry_->disk_entry,
    978                                    &custom_request_->extra_headers);
    979 
    980   if (reading_ && partial_->IsCurrentRangeCached()) {
    981     next_state_ = STATE_CACHE_READ_DATA;
    982     return OK;
    983   }
    984 
    985   return BeginCacheValidation();
    986 }
    987 
    988 // We received 304 or 206 and we want to update the cached response headers.
    989 int HttpCache::Transaction::DoUpdateCachedResponse() {
    990   next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
    991   int rv = OK;
    992   // Update cached response based on headers in new_response.
    993   // TODO(wtc): should we update cached certificate (response_.ssl_info), too?
    994   response_.headers->Update(*new_response_->headers);
    995   response_.response_time = new_response_->response_time;
    996   response_.request_time = new_response_->request_time;
    997 
    998   if (response_.headers->HasHeaderValue("cache-control", "no-store")) {
    999     int ret = cache_->DoomEntry(cache_key_, NULL);
   1000     DCHECK_EQ(OK, ret);
   1001   } else {
   1002     // If we are already reading, we already updated the headers for this
   1003     // request; doing it again will change Content-Length.
   1004     if (!reading_) {
   1005       target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
   1006       next_state_ = STATE_CACHE_WRITE_RESPONSE;
   1007       rv = OK;
   1008     }
   1009   }
   1010   return rv;
   1011 }
   1012 
   1013 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
   1014   if (mode_ == UPDATE) {
   1015     DCHECK(!server_responded_206_);
   1016     // We got a "not modified" response and already updated the corresponding
   1017     // cache entry above.
   1018     //
   1019     // By closing the cached entry now, we make sure that the 304 rather than
   1020     // the cached 200 response, is what will be returned to the user.
   1021     DoneWritingToEntry(true);
   1022   } else if (entry_ && !server_responded_206_) {
   1023     DCHECK_EQ(READ_WRITE, mode_);
   1024     if (!partial_.get() || partial_->IsLastRange()) {
   1025       cache_->ConvertWriterToReader(entry_);
   1026       mode_ = READ;
   1027     }
   1028     // We no longer need the network transaction, so destroy it.
   1029     final_upload_progress_ = network_trans_->GetUploadProgress();
   1030     network_trans_.reset();
   1031   } else if (entry_ && server_responded_206_ && truncated_ &&
   1032              partial_->initial_validation()) {
   1033     // We just finished the validation of a truncated entry, and the server
   1034     // is willing to resume the operation. Now we go back and start serving
   1035     // the first part to the user.
   1036     network_trans_.reset();
   1037     new_response_ = NULL;
   1038     next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   1039     partial_->SetRangeToStartDownload();
   1040     return OK;
   1041   }
   1042   next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
   1043   return OK;
   1044 }
   1045 
   1046 int HttpCache::Transaction::DoOverwriteCachedResponse() {
   1047   if (mode_ & READ) {
   1048     next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   1049     return OK;
   1050   }
   1051 
   1052   // We change the value of Content-Length for partial content.
   1053   if (server_responded_206_ && partial_.get())
   1054     partial_->FixContentLength(new_response_->headers);
   1055 
   1056   response_ = *new_response_;
   1057 
   1058   if (server_responded_206_ && !CanResume(false)) {
   1059     // There is no point in storing this resource because it will never be used.
   1060     DoneWritingToEntry(false);
   1061     if (partial_.get())
   1062       partial_->FixResponseHeaders(response_.headers, true);
   1063     next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   1064     return OK;
   1065   }
   1066 
   1067   target_state_ = STATE_TRUNCATE_CACHED_DATA;
   1068   next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE :
   1069                              STATE_CACHE_WRITE_RESPONSE;
   1070   return OK;
   1071 }
   1072 
   1073 int HttpCache::Transaction::DoTruncateCachedData() {
   1074   next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
   1075   cache_callback_->AddRef();  // Balanced in DoTruncateCachedDataComplete.
   1076   if (!entry_)
   1077     return OK;
   1078   if (net_log_.IsLoggingAllEvents())
   1079     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, NULL);
   1080 
   1081   // Truncate the stream.
   1082   return WriteToEntry(kResponseContentIndex, 0, NULL, 0, cache_callback_);
   1083 }
   1084 
   1085 int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
   1086   if (net_log_.IsLoggingAllEvents() && entry_) {
   1087     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
   1088                                       result);
   1089   }
   1090 
   1091   // Balance the AddRef from DoTruncateCachedData.
   1092   cache_callback_->Release();
   1093   next_state_ = STATE_TRUNCATE_CACHED_METADATA;
   1094   return OK;
   1095 }
   1096 
   1097 int HttpCache::Transaction::DoTruncateCachedMetadata() {
   1098   next_state_ = STATE_TRUNCATE_CACHED_METADATA_COMPLETE;
   1099   cache_callback_->AddRef();  // Balanced in DoTruncateCachedMetadataComplete.
   1100   if (!entry_)
   1101     return OK;
   1102 
   1103   if (net_log_.IsLoggingAllEvents())
   1104     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, NULL);
   1105   return WriteToEntry(kMetadataIndex, 0, NULL, 0, cache_callback_);
   1106 }
   1107 
   1108 int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) {
   1109   if (net_log_.IsLoggingAllEvents() && entry_) {
   1110     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
   1111                                       result);
   1112   }
   1113 
   1114   // Balance the AddRef from DoTruncateCachedMetadata.
   1115   cache_callback_->Release();
   1116 
   1117   // If this response is a redirect, then we can stop writing now.  (We don't
   1118   // need to cache the response body of a redirect.)
   1119   if (response_.headers->IsRedirect(NULL))
   1120     DoneWritingToEntry(true);
   1121   next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   1122   return OK;
   1123 }
   1124 
   1125 int HttpCache::Transaction::DoPartialHeadersReceived() {
   1126   new_response_ = NULL;
   1127   if (entry_ && !partial_.get() &&
   1128       entry_->disk_entry->GetDataSize(kMetadataIndex))
   1129     next_state_ = STATE_CACHE_READ_METADATA;
   1130 
   1131   if (!partial_.get())
   1132     return OK;
   1133 
   1134   if (reading_) {
   1135     if (network_trans_.get()) {
   1136       next_state_ = STATE_NETWORK_READ;
   1137     } else {
   1138       next_state_ = STATE_CACHE_READ_DATA;
   1139     }
   1140   } else if (mode_ != NONE) {
   1141     // We are about to return the headers for a byte-range request to the user,
   1142     // so let's fix them.
   1143     partial_->FixResponseHeaders(response_.headers, true);
   1144   }
   1145   return OK;
   1146 }
   1147 
   1148 int HttpCache::Transaction::DoCacheReadResponse() {
   1149   DCHECK(entry_);
   1150   next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
   1151 
   1152   io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
   1153   read_buf_ = new IOBuffer(io_buf_len_);
   1154 
   1155   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO, NULL);
   1156   cache_callback_->AddRef();  // Balanced in DoCacheReadResponseComplete.
   1157   return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_,
   1158                                       io_buf_len_, cache_callback_);
   1159 }
   1160 
   1161 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
   1162   cache_callback_->Release();  // Balance the AddRef from DoCacheReadResponse.
   1163 
   1164   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
   1165   if (result != io_buf_len_ ||
   1166       !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_,
   1167                                     &response_, &truncated_)) {
   1168     DLOG(ERROR) << "ReadData failed: " << result;
   1169     return ERR_CACHE_READ_FAILURE;
   1170   }
   1171 
   1172   next_state_ = STATE_NOTIFY_BEFORE_SEND_HEADERS;
   1173   return OK;
   1174 }
   1175 
   1176 int HttpCache::Transaction::DoCacheWriteResponse() {
   1177   if (net_log_.IsLoggingAllEvents() && entry_)
   1178     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, NULL);
   1179   return WriteResponseInfoToEntry(false);
   1180 }
   1181 
   1182 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
   1183   if (net_log_.IsLoggingAllEvents() && entry_)
   1184     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, NULL);
   1185   return WriteResponseInfoToEntry(true);
   1186 }
   1187 
   1188 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
   1189   next_state_ = target_state_;
   1190   target_state_ = STATE_NONE;
   1191   if (!entry_)
   1192     return OK;
   1193   if (net_log_.IsLoggingAllEvents()) {
   1194     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
   1195                                       result);
   1196   }
   1197 
   1198   // Balance the AddRef from WriteResponseInfoToEntry.
   1199   write_headers_callback_->Release();
   1200   if (result != io_buf_len_) {
   1201     DLOG(ERROR) << "failed to write response info to cache";
   1202     DoneWritingToEntry(false);
   1203   }
   1204   return OK;
   1205 }
   1206 
   1207 int HttpCache::Transaction::DoCacheReadMetadata() {
   1208   DCHECK(entry_);
   1209   DCHECK(!response_.metadata);
   1210   next_state_ = STATE_CACHE_READ_METADATA_COMPLETE;
   1211 
   1212   response_.metadata =
   1213       new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex));
   1214 
   1215   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO, NULL);
   1216   cache_callback_->AddRef();  // Balanced in DoCacheReadMetadataComplete.
   1217   return entry_->disk_entry->ReadData(kMetadataIndex, 0, response_.metadata,
   1218                                       response_.metadata->size(),
   1219                                       cache_callback_);
   1220 }
   1221 
   1222 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
   1223   cache_callback_->Release();  // Balance the AddRef from DoCacheReadMetadata.
   1224   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
   1225   if (result != response_.metadata->size()) {
   1226     DLOG(ERROR) << "ReadData failed: " << result;
   1227     return ERR_CACHE_READ_FAILURE;
   1228   }
   1229 
   1230   return OK;
   1231 }
   1232 
   1233 int HttpCache::Transaction::DoCacheQueryData() {
   1234   next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
   1235 
   1236   // Balanced in ValidateEntryHeadersAndContinue.
   1237   cache_callback_->AddRef();
   1238   return entry_->disk_entry->ReadyForSparseIO(cache_callback_);
   1239 }
   1240 
   1241 int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
   1242   DCHECK_EQ(OK, result);
   1243   // Balance the AddRef from BeginPartialCacheValidation.
   1244   cache_callback_->Release();
   1245   if (!cache_)
   1246     return ERR_UNEXPECTED;
   1247 
   1248   return ValidateEntryHeadersAndContinue(true);
   1249 }
   1250 
   1251 int HttpCache::Transaction::DoCacheReadData() {
   1252   DCHECK(entry_);
   1253   next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
   1254   cache_callback_->AddRef();  // Balanced in DoCacheReadDataComplete.
   1255 
   1256   if (net_log_.IsLoggingAllEvents())
   1257     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA, NULL);
   1258   if (partial_.get()) {
   1259     return partial_->CacheRead(entry_->disk_entry, read_buf_, io_buf_len_,
   1260                                cache_callback_);
   1261   }
   1262 
   1263   return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_,
   1264                                       read_buf_, io_buf_len_, cache_callback_);
   1265 }
   1266 
   1267 int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
   1268   cache_callback_->Release();  // Balance the AddRef from DoCacheReadData.
   1269   if (net_log_.IsLoggingAllEvents()) {
   1270     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
   1271                                       result);
   1272   }
   1273 
   1274   if (!cache_)
   1275     return ERR_UNEXPECTED;
   1276 
   1277   if (partial_.get())
   1278     return DoPartialCacheReadCompleted(result);
   1279 
   1280   if (result > 0) {
   1281     read_offset_ += result;
   1282   } else if (result == 0) {  // End of file.
   1283     cache_->DoneReadingFromEntry(entry_, this);
   1284     entry_ = NULL;
   1285   }
   1286   return result;
   1287 }
   1288 
   1289 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
   1290   next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
   1291   write_len_ = num_bytes;
   1292   if (net_log_.IsLoggingAllEvents() && entry_)
   1293     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, NULL);
   1294   cache_callback_->AddRef();  // Balanced in DoCacheWriteDataComplete.
   1295 
   1296   return AppendResponseDataToEntry(read_buf_, num_bytes, cache_callback_);
   1297 }
   1298 
   1299 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
   1300   if (net_log_.IsLoggingAllEvents() && entry_) {
   1301     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
   1302                                       result);
   1303   }
   1304   // Balance the AddRef from DoCacheWriteData.
   1305   cache_callback_->Release();
   1306   if (!cache_)
   1307     return ERR_UNEXPECTED;
   1308 
   1309   if (result != write_len_) {
   1310     DLOG(ERROR) << "failed to write response data to cache";
   1311     DoneWritingToEntry(false);
   1312 
   1313     // We want to ignore errors writing to disk and just keep reading from
   1314     // the network.
   1315     result = write_len_;
   1316   }
   1317 
   1318   if (partial_.get()) {
   1319     // This may be the last request.
   1320     if (!(result == 0 && !truncated_ &&
   1321           (partial_->IsLastRange() || mode_ == WRITE)))
   1322       return DoPartialNetworkReadCompleted(result);
   1323   }
   1324 
   1325   if (result == 0)  // End of file.
   1326     DoneWritingToEntry(true);
   1327 
   1328   return result;
   1329 }
   1330 
   1331 //-----------------------------------------------------------------------------
   1332 
   1333 void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log,
   1334                                         const HttpRequestInfo* request) {
   1335   net_log_ = net_log;
   1336   request_ = request;
   1337   effective_load_flags_ = request_->load_flags;
   1338 
   1339   switch (cache_->mode()) {
   1340     case NORMAL:
   1341       break;
   1342     case RECORD:
   1343       // When in record mode, we want to NEVER load from the cache.
   1344       // The reason for this is beacuse we save the Set-Cookie headers
   1345       // (intentionally).  If we read from the cache, we replay them
   1346       // prematurely.
   1347       effective_load_flags_ |= LOAD_BYPASS_CACHE;
   1348       break;
   1349     case PLAYBACK:
   1350       // When in playback mode, we want to load exclusively from the cache.
   1351       effective_load_flags_ |= LOAD_ONLY_FROM_CACHE;
   1352       break;
   1353     case DISABLE:
   1354       effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1355       break;
   1356   }
   1357 
   1358   // Some headers imply load flags.  The order here is significant.
   1359   //
   1360   //   LOAD_DISABLE_CACHE   : no cache read or write
   1361   //   LOAD_BYPASS_CACHE    : no cache read
   1362   //   LOAD_VALIDATE_CACHE  : no cache read unless validation
   1363   //
   1364   // The former modes trump latter modes, so if we find a matching header we
   1365   // can stop iterating kSpecialHeaders.
   1366   //
   1367   static const struct {
   1368     const HeaderNameAndValue* search;
   1369     int load_flag;
   1370   } kSpecialHeaders[] = {
   1371     { kPassThroughHeaders, LOAD_DISABLE_CACHE },
   1372     { kForceFetchHeaders, LOAD_BYPASS_CACHE },
   1373     { kForceValidateHeaders, LOAD_VALIDATE_CACHE },
   1374   };
   1375 
   1376   bool range_found = false;
   1377   bool external_validation_error = false;
   1378 
   1379   if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange))
   1380     range_found = true;
   1381 
   1382   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSpecialHeaders); ++i) {
   1383     if (HeaderMatches(request_->extra_headers, kSpecialHeaders[i].search)) {
   1384       effective_load_flags_ |= kSpecialHeaders[i].load_flag;
   1385       break;
   1386     }
   1387   }
   1388 
   1389   // Check for conditionalization headers which may correspond with a
   1390   // cache validation request.
   1391   for (size_t i = 0; i < arraysize(kValidationHeaders); ++i) {
   1392     const ValidationHeaderInfo& info = kValidationHeaders[i];
   1393     std::string validation_value;
   1394     if (request_->extra_headers.GetHeader(
   1395             info.request_header_name, &validation_value)) {
   1396       if (!external_validation_.values[i].empty() ||
   1397           validation_value.empty())
   1398         external_validation_error = true;
   1399       external_validation_.values[i] = validation_value;
   1400       external_validation_.initialized = true;
   1401       break;
   1402     }
   1403   }
   1404 
   1405   // We don't support ranges and validation headers.
   1406   if (range_found && external_validation_.initialized) {
   1407     LOG(WARNING) << "Byte ranges AND validation headers found.";
   1408     effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1409   }
   1410 
   1411   // If there is more than one validation header, we can't treat this request as
   1412   // a cache validation, since we don't know for sure which header the server
   1413   // will give us a response for (and they could be contradictory).
   1414   if (external_validation_error) {
   1415     LOG(WARNING) << "Multiple or malformed validation headers found.";
   1416     effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1417   }
   1418 
   1419   if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
   1420     partial_.reset(new PartialData);
   1421     if (partial_->Init(request_->extra_headers)) {
   1422       // We will be modifying the actual range requested to the server, so
   1423       // let's remove the header here.
   1424       custom_request_.reset(new HttpRequestInfo(*request_));
   1425       custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
   1426       request_ = custom_request_.get();
   1427       partial_->SetHeaders(custom_request_->extra_headers);
   1428     } else {
   1429       // The range is invalid or we cannot handle it properly.
   1430       VLOG(1) << "Invalid byte range found.";
   1431       effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1432       partial_.reset(NULL);
   1433     }
   1434   }
   1435 }
   1436 
   1437 bool HttpCache::Transaction::ShouldPassThrough() {
   1438   // We may have a null disk_cache if there is an error we cannot recover from,
   1439   // like not enough disk space, or sharing violations.
   1440   if (!cache_->disk_cache_.get())
   1441     return true;
   1442 
   1443   // When using the record/playback modes, we always use the cache
   1444   // and we never pass through.
   1445   if (cache_->mode() == RECORD || cache_->mode() == PLAYBACK)
   1446     return false;
   1447 
   1448   if (effective_load_flags_ & LOAD_DISABLE_CACHE)
   1449     return true;
   1450 
   1451   if (request_->method == "GET")
   1452     return false;
   1453 
   1454   if (request_->method == "POST" &&
   1455       request_->upload_data && request_->upload_data->identifier())
   1456     return false;
   1457 
   1458   // TODO(darin): add support for caching HEAD responses
   1459   return true;
   1460 }
   1461 
   1462 int HttpCache::Transaction::BeginCacheRead() {
   1463   // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges.
   1464   if (response_.headers->response_code() == 206 || partial_.get()) {
   1465     NOTREACHED();
   1466     return ERR_CACHE_MISS;
   1467   }
   1468 
   1469   // We don't have the whole resource.
   1470   if (truncated_)
   1471     return ERR_CACHE_MISS;
   1472 
   1473   if (entry_->disk_entry->GetDataSize(kMetadataIndex))
   1474     next_state_ = STATE_CACHE_READ_METADATA;
   1475 
   1476   return OK;
   1477 }
   1478 
   1479 int HttpCache::Transaction::BeginCacheValidation() {
   1480   DCHECK(mode_ == READ_WRITE);
   1481 
   1482   bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE ||
   1483                          !RequiresValidation();
   1484 
   1485   if (truncated_)
   1486     skip_validation = !partial_->initial_validation();
   1487 
   1488   if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_)
   1489     skip_validation = false;
   1490 
   1491   if (skip_validation) {
   1492     if (partial_.get()) {
   1493       // We are going to return the saved response headers to the caller, so
   1494       // we may need to adjust them first.
   1495       next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   1496       return OK;
   1497     }
   1498     cache_->ConvertWriterToReader(entry_);
   1499     mode_ = READ;
   1500 
   1501     if (entry_ && entry_->disk_entry->GetDataSize(kMetadataIndex))
   1502       next_state_ = STATE_CACHE_READ_METADATA;
   1503   } else {
   1504     // Make the network request conditional, to see if we may reuse our cached
   1505     // response.  If we cannot do so, then we just resort to a normal fetch.
   1506     // Our mode remains READ_WRITE for a conditional request.  We'll switch to
   1507     // either READ or WRITE mode once we hear back from the server.
   1508     if (!ConditionalizeRequest()) {
   1509       DCHECK(!partial_.get());
   1510       DCHECK_NE(206, response_.headers->response_code());
   1511       mode_ = WRITE;
   1512     }
   1513     next_state_ = STATE_SEND_REQUEST;
   1514   }
   1515   return OK;
   1516 }
   1517 
   1518 int HttpCache::Transaction::BeginPartialCacheValidation() {
   1519   DCHECK(mode_ == READ_WRITE);
   1520 
   1521   if (response_.headers->response_code() != 206 && !partial_.get() &&
   1522       !truncated_)
   1523     return BeginCacheValidation();
   1524 
   1525   bool byte_range_requested = partial_.get() != NULL;
   1526   if (byte_range_requested) {
   1527     next_state_ = STATE_CACHE_QUERY_DATA;
   1528     return OK;
   1529   }
   1530   // The request is not for a range, but we have stored just ranges.
   1531   partial_.reset(new PartialData());
   1532   partial_->SetHeaders(request_->extra_headers);
   1533   if (!custom_request_.get()) {
   1534     custom_request_.reset(new HttpRequestInfo(*request_));
   1535     request_ = custom_request_.get();
   1536   }
   1537 
   1538   return ValidateEntryHeadersAndContinue(false);
   1539 }
   1540 
   1541 // This should only be called once per request.
   1542 int HttpCache::Transaction::ValidateEntryHeadersAndContinue(
   1543     bool byte_range_requested) {
   1544   DCHECK(mode_ == READ_WRITE);
   1545 
   1546   if (!partial_->UpdateFromStoredHeaders(response_.headers, entry_->disk_entry,
   1547                                          truncated_)) {
   1548     // The stored data cannot be used. Get rid of it and restart this request.
   1549     // We need to also reset the |truncated_| flag as a new entry is created.
   1550     DoomPartialEntry(!byte_range_requested);
   1551     mode_ = WRITE;
   1552     truncated_ = false;
   1553     next_state_ = STATE_INIT_ENTRY;
   1554     return OK;
   1555   }
   1556 
   1557   if (response_.headers->response_code() == 206)
   1558     is_sparse_ = true;
   1559 
   1560   if (!partial_->IsRequestedRangeOK()) {
   1561     // The stored data is fine, but the request may be invalid.
   1562     invalid_range_ = true;
   1563   }
   1564 
   1565   next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   1566   return OK;
   1567 }
   1568 
   1569 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
   1570   DCHECK_EQ(UPDATE, mode_);
   1571   DCHECK(external_validation_.initialized);
   1572 
   1573   for (size_t i = 0;  i < arraysize(kValidationHeaders); i++) {
   1574     if (external_validation_.values[i].empty())
   1575       continue;
   1576     // Retrieve either the cached response's "etag" or "last-modified" header.
   1577     std::string validator;
   1578     response_.headers->EnumerateHeader(
   1579         NULL,
   1580         kValidationHeaders[i].related_response_header_name,
   1581         &validator);
   1582 
   1583     if (response_.headers->response_code() != 200 || truncated_ ||
   1584         validator.empty() || validator != external_validation_.values[i]) {
   1585       // The externally conditionalized request is not a validation request
   1586       // for our existing cache entry. Proceed with caching disabled.
   1587       DoneWritingToEntry(true);
   1588     }
   1589   }
   1590 
   1591   next_state_ = STATE_SEND_REQUEST;
   1592   return OK;
   1593 }
   1594 
   1595 int HttpCache::Transaction::RestartNetworkRequest() {
   1596   DCHECK(mode_ & WRITE || mode_ == NONE);
   1597   DCHECK(network_trans_.get());
   1598   DCHECK_EQ(STATE_NONE, next_state_);
   1599 
   1600   next_state_ = STATE_SEND_REQUEST_COMPLETE;
   1601   int rv = network_trans_->RestartIgnoringLastError(&io_callback_);
   1602   if (rv != ERR_IO_PENDING)
   1603     return DoLoop(rv);
   1604   return rv;
   1605 }
   1606 
   1607 int HttpCache::Transaction::RestartNetworkRequestWithCertificate(
   1608     X509Certificate* client_cert) {
   1609   DCHECK(mode_ & WRITE || mode_ == NONE);
   1610   DCHECK(network_trans_.get());
   1611   DCHECK_EQ(STATE_NONE, next_state_);
   1612 
   1613   next_state_ = STATE_SEND_REQUEST_COMPLETE;
   1614   int rv = network_trans_->RestartWithCertificate(client_cert, &io_callback_);
   1615   if (rv != ERR_IO_PENDING)
   1616     return DoLoop(rv);
   1617   return rv;
   1618 }
   1619 
   1620 int HttpCache::Transaction::RestartNetworkRequestWithAuth(
   1621     const string16& username,
   1622     const string16& password) {
   1623   DCHECK(mode_ & WRITE || mode_ == NONE);
   1624   DCHECK(network_trans_.get());
   1625   DCHECK_EQ(STATE_NONE, next_state_);
   1626 
   1627   next_state_ = STATE_SEND_REQUEST_COMPLETE;
   1628   int rv = network_trans_->RestartWithAuth(username, password, &io_callback_);
   1629   if (rv != ERR_IO_PENDING)
   1630     return DoLoop(rv);
   1631   return rv;
   1632 }
   1633 
   1634 bool HttpCache::Transaction::RequiresValidation() {
   1635   // TODO(darin): need to do more work here:
   1636   //  - make sure we have a matching request method
   1637   //  - watch out for cached responses that depend on authentication
   1638   // In playback mode, nothing requires validation.
   1639   if (cache_->mode() == net::HttpCache::PLAYBACK)
   1640     return false;
   1641 
   1642   if (effective_load_flags_ & LOAD_VALIDATE_CACHE)
   1643     return true;
   1644 
   1645   if (response_.headers->RequiresValidation(
   1646           response_.request_time, response_.response_time, Time::Now()))
   1647     return true;
   1648 
   1649   // Since Vary header computation is fairly expensive, we save it for last.
   1650   if (response_.vary_data.is_valid() &&
   1651       !response_.vary_data.MatchesRequest(*request_, *response_.headers))
   1652     return true;
   1653 
   1654   return false;
   1655 }
   1656 
   1657 bool HttpCache::Transaction::ConditionalizeRequest() {
   1658   DCHECK(response_.headers);
   1659 
   1660   // This only makes sense for cached 200 or 206 responses.
   1661   if (response_.headers->response_code() != 200 &&
   1662       response_.headers->response_code() != 206)
   1663     return false;
   1664 
   1665   // We should have handled this case before.
   1666   DCHECK(response_.headers->response_code() != 206 ||
   1667          response_.headers->HasStrongValidators());
   1668 
   1669   // Just use the first available ETag and/or Last-Modified header value.
   1670   // TODO(darin): Or should we use the last?
   1671 
   1672   std::string etag_value;
   1673   response_.headers->EnumerateHeader(NULL, "etag", &etag_value);
   1674 
   1675   std::string last_modified_value;
   1676   response_.headers->EnumerateHeader(NULL, "last-modified",
   1677                                      &last_modified_value);
   1678 
   1679   if (etag_value.empty() && last_modified_value.empty())
   1680     return false;
   1681 
   1682   if (!partial_.get()) {
   1683     // Need to customize the request, so this forces us to allocate :(
   1684     custom_request_.reset(new HttpRequestInfo(*request_));
   1685     request_ = custom_request_.get();
   1686   }
   1687   DCHECK(custom_request_.get());
   1688 
   1689   bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() &&
   1690                       !invalid_range_;
   1691 
   1692   if (!etag_value.empty()) {
   1693     if (use_if_range) {
   1694       // We don't want to switch to WRITE mode if we don't have this block of a
   1695       // byte-range request because we may have other parts cached.
   1696       custom_request_->extra_headers.SetHeader(
   1697           HttpRequestHeaders::kIfRange, etag_value);
   1698     } else {
   1699       custom_request_->extra_headers.SetHeader(
   1700           HttpRequestHeaders::kIfNoneMatch, etag_value);
   1701     }
   1702     // For byte-range requests, make sure that we use only one way to validate
   1703     // the request.
   1704     if (partial_.get() && !partial_->IsCurrentRangeCached())
   1705       return true;
   1706   }
   1707 
   1708   if (!last_modified_value.empty()) {
   1709     if (use_if_range) {
   1710       custom_request_->extra_headers.SetHeader(
   1711           HttpRequestHeaders::kIfRange, last_modified_value);
   1712     } else {
   1713       custom_request_->extra_headers.SetHeader(
   1714           HttpRequestHeaders::kIfModifiedSince, last_modified_value);
   1715     }
   1716   }
   1717 
   1718   return true;
   1719 }
   1720 
   1721 // We just received some headers from the server. We may have asked for a range,
   1722 // in which case partial_ has an object. This could be the first network request
   1723 // we make to fulfill the original request, or we may be already reading (from
   1724 // the net and / or the cache). If we are not expecting a certain response, we
   1725 // just bypass the cache for this request (but again, maybe we are reading), and
   1726 // delete partial_ (so we are not able to "fix" the headers that we return to
   1727 // the user). This results in either a weird response for the caller (we don't
   1728 // expect it after all), or maybe a range that was not exactly what it was asked
   1729 // for.
   1730 //
   1731 // If the server is simply telling us that the resource has changed, we delete
   1732 // the cached entry and restart the request as the caller intended (by returning
   1733 // false from this method). However, we may not be able to do that at any point,
   1734 // for instance if we already returned the headers to the user.
   1735 //
   1736 // WARNING: Whenever this code returns false, it has to make sure that the next
   1737 // time it is called it will return true so that we don't keep retrying the
   1738 // request.
   1739 bool HttpCache::Transaction::ValidatePartialResponse(bool* partial_content) {
   1740   const HttpResponseHeaders* headers = new_response_->headers;
   1741   int response_code = headers->response_code();
   1742   bool partial_response = (response_code == 206);
   1743   *partial_content = false;
   1744 
   1745   if (!entry_)
   1746     return true;
   1747 
   1748   if (invalid_range_) {
   1749     // We gave up trying to match this request with the stored data. If the
   1750     // server is ok with the request, delete the entry, otherwise just ignore
   1751     // this request
   1752     DCHECK(!reading_);
   1753     if (partial_response || response_code == 200) {
   1754       DoomPartialEntry(true);
   1755       mode_ = NONE;
   1756     } else {
   1757       if (response_code == 304)
   1758         FailRangeRequest();
   1759       IgnoreRangeRequest();
   1760     }
   1761     return true;
   1762   }
   1763 
   1764   if (!partial_.get()) {
   1765     // We are not expecting 206 but we may have one.
   1766     if (partial_response)
   1767       IgnoreRangeRequest();
   1768 
   1769     return true;
   1770   }
   1771 
   1772   // TODO(rvargas): Do we need to consider other results here?.
   1773   bool failure = response_code == 200 || response_code == 416;
   1774 
   1775   if (partial_->IsCurrentRangeCached()) {
   1776     // We asked for "If-None-Match: " so a 206 means a new object.
   1777     if (partial_response)
   1778       failure = true;
   1779 
   1780     if (response_code == 304 && partial_->ResponseHeadersOK(headers))
   1781       return true;
   1782   } else {
   1783     // We asked for "If-Range: " so a 206 means just another range.
   1784     if (partial_response && partial_->ResponseHeadersOK(headers)) {
   1785       *partial_content = true;
   1786       return true;
   1787     }
   1788 
   1789     // 304 is not expected here, but we'll spare the entry (unless it was
   1790     // truncated).
   1791     if (truncated_) {
   1792       if (!reading_ && response_code == 200) {
   1793         // The server is sending the whole resource, and we can save it.
   1794         DCHECK(!partial_->IsLastRange());
   1795         partial_.reset();
   1796         truncated_ = false;
   1797         return true;
   1798       }
   1799       failure = true;
   1800     }
   1801   }
   1802 
   1803   if (failure) {
   1804     // We cannot truncate this entry, it has to be deleted.
   1805     DoomPartialEntry(false);
   1806     mode_ = NONE;
   1807     if (!reading_ && !partial_->IsLastRange()) {
   1808       // We'll attempt to issue another network request, this time without us
   1809       // messing up the headers.
   1810       partial_->RestoreHeaders(&custom_request_->extra_headers);
   1811       partial_.reset();
   1812       truncated_ = false;
   1813       return false;
   1814     }
   1815     LOG(WARNING) << "Failed to revalidate partial entry";
   1816     partial_.reset();
   1817     return true;
   1818   }
   1819 
   1820   IgnoreRangeRequest();
   1821   return true;
   1822 }
   1823 
   1824 void HttpCache::Transaction::IgnoreRangeRequest() {
   1825   // We have a problem. We may or may not be reading already (in which case we
   1826   // returned the headers), but we'll just pretend that this request is not
   1827   // using the cache and see what happens. Most likely this is the first
   1828   // response from the server (it's not changing its mind midway, right?).
   1829   if (mode_ & WRITE) {
   1830     DoneWritingToEntry(mode_ != WRITE);
   1831   } else if (mode_ & READ && entry_) {
   1832     cache_->DoneReadingFromEntry(entry_, this);
   1833   }
   1834 
   1835   partial_.reset(NULL);
   1836   entry_ = NULL;
   1837   mode_ = NONE;
   1838 }
   1839 
   1840 void HttpCache::Transaction::FailRangeRequest() {
   1841   response_ = *new_response_;
   1842   partial_->FixResponseHeaders(response_.headers, false);
   1843 }
   1844 
   1845 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
   1846   read_buf_ = data;
   1847   io_buf_len_ = data_len;
   1848   next_state_ = STATE_NETWORK_READ;
   1849   return DoLoop(OK);
   1850 }
   1851 
   1852 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) {
   1853   read_buf_ = data;
   1854   io_buf_len_ = data_len;
   1855   next_state_ = STATE_CACHE_READ_DATA;
   1856   return DoLoop(OK);
   1857 }
   1858 
   1859 int HttpCache::Transaction::WriteToEntry(int index, int offset,
   1860                                          IOBuffer* data, int data_len,
   1861                                          CompletionCallback* callback) {
   1862   if (!entry_)
   1863     return data_len;
   1864 
   1865   int rv = 0;
   1866   if (!partial_.get() || !data_len) {
   1867     rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback,
   1868                                        true);
   1869   } else {
   1870     rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback);
   1871   }
   1872   return rv;
   1873 }
   1874 
   1875 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
   1876   next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
   1877   if (!entry_)
   1878     return OK;
   1879 
   1880   // Do not cache no-store content (unless we are record mode).  Do not cache
   1881   // content with cert errors either.  This is to prevent not reporting net
   1882   // errors when loading a resource from the cache.  When we load a page over
   1883   // HTTPS with a cert error we show an SSL blocking page.  If the user clicks
   1884   // proceed we reload the resource ignoring the errors.  The loaded resource
   1885   // is then cached.  If that resource is subsequently loaded from the cache,
   1886   // no net error is reported (even though the cert status contains the actual
   1887   // errors) and no SSL blocking page is shown.  An alternative would be to
   1888   // reverse-map the cert status to a net error and replay the net error.
   1889   if ((cache_->mode() != RECORD &&
   1890        response_.headers->HasHeaderValue("cache-control", "no-store")) ||
   1891       net::IsCertStatusError(response_.ssl_info.cert_status)) {
   1892     DoneWritingToEntry(false);
   1893     return OK;
   1894   }
   1895 
   1896   // When writing headers, we normally only write the non-transient
   1897   // headers; when in record mode, record everything.
   1898   bool skip_transient_headers = (cache_->mode() != RECORD);
   1899 
   1900   if (truncated) {
   1901     DCHECK_EQ(200, response_.headers->response_code());
   1902   }
   1903 
   1904   scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
   1905   response_.Persist(data->pickle(), skip_transient_headers, truncated);
   1906   data->Done();
   1907 
   1908   // Balanced in DoCacheWriteResponseComplete.  We may be running from the
   1909   // destructor of this object so cache_callback_ may be currently in use.
   1910   write_headers_callback_->AddRef();
   1911   io_buf_len_ = data->pickle()->size();
   1912   return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data, io_buf_len_,
   1913                                        write_headers_callback_, true);
   1914 }
   1915 
   1916 int HttpCache::Transaction::AppendResponseDataToEntry(
   1917     IOBuffer* data, int data_len, CompletionCallback* callback) {
   1918   if (!entry_ || !data_len)
   1919     return data_len;
   1920 
   1921   int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
   1922   return WriteToEntry(kResponseContentIndex, current_size, data, data_len,
   1923                       callback);
   1924 }
   1925 
   1926 void HttpCache::Transaction::DoneWritingToEntry(bool success) {
   1927   if (!entry_)
   1928     return;
   1929 
   1930   if (cache_->mode() == RECORD)
   1931     DVLOG(1) << "Recorded: " << request_->method << request_->url
   1932              << " status: " << response_.headers->response_code();
   1933 
   1934   cache_->DoneWritingToEntry(entry_, success);
   1935   entry_ = NULL;
   1936   mode_ = NONE;  // switch to 'pass through' mode
   1937 }
   1938 
   1939 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
   1940   DVLOG(2) << "DoomPartialEntry";
   1941   int rv = cache_->DoomEntry(cache_key_, NULL);
   1942   DCHECK_EQ(OK, rv);
   1943   cache_->DoneWithEntry(entry_, this, false);
   1944   entry_ = NULL;
   1945   is_sparse_ = false;
   1946   if (delete_object)
   1947     partial_.reset(NULL);
   1948 }
   1949 
   1950 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
   1951   partial_->OnNetworkReadCompleted(result);
   1952 
   1953   if (result == 0) {
   1954     // We need to move on to the next range.
   1955     network_trans_.reset();
   1956     next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   1957   }
   1958   return result;
   1959 }
   1960 
   1961 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
   1962   partial_->OnCacheReadCompleted(result);
   1963 
   1964   if (result == 0 && mode_ == READ_WRITE) {
   1965     // We need to move on to the next range.
   1966     next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   1967   }
   1968   return result;
   1969 }
   1970 
   1971 // Histogram data from the end of 2010 show the following distribution of
   1972 // response headers:
   1973 //
   1974 //   Content-Length............... 87%
   1975 //   Date......................... 98%
   1976 //   Last-Modified................ 49%
   1977 //   Etag......................... 19%
   1978 //   Accept-Ranges: bytes......... 25%
   1979 //   Accept-Ranges: none.......... 0.4%
   1980 //   Strong Validator............. 50%
   1981 //   Strong Validator + ranges.... 24%
   1982 //   Strong Validator + CL........ 49%
   1983 //
   1984 bool HttpCache::Transaction::CanResume(bool has_data) {
   1985   // Double check that there is something worth keeping.
   1986   if (has_data && !entry_->disk_entry->GetDataSize(kResponseContentIndex))
   1987     return false;
   1988 
   1989   if (request_->method != "GET")
   1990     return false;
   1991 
   1992   if (response_.headers->GetContentLength() <= 0 ||
   1993       response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
   1994       !response_.headers->HasStrongValidators())
   1995     return false;
   1996 
   1997   return true;
   1998 }
   1999 
   2000 void HttpCache::Transaction::OnIOComplete(int result) {
   2001   DoLoop(result);
   2002 }
   2003 
   2004 }  // namespace net
   2005