Home | History | Annotate | Download | only in http
      1 // Copyright (c) 2012 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 <algorithm>
     14 #include <string>
     15 
     16 #include "base/bind.h"
     17 #include "base/compiler_specific.h"
     18 #include "base/memory/ref_counted.h"
     19 #include "base/metrics/field_trial.h"
     20 #include "base/metrics/histogram.h"
     21 #include "base/metrics/sparse_histogram.h"
     22 #include "base/rand_util.h"
     23 #include "base/strings/string_number_conversions.h"
     24 #include "base/strings/string_util.h"
     25 #include "base/time/time.h"
     26 #include "net/base/completion_callback.h"
     27 #include "net/base/io_buffer.h"
     28 #include "net/base/load_flags.h"
     29 #include "net/base/load_timing_info.h"
     30 #include "net/base/net_errors.h"
     31 #include "net/base/net_log.h"
     32 #include "net/base/upload_data_stream.h"
     33 #include "net/cert/cert_status_flags.h"
     34 #include "net/disk_cache/disk_cache.h"
     35 #include "net/http/http_network_session.h"
     36 #include "net/http/http_request_info.h"
     37 #include "net/http/http_response_headers.h"
     38 #include "net/http/http_transaction.h"
     39 #include "net/http/http_util.h"
     40 #include "net/http/partial_data.h"
     41 #include "net/ssl/ssl_cert_request_info.h"
     42 #include "net/ssl/ssl_config_service.h"
     43 
     44 using base::Time;
     45 using base::TimeDelta;
     46 using base::TimeTicks;
     47 
     48 namespace {
     49 
     50 // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
     51 //      a "non-error response" is one with a 2xx (Successful) or 3xx
     52 //      (Redirection) status code.
     53 bool NonErrorResponse(int status_code) {
     54   int status_code_range = status_code / 100;
     55   return status_code_range == 2 || status_code_range == 3;
     56 }
     57 
     58 // Error codes that will be considered indicative of a page being offline/
     59 // unreachable for LOAD_FROM_CACHE_IF_OFFLINE.
     60 bool IsOfflineError(int error) {
     61   return (error == net::ERR_NAME_NOT_RESOLVED ||
     62           error == net::ERR_INTERNET_DISCONNECTED ||
     63           error == net::ERR_ADDRESS_UNREACHABLE ||
     64           error == net::ERR_CONNECTION_TIMED_OUT);
     65 }
     66 
     67 // Enum for UMA, indicating the status (with regard to offline mode) of
     68 // a particular request.
     69 enum RequestOfflineStatus {
     70   // A cache transaction hit in cache (data was present and not stale)
     71   // and returned it.
     72   OFFLINE_STATUS_FRESH_CACHE,
     73 
     74   // A network request was required for a cache entry, and it succeeded.
     75   OFFLINE_STATUS_NETWORK_SUCCEEDED,
     76 
     77   // A network request was required for a cache entry, and it failed with
     78   // a non-offline error.
     79   OFFLINE_STATUS_NETWORK_FAILED,
     80 
     81   // A network request was required for a cache entry, it failed with an
     82   // offline error, and we could serve stale data if
     83   // LOAD_FROM_CACHE_IF_OFFLINE was set.
     84   OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE,
     85 
     86   // A network request was required for a cache entry, it failed with
     87   // an offline error, and there was no servable data in cache (even
     88   // stale data).
     89   OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE,
     90 
     91   OFFLINE_STATUS_MAX_ENTRIES
     92 };
     93 
     94 void RecordOfflineStatus(int load_flags, RequestOfflineStatus status) {
     95   // Restrict to main frame to keep statistics close to
     96   // "would have shown them something useful if offline mode was enabled".
     97   if (load_flags & net::LOAD_MAIN_FRAME) {
     98     UMA_HISTOGRAM_ENUMERATION("HttpCache.OfflineStatus", status,
     99                               OFFLINE_STATUS_MAX_ENTRIES);
    100   }
    101 }
    102 
    103 // TODO(rvargas): Remove once we get the data.
    104 void RecordVaryHeaderHistogram(const net::HttpResponseInfo* response) {
    105   enum VaryType {
    106     VARY_NOT_PRESENT,
    107     VARY_UA,
    108     VARY_OTHER,
    109     VARY_MAX
    110   };
    111   VaryType vary = VARY_NOT_PRESENT;
    112   if (response->vary_data.is_valid()) {
    113     vary = VARY_OTHER;
    114     if (response->headers->HasHeaderValue("vary", "user-agent"))
    115       vary = VARY_UA;
    116   }
    117   UMA_HISTOGRAM_ENUMERATION("HttpCache.Vary", vary, VARY_MAX);
    118 }
    119 
    120 void RecordNoStoreHeaderHistogram(int load_flags,
    121                                   const net::HttpResponseInfo* response) {
    122   if (load_flags & net::LOAD_MAIN_FRAME) {
    123     UMA_HISTOGRAM_BOOLEAN(
    124         "Net.MainFrameNoStore",
    125         response->headers->HasHeaderValue("cache-control", "no-store"));
    126   }
    127 }
    128 
    129 }  // namespace
    130 
    131 namespace net {
    132 
    133 struct HeaderNameAndValue {
    134   const char* name;
    135   const char* value;
    136 };
    137 
    138 // If the request includes one of these request headers, then avoid caching
    139 // to avoid getting confused.
    140 static const HeaderNameAndValue kPassThroughHeaders[] = {
    141   { "if-unmodified-since", NULL },  // causes unexpected 412s
    142   { "if-match", NULL },             // causes unexpected 412s
    143   { "if-range", NULL },
    144   { NULL, NULL }
    145 };
    146 
    147 struct ValidationHeaderInfo {
    148   const char* request_header_name;
    149   const char* related_response_header_name;
    150 };
    151 
    152 static const ValidationHeaderInfo kValidationHeaders[] = {
    153   { "if-modified-since", "last-modified" },
    154   { "if-none-match", "etag" },
    155 };
    156 
    157 // If the request includes one of these request headers, then avoid reusing
    158 // our cached copy if any.
    159 static const HeaderNameAndValue kForceFetchHeaders[] = {
    160   { "cache-control", "no-cache" },
    161   { "pragma", "no-cache" },
    162   { NULL, NULL }
    163 };
    164 
    165 // If the request includes one of these request headers, then force our
    166 // cached copy (if any) to be revalidated before reusing it.
    167 static const HeaderNameAndValue kForceValidateHeaders[] = {
    168   { "cache-control", "max-age=0" },
    169   { NULL, NULL }
    170 };
    171 
    172 static bool HeaderMatches(const HttpRequestHeaders& headers,
    173                           const HeaderNameAndValue* search) {
    174   for (; search->name; ++search) {
    175     std::string header_value;
    176     if (!headers.GetHeader(search->name, &header_value))
    177       continue;
    178 
    179     if (!search->value)
    180       return true;
    181 
    182     HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ',');
    183     while (v.GetNext()) {
    184       if (LowerCaseEqualsASCII(v.value_begin(), v.value_end(), search->value))
    185         return true;
    186     }
    187   }
    188   return false;
    189 }
    190 
    191 //-----------------------------------------------------------------------------
    192 
    193 HttpCache::Transaction::Transaction(
    194     RequestPriority priority,
    195     HttpCache* cache)
    196     : next_state_(STATE_NONE),
    197       request_(NULL),
    198       priority_(priority),
    199       cache_(cache->GetWeakPtr()),
    200       entry_(NULL),
    201       new_entry_(NULL),
    202       new_response_(NULL),
    203       mode_(NONE),
    204       target_state_(STATE_NONE),
    205       reading_(false),
    206       invalid_range_(false),
    207       truncated_(false),
    208       is_sparse_(false),
    209       range_requested_(false),
    210       handling_206_(false),
    211       cache_pending_(false),
    212       done_reading_(false),
    213       vary_mismatch_(false),
    214       couldnt_conditionalize_request_(false),
    215       io_buf_len_(0),
    216       read_offset_(0),
    217       effective_load_flags_(0),
    218       write_len_(0),
    219       weak_factory_(this),
    220       io_callback_(base::Bind(&Transaction::OnIOComplete,
    221                               weak_factory_.GetWeakPtr())),
    222       transaction_pattern_(PATTERN_UNDEFINED),
    223       total_received_bytes_(0),
    224       websocket_handshake_stream_base_create_helper_(NULL) {
    225   COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
    226                  arraysize(kValidationHeaders),
    227                  Invalid_number_of_validation_headers);
    228 }
    229 
    230 HttpCache::Transaction::~Transaction() {
    231   // We may have to issue another IO, but we should never invoke the callback_
    232   // after this point.
    233   callback_.Reset();
    234 
    235   if (cache_) {
    236     if (entry_) {
    237       bool cancel_request = reading_ && response_.headers;
    238       if (cancel_request) {
    239         if (partial_) {
    240           entry_->disk_entry->CancelSparseIO();
    241         } else {
    242           cancel_request &= (response_.headers->response_code() == 200);
    243         }
    244       }
    245 
    246       cache_->DoneWithEntry(entry_, this, cancel_request);
    247     } else if (cache_pending_) {
    248       cache_->RemovePendingTransaction(this);
    249     }
    250   }
    251 }
    252 
    253 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
    254                                           const CompletionCallback& callback) {
    255   DCHECK(buf);
    256   DCHECK_GT(buf_len, 0);
    257   DCHECK(!callback.is_null());
    258   if (!cache_.get() || !entry_)
    259     return ERR_UNEXPECTED;
    260 
    261   // We don't need to track this operation for anything.
    262   // It could be possible to check if there is something already written and
    263   // avoid writing again (it should be the same, right?), but let's allow the
    264   // caller to "update" the contents with something new.
    265   return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
    266                                        callback, true);
    267 }
    268 
    269 bool HttpCache::Transaction::AddTruncatedFlag() {
    270   DCHECK(mode_ & WRITE || mode_ == NONE);
    271 
    272   // Don't set the flag for sparse entries.
    273   if (partial_.get() && !truncated_)
    274     return true;
    275 
    276   if (!CanResume(true))
    277     return false;
    278 
    279   // We may have received the whole resource already.
    280   if (done_reading_)
    281     return true;
    282 
    283   truncated_ = true;
    284   target_state_ = STATE_NONE;
    285   next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
    286   DoLoop(OK);
    287   return true;
    288 }
    289 
    290 LoadState HttpCache::Transaction::GetWriterLoadState() const {
    291   if (network_trans_.get())
    292     return network_trans_->GetLoadState();
    293   if (entry_ || !request_)
    294     return LOAD_STATE_IDLE;
    295   return LOAD_STATE_WAITING_FOR_CACHE;
    296 }
    297 
    298 const BoundNetLog& HttpCache::Transaction::net_log() const {
    299   return net_log_;
    300 }
    301 
    302 int HttpCache::Transaction::Start(const HttpRequestInfo* request,
    303                                   const CompletionCallback& callback,
    304                                   const BoundNetLog& net_log) {
    305   DCHECK(request);
    306   DCHECK(!callback.is_null());
    307 
    308   // Ensure that we only have one asynchronous call at a time.
    309   DCHECK(callback_.is_null());
    310   DCHECK(!reading_);
    311   DCHECK(!network_trans_.get());
    312   DCHECK(!entry_);
    313 
    314   if (!cache_.get())
    315     return ERR_UNEXPECTED;
    316 
    317   SetRequest(net_log, request);
    318 
    319   // We have to wait until the backend is initialized so we start the SM.
    320   next_state_ = STATE_GET_BACKEND;
    321   int rv = DoLoop(OK);
    322 
    323   // Setting this here allows us to check for the existence of a callback_ to
    324   // determine if we are still inside Start.
    325   if (rv == ERR_IO_PENDING)
    326     callback_ = callback;
    327 
    328   return rv;
    329 }
    330 
    331 int HttpCache::Transaction::RestartIgnoringLastError(
    332     const CompletionCallback& callback) {
    333   DCHECK(!callback.is_null());
    334 
    335   // Ensure that we only have one asynchronous call at a time.
    336   DCHECK(callback_.is_null());
    337 
    338   if (!cache_.get())
    339     return ERR_UNEXPECTED;
    340 
    341   int rv = RestartNetworkRequest();
    342 
    343   if (rv == ERR_IO_PENDING)
    344     callback_ = callback;
    345 
    346   return rv;
    347 }
    348 
    349 int HttpCache::Transaction::RestartWithCertificate(
    350     X509Certificate* client_cert,
    351     const CompletionCallback& callback) {
    352   DCHECK(!callback.is_null());
    353 
    354   // Ensure that we only have one asynchronous call at a time.
    355   DCHECK(callback_.is_null());
    356 
    357   if (!cache_.get())
    358     return ERR_UNEXPECTED;
    359 
    360   int rv = RestartNetworkRequestWithCertificate(client_cert);
    361 
    362   if (rv == ERR_IO_PENDING)
    363     callback_ = callback;
    364 
    365   return rv;
    366 }
    367 
    368 int HttpCache::Transaction::RestartWithAuth(
    369     const AuthCredentials& credentials,
    370     const CompletionCallback& callback) {
    371   DCHECK(auth_response_.headers.get());
    372   DCHECK(!callback.is_null());
    373 
    374   // Ensure that we only have one asynchronous call at a time.
    375   DCHECK(callback_.is_null());
    376 
    377   if (!cache_.get())
    378     return ERR_UNEXPECTED;
    379 
    380   // Clear the intermediate response since we are going to start over.
    381   auth_response_ = HttpResponseInfo();
    382 
    383   int rv = RestartNetworkRequestWithAuth(credentials);
    384 
    385   if (rv == ERR_IO_PENDING)
    386     callback_ = callback;
    387 
    388   return rv;
    389 }
    390 
    391 bool HttpCache::Transaction::IsReadyToRestartForAuth() {
    392   if (!network_trans_.get())
    393     return false;
    394   return network_trans_->IsReadyToRestartForAuth();
    395 }
    396 
    397 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
    398                                  const CompletionCallback& callback) {
    399   DCHECK(buf);
    400   DCHECK_GT(buf_len, 0);
    401   DCHECK(!callback.is_null());
    402 
    403   DCHECK(callback_.is_null());
    404 
    405   if (!cache_.get())
    406     return ERR_UNEXPECTED;
    407 
    408   // If we have an intermediate auth response at this point, then it means the
    409   // user wishes to read the network response (the error page).  If there is a
    410   // previous response in the cache then we should leave it intact.
    411   if (auth_response_.headers.get() && mode_ != NONE) {
    412     UpdateTransactionPattern(PATTERN_NOT_COVERED);
    413     DCHECK(mode_ & WRITE);
    414     DoneWritingToEntry(mode_ == READ_WRITE);
    415     mode_ = NONE;
    416   }
    417 
    418   reading_ = true;
    419   int rv;
    420 
    421   switch (mode_) {
    422     case READ_WRITE:
    423       DCHECK(partial_.get());
    424       if (!network_trans_.get()) {
    425         // We are just reading from the cache, but we may be writing later.
    426         rv = ReadFromEntry(buf, buf_len);
    427         break;
    428       }
    429     case NONE:
    430     case WRITE:
    431       DCHECK(network_trans_.get());
    432       rv = ReadFromNetwork(buf, buf_len);
    433       break;
    434     case READ:
    435       rv = ReadFromEntry(buf, buf_len);
    436       break;
    437     default:
    438       NOTREACHED();
    439       rv = ERR_FAILED;
    440   }
    441 
    442   if (rv == ERR_IO_PENDING) {
    443     DCHECK(callback_.is_null());
    444     callback_ = callback;
    445   }
    446   return rv;
    447 }
    448 
    449 void HttpCache::Transaction::StopCaching() {
    450   // We really don't know where we are now. Hopefully there is no operation in
    451   // progress, but nothing really prevents this method to be called after we
    452   // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this
    453   // point because we need the state machine for that (and even if we are really
    454   // free, that would be an asynchronous operation). In other words, keep the
    455   // entry how it is (it will be marked as truncated at destruction), and let
    456   // the next piece of code that executes know that we are now reading directly
    457   // from the net.
    458   // TODO(mmenke):  This doesn't release the lock on the cache entry, so a
    459   //                future request for the resource will be blocked on this one.
    460   //                Fix this.
    461   if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() &&
    462       !is_sparse_ && !range_requested_) {
    463     mode_ = NONE;
    464   }
    465 }
    466 
    467 bool HttpCache::Transaction::GetFullRequestHeaders(
    468     HttpRequestHeaders* headers) const {
    469   if (network_trans_)
    470     return network_trans_->GetFullRequestHeaders(headers);
    471 
    472   // TODO(ttuttle): Read headers from cache.
    473   return false;
    474 }
    475 
    476 int64 HttpCache::Transaction::GetTotalReceivedBytes() const {
    477   int64 total_received_bytes = total_received_bytes_;
    478   if (network_trans_)
    479     total_received_bytes += network_trans_->GetTotalReceivedBytes();
    480   return total_received_bytes;
    481 }
    482 
    483 void HttpCache::Transaction::DoneReading() {
    484   if (cache_.get() && entry_) {
    485     DCHECK_NE(mode_, UPDATE);
    486     if (mode_ & WRITE) {
    487       DoneWritingToEntry(true);
    488     } else if (mode_ & READ) {
    489       // It is necessary to check mode_ & READ because it is possible
    490       // for mode_ to be NONE and entry_ non-NULL with a write entry
    491       // if StopCaching was called.
    492       cache_->DoneReadingFromEntry(entry_, this);
    493       entry_ = NULL;
    494     }
    495   }
    496 }
    497 
    498 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
    499   // Null headers means we encountered an error or haven't a response yet
    500   if (auth_response_.headers.get())
    501     return &auth_response_;
    502   return (response_.headers.get() || response_.ssl_info.cert.get() ||
    503           response_.cert_request_info.get())
    504              ? &response_
    505              : NULL;
    506 }
    507 
    508 LoadState HttpCache::Transaction::GetLoadState() const {
    509   LoadState state = GetWriterLoadState();
    510   if (state != LOAD_STATE_WAITING_FOR_CACHE)
    511     return state;
    512 
    513   if (cache_.get())
    514     return cache_->GetLoadStateForPendingTransaction(this);
    515 
    516   return LOAD_STATE_IDLE;
    517 }
    518 
    519 UploadProgress HttpCache::Transaction::GetUploadProgress() const {
    520   if (network_trans_.get())
    521     return network_trans_->GetUploadProgress();
    522   return final_upload_progress_;
    523 }
    524 
    525 void HttpCache::Transaction::SetQuicServerInfo(
    526     QuicServerInfo* quic_server_info) {}
    527 
    528 bool HttpCache::Transaction::GetLoadTimingInfo(
    529     LoadTimingInfo* load_timing_info) const {
    530   if (network_trans_)
    531     return network_trans_->GetLoadTimingInfo(load_timing_info);
    532 
    533   if (old_network_trans_load_timing_) {
    534     *load_timing_info = *old_network_trans_load_timing_;
    535     return true;
    536   }
    537 
    538   if (first_cache_access_since_.is_null())
    539     return false;
    540 
    541   // If the cache entry was opened, return that time.
    542   load_timing_info->send_start = first_cache_access_since_;
    543   // This time doesn't make much sense when reading from the cache, so just use
    544   // the same time as send_start.
    545   load_timing_info->send_end = first_cache_access_since_;
    546   return true;
    547 }
    548 
    549 void HttpCache::Transaction::SetPriority(RequestPriority priority) {
    550   priority_ = priority;
    551   if (network_trans_)
    552     network_trans_->SetPriority(priority_);
    553 }
    554 
    555 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
    556     WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
    557   websocket_handshake_stream_base_create_helper_ = create_helper;
    558   if (network_trans_)
    559     network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
    560 }
    561 
    562 void HttpCache::Transaction::SetBeforeNetworkStartCallback(
    563     const BeforeNetworkStartCallback& callback) {
    564   DCHECK(!network_trans_);
    565   before_network_start_callback_ = callback;
    566 }
    567 
    568 int HttpCache::Transaction::ResumeNetworkStart() {
    569   if (network_trans_)
    570     return network_trans_->ResumeNetworkStart();
    571   return ERR_UNEXPECTED;
    572 }
    573 
    574 //-----------------------------------------------------------------------------
    575 
    576 void HttpCache::Transaction::DoCallback(int rv) {
    577   DCHECK(rv != ERR_IO_PENDING);
    578   DCHECK(!callback_.is_null());
    579 
    580   read_buf_ = NULL;  // Release the buffer before invoking the callback.
    581 
    582   // Since Run may result in Read being called, clear callback_ up front.
    583   CompletionCallback c = callback_;
    584   callback_.Reset();
    585   c.Run(rv);
    586 }
    587 
    588 int HttpCache::Transaction::HandleResult(int rv) {
    589   DCHECK(rv != ERR_IO_PENDING);
    590   if (!callback_.is_null())
    591     DoCallback(rv);
    592 
    593   return rv;
    594 }
    595 
    596 // A few common patterns: (Foo* means Foo -> FooComplete)
    597 //
    598 // Not-cached entry:
    599 //   Start():
    600 //   GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* ->
    601 //   SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
    602 //   CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* ->
    603 //   PartialHeadersReceived
    604 //
    605 //   Read():
    606 //   NetworkRead* -> CacheWriteData*
    607 //
    608 // Cached entry, no validation:
    609 //   Start():
    610 //   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
    611 //   -> BeginPartialCacheValidation() -> BeginCacheValidation()
    612 //
    613 //   Read():
    614 //   CacheReadData*
    615 //
    616 // Cached entry, validation (304):
    617 //   Start():
    618 //   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
    619 //   -> BeginPartialCacheValidation() -> BeginCacheValidation() ->
    620 //   SendRequest* -> SuccessfulSendRequest -> UpdateCachedResponse ->
    621 //   CacheWriteResponse* -> UpdateCachedResponseComplete ->
    622 //   OverwriteCachedResponse -> PartialHeadersReceived
    623 //
    624 //   Read():
    625 //   CacheReadData*
    626 //
    627 // Cached entry, validation and replace (200):
    628 //   Start():
    629 //   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
    630 //   -> BeginPartialCacheValidation() -> BeginCacheValidation() ->
    631 //   SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
    632 //   CacheWriteResponse* -> DoTruncateCachedData* -> TruncateCachedMetadata* ->
    633 //   PartialHeadersReceived
    634 //
    635 //   Read():
    636 //   NetworkRead* -> CacheWriteData*
    637 //
    638 // Sparse entry, partially cached, byte range request:
    639 //   Start():
    640 //   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
    641 //   -> BeginPartialCacheValidation() -> CacheQueryData* ->
    642 //   ValidateEntryHeadersAndContinue() -> StartPartialCacheValidation ->
    643 //   CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
    644 //   SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteResponse* ->
    645 //   UpdateCachedResponseComplete -> OverwriteCachedResponse ->
    646 //   PartialHeadersReceived
    647 //
    648 //   Read() 1:
    649 //   NetworkRead* -> CacheWriteData*
    650 //
    651 //   Read() 2:
    652 //   NetworkRead* -> CacheWriteData* -> StartPartialCacheValidation ->
    653 //   CompletePartialCacheValidation -> CacheReadData* ->
    654 //
    655 //   Read() 3:
    656 //   CacheReadData* -> StartPartialCacheValidation ->
    657 //   CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
    658 //   SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse
    659 //   -> PartialHeadersReceived -> NetworkRead* -> CacheWriteData*
    660 //
    661 int HttpCache::Transaction::DoLoop(int result) {
    662   DCHECK(next_state_ != STATE_NONE);
    663 
    664   int rv = result;
    665   do {
    666     State state = next_state_;
    667     next_state_ = STATE_NONE;
    668     switch (state) {
    669       case STATE_GET_BACKEND:
    670         DCHECK_EQ(OK, rv);
    671         rv = DoGetBackend();
    672         break;
    673       case STATE_GET_BACKEND_COMPLETE:
    674         rv = DoGetBackendComplete(rv);
    675         break;
    676       case STATE_SEND_REQUEST:
    677         DCHECK_EQ(OK, rv);
    678         rv = DoSendRequest();
    679         break;
    680       case STATE_SEND_REQUEST_COMPLETE:
    681         rv = DoSendRequestComplete(rv);
    682         break;
    683       case STATE_SUCCESSFUL_SEND_REQUEST:
    684         DCHECK_EQ(OK, rv);
    685         rv = DoSuccessfulSendRequest();
    686         break;
    687       case STATE_NETWORK_READ:
    688         DCHECK_EQ(OK, rv);
    689         rv = DoNetworkRead();
    690         break;
    691       case STATE_NETWORK_READ_COMPLETE:
    692         rv = DoNetworkReadComplete(rv);
    693         break;
    694       case STATE_INIT_ENTRY:
    695         DCHECK_EQ(OK, rv);
    696         rv = DoInitEntry();
    697         break;
    698       case STATE_OPEN_ENTRY:
    699         DCHECK_EQ(OK, rv);
    700         rv = DoOpenEntry();
    701         break;
    702       case STATE_OPEN_ENTRY_COMPLETE:
    703         rv = DoOpenEntryComplete(rv);
    704         break;
    705       case STATE_CREATE_ENTRY:
    706         DCHECK_EQ(OK, rv);
    707         rv = DoCreateEntry();
    708         break;
    709       case STATE_CREATE_ENTRY_COMPLETE:
    710         rv = DoCreateEntryComplete(rv);
    711         break;
    712       case STATE_DOOM_ENTRY:
    713         DCHECK_EQ(OK, rv);
    714         rv = DoDoomEntry();
    715         break;
    716       case STATE_DOOM_ENTRY_COMPLETE:
    717         rv = DoDoomEntryComplete(rv);
    718         break;
    719       case STATE_ADD_TO_ENTRY:
    720         DCHECK_EQ(OK, rv);
    721         rv = DoAddToEntry();
    722         break;
    723       case STATE_ADD_TO_ENTRY_COMPLETE:
    724         rv = DoAddToEntryComplete(rv);
    725         break;
    726       case STATE_START_PARTIAL_CACHE_VALIDATION:
    727         DCHECK_EQ(OK, rv);
    728         rv = DoStartPartialCacheValidation();
    729         break;
    730       case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION:
    731         rv = DoCompletePartialCacheValidation(rv);
    732         break;
    733       case STATE_UPDATE_CACHED_RESPONSE:
    734         DCHECK_EQ(OK, rv);
    735         rv = DoUpdateCachedResponse();
    736         break;
    737       case STATE_UPDATE_CACHED_RESPONSE_COMPLETE:
    738         rv = DoUpdateCachedResponseComplete(rv);
    739         break;
    740       case STATE_OVERWRITE_CACHED_RESPONSE:
    741         DCHECK_EQ(OK, rv);
    742         rv = DoOverwriteCachedResponse();
    743         break;
    744       case STATE_TRUNCATE_CACHED_DATA:
    745         DCHECK_EQ(OK, rv);
    746         rv = DoTruncateCachedData();
    747         break;
    748       case STATE_TRUNCATE_CACHED_DATA_COMPLETE:
    749         rv = DoTruncateCachedDataComplete(rv);
    750         break;
    751       case STATE_TRUNCATE_CACHED_METADATA:
    752         DCHECK_EQ(OK, rv);
    753         rv = DoTruncateCachedMetadata();
    754         break;
    755       case STATE_TRUNCATE_CACHED_METADATA_COMPLETE:
    756         rv = DoTruncateCachedMetadataComplete(rv);
    757         break;
    758       case STATE_PARTIAL_HEADERS_RECEIVED:
    759         DCHECK_EQ(OK, rv);
    760         rv = DoPartialHeadersReceived();
    761         break;
    762       case STATE_CACHE_READ_RESPONSE:
    763         DCHECK_EQ(OK, rv);
    764         rv = DoCacheReadResponse();
    765         break;
    766       case STATE_CACHE_READ_RESPONSE_COMPLETE:
    767         rv = DoCacheReadResponseComplete(rv);
    768         break;
    769       case STATE_CACHE_WRITE_RESPONSE:
    770         DCHECK_EQ(OK, rv);
    771         rv = DoCacheWriteResponse();
    772         break;
    773       case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
    774         DCHECK_EQ(OK, rv);
    775         rv = DoCacheWriteTruncatedResponse();
    776         break;
    777       case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
    778         rv = DoCacheWriteResponseComplete(rv);
    779         break;
    780       case STATE_CACHE_READ_METADATA:
    781         DCHECK_EQ(OK, rv);
    782         rv = DoCacheReadMetadata();
    783         break;
    784       case STATE_CACHE_READ_METADATA_COMPLETE:
    785         rv = DoCacheReadMetadataComplete(rv);
    786         break;
    787       case STATE_CACHE_QUERY_DATA:
    788         DCHECK_EQ(OK, rv);
    789         rv = DoCacheQueryData();
    790         break;
    791       case STATE_CACHE_QUERY_DATA_COMPLETE:
    792         rv = DoCacheQueryDataComplete(rv);
    793         break;
    794       case STATE_CACHE_READ_DATA:
    795         DCHECK_EQ(OK, rv);
    796         rv = DoCacheReadData();
    797         break;
    798       case STATE_CACHE_READ_DATA_COMPLETE:
    799         rv = DoCacheReadDataComplete(rv);
    800         break;
    801       case STATE_CACHE_WRITE_DATA:
    802         rv = DoCacheWriteData(rv);
    803         break;
    804       case STATE_CACHE_WRITE_DATA_COMPLETE:
    805         rv = DoCacheWriteDataComplete(rv);
    806         break;
    807       default:
    808         NOTREACHED() << "bad state";
    809         rv = ERR_FAILED;
    810         break;
    811     }
    812   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    813 
    814   if (rv != ERR_IO_PENDING)
    815     HandleResult(rv);
    816 
    817   return rv;
    818 }
    819 
    820 int HttpCache::Transaction::DoGetBackend() {
    821   cache_pending_ = true;
    822   next_state_ = STATE_GET_BACKEND_COMPLETE;
    823   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND);
    824   return cache_->GetBackendForTransaction(this);
    825 }
    826 
    827 int HttpCache::Transaction::DoGetBackendComplete(int result) {
    828   DCHECK(result == OK || result == ERR_FAILED);
    829   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_GET_BACKEND,
    830                                     result);
    831   cache_pending_ = false;
    832 
    833   if (!ShouldPassThrough()) {
    834     cache_key_ = cache_->GenerateCacheKey(request_);
    835 
    836     // Requested cache access mode.
    837     if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
    838       mode_ = READ;
    839     } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
    840       mode_ = WRITE;
    841     } else {
    842       mode_ = READ_WRITE;
    843     }
    844 
    845     // Downgrade to UPDATE if the request has been externally conditionalized.
    846     if (external_validation_.initialized) {
    847       if (mode_ & WRITE) {
    848         // Strip off the READ_DATA bit (and maybe add back a READ_META bit
    849         // in case READ was off).
    850         mode_ = UPDATE;
    851       } else {
    852         mode_ = NONE;
    853       }
    854     }
    855   }
    856 
    857   // Use PUT and DELETE only to invalidate existing stored entries.
    858   if ((request_->method == "PUT" || request_->method == "DELETE") &&
    859       mode_ != READ_WRITE && mode_ != WRITE) {
    860     mode_ = NONE;
    861   }
    862 
    863   // If must use cache, then we must fail.  This can happen for back/forward
    864   // navigations to a page generated via a form post.
    865   if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE)
    866     return ERR_CACHE_MISS;
    867 
    868   if (mode_ == NONE) {
    869     if (partial_.get()) {
    870       partial_->RestoreHeaders(&custom_request_->extra_headers);
    871       partial_.reset();
    872     }
    873     next_state_ = STATE_SEND_REQUEST;
    874   } else {
    875     next_state_ = STATE_INIT_ENTRY;
    876   }
    877 
    878   // This is only set if we have something to do with the response.
    879   range_requested_ = (partial_.get() != NULL);
    880 
    881   return OK;
    882 }
    883 
    884 int HttpCache::Transaction::DoSendRequest() {
    885   DCHECK(mode_ & WRITE || mode_ == NONE);
    886   DCHECK(!network_trans_.get());
    887 
    888   send_request_since_ = TimeTicks::Now();
    889 
    890   // Create a network transaction.
    891   int rv = cache_->network_layer_->CreateTransaction(priority_,
    892                                                      &network_trans_);
    893   if (rv != OK)
    894     return rv;
    895   network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_);
    896 
    897   // Old load timing information, if any, is now obsolete.
    898   old_network_trans_load_timing_.reset();
    899 
    900   if (websocket_handshake_stream_base_create_helper_)
    901     network_trans_->SetWebSocketHandshakeStreamCreateHelper(
    902         websocket_handshake_stream_base_create_helper_);
    903 
    904   next_state_ = STATE_SEND_REQUEST_COMPLETE;
    905   rv = network_trans_->Start(request_, io_callback_, net_log_);
    906   return rv;
    907 }
    908 
    909 int HttpCache::Transaction::DoSendRequestComplete(int result) {
    910   if (!cache_.get())
    911     return ERR_UNEXPECTED;
    912 
    913   // If requested, and we have a readable cache entry, and we have
    914   // an error indicating that we're offline as opposed to in contact
    915   // with a bad server, read from cache anyway.
    916   if (IsOfflineError(result)) {
    917     if (mode_ == READ_WRITE && entry_ && !partial_) {
    918       RecordOfflineStatus(effective_load_flags_,
    919                           OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE);
    920       if (effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) {
    921         UpdateTransactionPattern(PATTERN_NOT_COVERED);
    922         response_.server_data_unavailable = true;
    923         return SetupEntryForRead();
    924       }
    925     } else {
    926       RecordOfflineStatus(effective_load_flags_,
    927                           OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE);
    928     }
    929   } else {
    930     RecordOfflineStatus(effective_load_flags_,
    931                         (result == OK ? OFFLINE_STATUS_NETWORK_SUCCEEDED :
    932                                         OFFLINE_STATUS_NETWORK_FAILED));
    933   }
    934 
    935   // If we tried to conditionalize the request and failed, we know
    936   // we won't be reading from the cache after this point.
    937   if (couldnt_conditionalize_request_)
    938     mode_ = WRITE;
    939 
    940   if (result == OK) {
    941     next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
    942     return OK;
    943   }
    944 
    945   // Do not record requests that have network errors or restarts.
    946   UpdateTransactionPattern(PATTERN_NOT_COVERED);
    947   if (IsCertificateError(result)) {
    948     const HttpResponseInfo* response = network_trans_->GetResponseInfo();
    949     // If we get a certificate error, then there is a certificate in ssl_info,
    950     // so GetResponseInfo() should never return NULL here.
    951     DCHECK(response);
    952     response_.ssl_info = response->ssl_info;
    953   } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
    954     const HttpResponseInfo* response = network_trans_->GetResponseInfo();
    955     DCHECK(response);
    956     response_.cert_request_info = response->cert_request_info;
    957   } else if (response_.was_cached) {
    958     DoneWritingToEntry(true);
    959   }
    960   return result;
    961 }
    962 
    963 // We received the response headers and there is no error.
    964 int HttpCache::Transaction::DoSuccessfulSendRequest() {
    965   DCHECK(!new_response_);
    966   const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
    967   bool authentication_failure = false;
    968 
    969   if (new_response->headers->response_code() == 401 ||
    970       new_response->headers->response_code() == 407) {
    971     auth_response_ = *new_response;
    972     if (!reading_)
    973       return OK;
    974 
    975     // We initiated a second request the caller doesn't know about. We should be
    976     // able to authenticate this request because we should have authenticated
    977     // this URL moments ago.
    978     if (IsReadyToRestartForAuth()) {
    979       DCHECK(!response_.auth_challenge.get());
    980       next_state_ = STATE_SEND_REQUEST_COMPLETE;
    981       // In theory we should check to see if there are new cookies, but there
    982       // is no way to do that from here.
    983       return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_);
    984     }
    985 
    986     // We have to perform cleanup at this point so that at least the next
    987     // request can succeed.
    988     authentication_failure = true;
    989     if (entry_)
    990       DoomPartialEntry(false);
    991     mode_ = NONE;
    992     partial_.reset();
    993   }
    994 
    995   new_response_ = new_response;
    996   if (authentication_failure ||
    997       (!ValidatePartialResponse() && !auth_response_.headers.get())) {
    998     // Something went wrong with this request and we have to restart it.
    999     // If we have an authentication response, we are exposed to weird things
   1000     // hapenning if the user cancels the authentication before we receive
   1001     // the new response.
   1002     UpdateTransactionPattern(PATTERN_NOT_COVERED);
   1003     response_ = HttpResponseInfo();
   1004     ResetNetworkTransaction();
   1005     new_response_ = NULL;
   1006     next_state_ = STATE_SEND_REQUEST;
   1007     return OK;
   1008   }
   1009 
   1010   if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
   1011     // We have stored the full entry, but it changed and the server is
   1012     // sending a range. We have to delete the old entry.
   1013     UpdateTransactionPattern(PATTERN_NOT_COVERED);
   1014     DoneWritingToEntry(false);
   1015   }
   1016 
   1017   if (mode_ == WRITE &&
   1018       transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) {
   1019     UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
   1020   }
   1021 
   1022   if (mode_ == WRITE &&
   1023       (request_->method == "PUT" || request_->method == "DELETE")) {
   1024     if (NonErrorResponse(new_response->headers->response_code())) {
   1025       int ret = cache_->DoomEntry(cache_key_, NULL);
   1026       DCHECK_EQ(OK, ret);
   1027     }
   1028     cache_->DoneWritingToEntry(entry_, true);
   1029     entry_ = NULL;
   1030     mode_ = NONE;
   1031   }
   1032 
   1033   if (request_->method == "POST" &&
   1034       NonErrorResponse(new_response->headers->response_code())) {
   1035     cache_->DoomMainEntryForUrl(request_->url);
   1036   }
   1037 
   1038   RecordVaryHeaderHistogram(new_response);
   1039   RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
   1040 
   1041   if (new_response_->headers->response_code() == 416 &&
   1042       (request_->method == "GET" || request_->method == "POST")) {
   1043     // If there is an ective entry it may be destroyed with this transaction.
   1044     response_ = *new_response_;
   1045     return OK;
   1046   }
   1047 
   1048   // Are we expecting a response to a conditional query?
   1049   if (mode_ == READ_WRITE || mode_ == UPDATE) {
   1050     if (new_response->headers->response_code() == 304 || handling_206_) {
   1051       UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED);
   1052       next_state_ = STATE_UPDATE_CACHED_RESPONSE;
   1053       return OK;
   1054     }
   1055     UpdateTransactionPattern(PATTERN_ENTRY_UPDATED);
   1056     mode_ = WRITE;
   1057   }
   1058 
   1059   next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
   1060   return OK;
   1061 }
   1062 
   1063 int HttpCache::Transaction::DoNetworkRead() {
   1064   next_state_ = STATE_NETWORK_READ_COMPLETE;
   1065   return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
   1066 }
   1067 
   1068 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
   1069   DCHECK(mode_ & WRITE || mode_ == NONE);
   1070 
   1071   if (!cache_.get())
   1072     return ERR_UNEXPECTED;
   1073 
   1074   // If there is an error or we aren't saving the data, we are done; just wait
   1075   // until the destructor runs to see if we can keep the data.
   1076   if (mode_ == NONE || result < 0)
   1077     return result;
   1078 
   1079   next_state_ = STATE_CACHE_WRITE_DATA;
   1080   return result;
   1081 }
   1082 
   1083 int HttpCache::Transaction::DoInitEntry() {
   1084   DCHECK(!new_entry_);
   1085 
   1086   if (!cache_.get())
   1087     return ERR_UNEXPECTED;
   1088 
   1089   if (mode_ == WRITE) {
   1090     next_state_ = STATE_DOOM_ENTRY;
   1091     return OK;
   1092   }
   1093 
   1094   next_state_ = STATE_OPEN_ENTRY;
   1095   return OK;
   1096 }
   1097 
   1098 int HttpCache::Transaction::DoOpenEntry() {
   1099   DCHECK(!new_entry_);
   1100   next_state_ = STATE_OPEN_ENTRY_COMPLETE;
   1101   cache_pending_ = true;
   1102   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
   1103   first_cache_access_since_ = TimeTicks::Now();
   1104   return cache_->OpenEntry(cache_key_, &new_entry_, this);
   1105 }
   1106 
   1107 int HttpCache::Transaction::DoOpenEntryComplete(int result) {
   1108   // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
   1109   // OK, otherwise the cache will end up with an active entry without any
   1110   // transaction attached.
   1111   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
   1112   cache_pending_ = false;
   1113   if (result == OK) {
   1114     next_state_ = STATE_ADD_TO_ENTRY;
   1115     return OK;
   1116   }
   1117 
   1118   if (result == ERR_CACHE_RACE) {
   1119     next_state_ = STATE_INIT_ENTRY;
   1120     return OK;
   1121   }
   1122 
   1123   if (request_->method == "PUT" || request_->method == "DELETE") {
   1124     DCHECK(mode_ == READ_WRITE || mode_ == WRITE);
   1125     mode_ = NONE;
   1126     next_state_ = STATE_SEND_REQUEST;
   1127     return OK;
   1128   }
   1129 
   1130   if (mode_ == READ_WRITE) {
   1131     mode_ = WRITE;
   1132     next_state_ = STATE_CREATE_ENTRY;
   1133     return OK;
   1134   }
   1135   if (mode_ == UPDATE) {
   1136     // There is no cache entry to update; proceed without caching.
   1137     mode_ = NONE;
   1138     next_state_ = STATE_SEND_REQUEST;
   1139     return OK;
   1140   }
   1141   if (cache_->mode() == PLAYBACK)
   1142     DVLOG(1) << "Playback Cache Miss: " << request_->url;
   1143 
   1144   // The entry does not exist, and we are not permitted to create a new entry,
   1145   // so we must fail.
   1146   return ERR_CACHE_MISS;
   1147 }
   1148 
   1149 int HttpCache::Transaction::DoCreateEntry() {
   1150   DCHECK(!new_entry_);
   1151   next_state_ = STATE_CREATE_ENTRY_COMPLETE;
   1152   cache_pending_ = true;
   1153   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
   1154   return cache_->CreateEntry(cache_key_, &new_entry_, this);
   1155 }
   1156 
   1157 int HttpCache::Transaction::DoCreateEntryComplete(int result) {
   1158   // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
   1159   // OK, otherwise the cache will end up with an active entry without any
   1160   // transaction attached.
   1161   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
   1162                                     result);
   1163   cache_pending_ = false;
   1164   next_state_ = STATE_ADD_TO_ENTRY;
   1165 
   1166   if (result == ERR_CACHE_RACE) {
   1167     next_state_ = STATE_INIT_ENTRY;
   1168     return OK;
   1169   }
   1170 
   1171   if (result == OK) {
   1172     UMA_HISTOGRAM_BOOLEAN("HttpCache.OpenToCreateRace", false);
   1173   } else {
   1174     UMA_HISTOGRAM_BOOLEAN("HttpCache.OpenToCreateRace", true);
   1175     // We have a race here: Maybe we failed to open the entry and decided to
   1176     // create one, but by the time we called create, another transaction already
   1177     // created the entry. If we want to eliminate this issue, we need an atomic
   1178     // OpenOrCreate() method exposed by the disk cache.
   1179     DLOG(WARNING) << "Unable to create cache entry";
   1180     mode_ = NONE;
   1181     if (partial_.get())
   1182       partial_->RestoreHeaders(&custom_request_->extra_headers);
   1183     next_state_ = STATE_SEND_REQUEST;
   1184   }
   1185   return OK;
   1186 }
   1187 
   1188 int HttpCache::Transaction::DoDoomEntry() {
   1189   next_state_ = STATE_DOOM_ENTRY_COMPLETE;
   1190   cache_pending_ = true;
   1191   if (first_cache_access_since_.is_null())
   1192     first_cache_access_since_ = TimeTicks::Now();
   1193   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY);
   1194   return cache_->DoomEntry(cache_key_, this);
   1195 }
   1196 
   1197 int HttpCache::Transaction::DoDoomEntryComplete(int result) {
   1198   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result);
   1199   next_state_ = STATE_CREATE_ENTRY;
   1200   cache_pending_ = false;
   1201   if (result == ERR_CACHE_RACE)
   1202     next_state_ = STATE_INIT_ENTRY;
   1203   return OK;
   1204 }
   1205 
   1206 int HttpCache::Transaction::DoAddToEntry() {
   1207   DCHECK(new_entry_);
   1208   cache_pending_ = true;
   1209   next_state_ = STATE_ADD_TO_ENTRY_COMPLETE;
   1210   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY);
   1211   DCHECK(entry_lock_waiting_since_.is_null());
   1212   entry_lock_waiting_since_ = TimeTicks::Now();
   1213   return cache_->AddTransactionToEntry(new_entry_, this);
   1214 }
   1215 
   1216 int HttpCache::Transaction::DoAddToEntryComplete(int result) {
   1217   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY,
   1218                                     result);
   1219   const TimeDelta entry_lock_wait =
   1220       TimeTicks::Now() - entry_lock_waiting_since_;
   1221   UMA_HISTOGRAM_TIMES("HttpCache.EntryLockWait", entry_lock_wait);
   1222 
   1223   entry_lock_waiting_since_ = TimeTicks();
   1224   DCHECK(new_entry_);
   1225   cache_pending_ = false;
   1226 
   1227   if (result == OK)
   1228     entry_ = new_entry_;
   1229 
   1230   // If there is a failure, the cache should have taken care of new_entry_.
   1231   new_entry_ = NULL;
   1232 
   1233   if (result == ERR_CACHE_RACE) {
   1234     next_state_ = STATE_INIT_ENTRY;
   1235     return OK;
   1236   }
   1237 
   1238   if (result != OK) {
   1239     NOTREACHED();
   1240     return result;
   1241   }
   1242 
   1243   if (mode_ == WRITE) {
   1244     if (partial_.get())
   1245       partial_->RestoreHeaders(&custom_request_->extra_headers);
   1246     next_state_ = STATE_SEND_REQUEST;
   1247   } else {
   1248     // We have to read the headers from the cached entry.
   1249     DCHECK(mode_ & READ_META);
   1250     next_state_ = STATE_CACHE_READ_RESPONSE;
   1251   }
   1252   return OK;
   1253 }
   1254 
   1255 // We may end up here multiple times for a given request.
   1256 int HttpCache::Transaction::DoStartPartialCacheValidation() {
   1257   if (mode_ == NONE)
   1258     return OK;
   1259 
   1260   next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
   1261   return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_);
   1262 }
   1263 
   1264 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
   1265   if (!result) {
   1266     // This is the end of the request.
   1267     if (mode_ & WRITE) {
   1268       DoneWritingToEntry(true);
   1269     } else {
   1270       cache_->DoneReadingFromEntry(entry_, this);
   1271       entry_ = NULL;
   1272     }
   1273     return result;
   1274   }
   1275 
   1276   if (result < 0)
   1277     return result;
   1278 
   1279   partial_->PrepareCacheValidation(entry_->disk_entry,
   1280                                    &custom_request_->extra_headers);
   1281 
   1282   if (reading_ && partial_->IsCurrentRangeCached()) {
   1283     next_state_ = STATE_CACHE_READ_DATA;
   1284     return OK;
   1285   }
   1286 
   1287   return BeginCacheValidation();
   1288 }
   1289 
   1290 // We received 304 or 206 and we want to update the cached response headers.
   1291 int HttpCache::Transaction::DoUpdateCachedResponse() {
   1292   next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
   1293   int rv = OK;
   1294   // Update cached response based on headers in new_response.
   1295   // TODO(wtc): should we update cached certificate (response_.ssl_info), too?
   1296   response_.headers->Update(*new_response_->headers.get());
   1297   response_.response_time = new_response_->response_time;
   1298   response_.request_time = new_response_->request_time;
   1299   response_.network_accessed = new_response_->network_accessed;
   1300 
   1301   if (response_.headers->HasHeaderValue("cache-control", "no-store")) {
   1302     if (!entry_->doomed) {
   1303       int ret = cache_->DoomEntry(cache_key_, NULL);
   1304       DCHECK_EQ(OK, ret);
   1305     }
   1306   } else {
   1307     // If we are already reading, we already updated the headers for this
   1308     // request; doing it again will change Content-Length.
   1309     if (!reading_) {
   1310       target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
   1311       next_state_ = STATE_CACHE_WRITE_RESPONSE;
   1312       rv = OK;
   1313     }
   1314   }
   1315   return rv;
   1316 }
   1317 
   1318 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
   1319   if (mode_ == UPDATE) {
   1320     DCHECK(!handling_206_);
   1321     // We got a "not modified" response and already updated the corresponding
   1322     // cache entry above.
   1323     //
   1324     // By closing the cached entry now, we make sure that the 304 rather than
   1325     // the cached 200 response, is what will be returned to the user.
   1326     DoneWritingToEntry(true);
   1327   } else if (entry_ && !handling_206_) {
   1328     DCHECK_EQ(READ_WRITE, mode_);
   1329     if (!partial_.get() || partial_->IsLastRange()) {
   1330       cache_->ConvertWriterToReader(entry_);
   1331       mode_ = READ;
   1332     }
   1333     // We no longer need the network transaction, so destroy it.
   1334     final_upload_progress_ = network_trans_->GetUploadProgress();
   1335     ResetNetworkTransaction();
   1336   } else if (entry_ && handling_206_ && truncated_ &&
   1337              partial_->initial_validation()) {
   1338     // We just finished the validation of a truncated entry, and the server
   1339     // is willing to resume the operation. Now we go back and start serving
   1340     // the first part to the user.
   1341     ResetNetworkTransaction();
   1342     new_response_ = NULL;
   1343     next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   1344     partial_->SetRangeToStartDownload();
   1345     return OK;
   1346   }
   1347   next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
   1348   return OK;
   1349 }
   1350 
   1351 int HttpCache::Transaction::DoOverwriteCachedResponse() {
   1352   if (mode_ & READ) {
   1353     next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   1354     return OK;
   1355   }
   1356 
   1357   // We change the value of Content-Length for partial content.
   1358   if (handling_206_ && partial_.get())
   1359     partial_->FixContentLength(new_response_->headers.get());
   1360 
   1361   response_ = *new_response_;
   1362 
   1363   if (handling_206_ && !CanResume(false)) {
   1364     // There is no point in storing this resource because it will never be used.
   1365     DoneWritingToEntry(false);
   1366     if (partial_.get())
   1367       partial_->FixResponseHeaders(response_.headers.get(), true);
   1368     next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   1369     return OK;
   1370   }
   1371 
   1372   target_state_ = STATE_TRUNCATE_CACHED_DATA;
   1373   next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE :
   1374                              STATE_CACHE_WRITE_RESPONSE;
   1375   return OK;
   1376 }
   1377 
   1378 int HttpCache::Transaction::DoTruncateCachedData() {
   1379   next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
   1380   if (!entry_)
   1381     return OK;
   1382   if (net_log_.IsLogging())
   1383     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
   1384   // Truncate the stream.
   1385   return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_);
   1386 }
   1387 
   1388 int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
   1389   if (entry_) {
   1390     if (net_log_.IsLogging()) {
   1391       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
   1392                                         result);
   1393     }
   1394   }
   1395 
   1396   next_state_ = STATE_TRUNCATE_CACHED_METADATA;
   1397   return OK;
   1398 }
   1399 
   1400 int HttpCache::Transaction::DoTruncateCachedMetadata() {
   1401   next_state_ = STATE_TRUNCATE_CACHED_METADATA_COMPLETE;
   1402   if (!entry_)
   1403     return OK;
   1404 
   1405   if (net_log_.IsLogging())
   1406     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
   1407   return WriteToEntry(kMetadataIndex, 0, NULL, 0, io_callback_);
   1408 }
   1409 
   1410 int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) {
   1411   if (entry_) {
   1412     if (net_log_.IsLogging()) {
   1413       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
   1414                                         result);
   1415     }
   1416   }
   1417 
   1418   next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   1419   return OK;
   1420 }
   1421 
   1422 int HttpCache::Transaction::DoPartialHeadersReceived() {
   1423   new_response_ = NULL;
   1424   if (entry_ && !partial_.get() &&
   1425       entry_->disk_entry->GetDataSize(kMetadataIndex))
   1426     next_state_ = STATE_CACHE_READ_METADATA;
   1427 
   1428   if (!partial_.get())
   1429     return OK;
   1430 
   1431   if (reading_) {
   1432     if (network_trans_.get()) {
   1433       next_state_ = STATE_NETWORK_READ;
   1434     } else {
   1435       next_state_ = STATE_CACHE_READ_DATA;
   1436     }
   1437   } else if (mode_ != NONE) {
   1438     // We are about to return the headers for a byte-range request to the user,
   1439     // so let's fix them.
   1440     partial_->FixResponseHeaders(response_.headers.get(), true);
   1441   }
   1442   return OK;
   1443 }
   1444 
   1445 int HttpCache::Transaction::DoCacheReadResponse() {
   1446   DCHECK(entry_);
   1447   next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
   1448 
   1449   io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
   1450   read_buf_ = new IOBuffer(io_buf_len_);
   1451 
   1452   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
   1453   return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
   1454                                       io_buf_len_, io_callback_);
   1455 }
   1456 
   1457 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
   1458   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
   1459   if (result != io_buf_len_ ||
   1460       !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_,
   1461                                     &response_, &truncated_)) {
   1462     return OnCacheReadError(result, true);
   1463   }
   1464 
   1465   // Some resources may have slipped in as truncated when they're not.
   1466   int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
   1467   if (response_.headers->GetContentLength() == current_size)
   1468     truncated_ = false;
   1469 
   1470   // We now have access to the cache entry.
   1471   //
   1472   //  o if we are a reader for the transaction, then we can start reading the
   1473   //    cache entry.
   1474   //
   1475   //  o if we can read or write, then we should check if the cache entry needs
   1476   //    to be validated and then issue a network request if needed or just read
   1477   //    from the cache if the cache entry is already valid.
   1478   //
   1479   //  o if we are set to UPDATE, then we are handling an externally
   1480   //    conditionalized request (if-modified-since / if-none-match). We check
   1481   //    if the request headers define a validation request.
   1482   //
   1483   switch (mode_) {
   1484     case READ:
   1485       UpdateTransactionPattern(PATTERN_ENTRY_USED);
   1486       result = BeginCacheRead();
   1487       break;
   1488     case READ_WRITE:
   1489       result = BeginPartialCacheValidation();
   1490       break;
   1491     case UPDATE:
   1492       result = BeginExternallyConditionalizedRequest();
   1493       break;
   1494     case WRITE:
   1495     default:
   1496       NOTREACHED();
   1497       result = ERR_FAILED;
   1498   }
   1499   return result;
   1500 }
   1501 
   1502 int HttpCache::Transaction::DoCacheWriteResponse() {
   1503   if (entry_) {
   1504     if (net_log_.IsLogging())
   1505       net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
   1506   }
   1507   return WriteResponseInfoToEntry(false);
   1508 }
   1509 
   1510 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
   1511   if (entry_) {
   1512     if (net_log_.IsLogging())
   1513       net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
   1514   }
   1515   return WriteResponseInfoToEntry(true);
   1516 }
   1517 
   1518 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
   1519   next_state_ = target_state_;
   1520   target_state_ = STATE_NONE;
   1521   if (!entry_)
   1522     return OK;
   1523   if (net_log_.IsLogging()) {
   1524     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
   1525                                       result);
   1526   }
   1527 
   1528   // Balance the AddRef from WriteResponseInfoToEntry.
   1529   if (result != io_buf_len_) {
   1530     DLOG(ERROR) << "failed to write response info to cache";
   1531     DoneWritingToEntry(false);
   1532   }
   1533   return OK;
   1534 }
   1535 
   1536 int HttpCache::Transaction::DoCacheReadMetadata() {
   1537   DCHECK(entry_);
   1538   DCHECK(!response_.metadata.get());
   1539   next_state_ = STATE_CACHE_READ_METADATA_COMPLETE;
   1540 
   1541   response_.metadata =
   1542       new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex));
   1543 
   1544   net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
   1545   return entry_->disk_entry->ReadData(kMetadataIndex, 0,
   1546                                       response_.metadata.get(),
   1547                                       response_.metadata->size(),
   1548                                       io_callback_);
   1549 }
   1550 
   1551 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
   1552   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
   1553   if (result != response_.metadata->size())
   1554     return OnCacheReadError(result, false);
   1555   return OK;
   1556 }
   1557 
   1558 int HttpCache::Transaction::DoCacheQueryData() {
   1559   next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
   1560   return entry_->disk_entry->ReadyForSparseIO(io_callback_);
   1561 }
   1562 
   1563 int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
   1564   if (result == ERR_NOT_IMPLEMENTED) {
   1565     // Restart the request overwriting the cache entry.
   1566     // TODO(pasko): remove this workaround as soon as the SimpleBackendImpl
   1567     // supports Sparse IO.
   1568     return DoRestartPartialRequest();
   1569   }
   1570   DCHECK_EQ(OK, result);
   1571   if (!cache_.get())
   1572     return ERR_UNEXPECTED;
   1573 
   1574   return ValidateEntryHeadersAndContinue();
   1575 }
   1576 
   1577 int HttpCache::Transaction::DoCacheReadData() {
   1578   DCHECK(entry_);
   1579   next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
   1580 
   1581   if (net_log_.IsLogging())
   1582     net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA);
   1583   if (partial_.get()) {
   1584     return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_,
   1585                                io_callback_);
   1586   }
   1587 
   1588   return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_,
   1589                                       read_buf_.get(), io_buf_len_,
   1590                                       io_callback_);
   1591 }
   1592 
   1593 int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
   1594   if (net_log_.IsLogging()) {
   1595     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
   1596                                       result);
   1597   }
   1598 
   1599   if (!cache_.get())
   1600     return ERR_UNEXPECTED;
   1601 
   1602   if (partial_.get()) {
   1603     // Partial requests are confusing to report in histograms because they may
   1604     // have multiple underlying requests.
   1605     UpdateTransactionPattern(PATTERN_NOT_COVERED);
   1606     return DoPartialCacheReadCompleted(result);
   1607   }
   1608 
   1609   if (result > 0) {
   1610     read_offset_ += result;
   1611   } else if (result == 0) {  // End of file.
   1612     RecordHistograms();
   1613     cache_->DoneReadingFromEntry(entry_, this);
   1614     entry_ = NULL;
   1615   } else {
   1616     return OnCacheReadError(result, false);
   1617   }
   1618   return result;
   1619 }
   1620 
   1621 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
   1622   next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
   1623   write_len_ = num_bytes;
   1624   if (entry_) {
   1625     if (net_log_.IsLogging())
   1626       net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
   1627   }
   1628 
   1629   return AppendResponseDataToEntry(read_buf_.get(), num_bytes, io_callback_);
   1630 }
   1631 
   1632 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
   1633   if (entry_) {
   1634     if (net_log_.IsLogging()) {
   1635       net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
   1636                                         result);
   1637     }
   1638   }
   1639   // Balance the AddRef from DoCacheWriteData.
   1640   if (!cache_.get())
   1641     return ERR_UNEXPECTED;
   1642 
   1643   if (result != write_len_) {
   1644     DLOG(ERROR) << "failed to write response data to cache";
   1645     DoneWritingToEntry(false);
   1646 
   1647     // We want to ignore errors writing to disk and just keep reading from
   1648     // the network.
   1649     result = write_len_;
   1650   } else if (!done_reading_ && entry_) {
   1651     int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
   1652     int64 body_size = response_.headers->GetContentLength();
   1653     if (body_size >= 0 && body_size <= current_size)
   1654       done_reading_ = true;
   1655   }
   1656 
   1657   if (partial_.get()) {
   1658     // This may be the last request.
   1659     if (!(result == 0 && !truncated_ &&
   1660           (partial_->IsLastRange() || mode_ == WRITE)))
   1661       return DoPartialNetworkReadCompleted(result);
   1662   }
   1663 
   1664   if (result == 0) {
   1665     // End of file. This may be the result of a connection problem so see if we
   1666     // have to keep the entry around to be flagged as truncated later on.
   1667     if (done_reading_ || !entry_ || partial_.get() ||
   1668         response_.headers->GetContentLength() <= 0)
   1669       DoneWritingToEntry(true);
   1670   }
   1671 
   1672   return result;
   1673 }
   1674 
   1675 //-----------------------------------------------------------------------------
   1676 
   1677 void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log,
   1678                                         const HttpRequestInfo* request) {
   1679   net_log_ = net_log;
   1680   request_ = request;
   1681   effective_load_flags_ = request_->load_flags;
   1682 
   1683   switch (cache_->mode()) {
   1684     case NORMAL:
   1685       break;
   1686     case RECORD:
   1687       // When in record mode, we want to NEVER load from the cache.
   1688       // The reason for this is beacuse we save the Set-Cookie headers
   1689       // (intentionally).  If we read from the cache, we replay them
   1690       // prematurely.
   1691       effective_load_flags_ |= LOAD_BYPASS_CACHE;
   1692       break;
   1693     case PLAYBACK:
   1694       // When in playback mode, we want to load exclusively from the cache.
   1695       effective_load_flags_ |= LOAD_ONLY_FROM_CACHE;
   1696       break;
   1697     case DISABLE:
   1698       effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1699       break;
   1700   }
   1701 
   1702   // Some headers imply load flags.  The order here is significant.
   1703   //
   1704   //   LOAD_DISABLE_CACHE   : no cache read or write
   1705   //   LOAD_BYPASS_CACHE    : no cache read
   1706   //   LOAD_VALIDATE_CACHE  : no cache read unless validation
   1707   //
   1708   // The former modes trump latter modes, so if we find a matching header we
   1709   // can stop iterating kSpecialHeaders.
   1710   //
   1711   static const struct {
   1712     const HeaderNameAndValue* search;
   1713     int load_flag;
   1714   } kSpecialHeaders[] = {
   1715     { kPassThroughHeaders, LOAD_DISABLE_CACHE },
   1716     { kForceFetchHeaders, LOAD_BYPASS_CACHE },
   1717     { kForceValidateHeaders, LOAD_VALIDATE_CACHE },
   1718   };
   1719 
   1720   bool range_found = false;
   1721   bool external_validation_error = false;
   1722 
   1723   if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange))
   1724     range_found = true;
   1725 
   1726   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSpecialHeaders); ++i) {
   1727     if (HeaderMatches(request_->extra_headers, kSpecialHeaders[i].search)) {
   1728       effective_load_flags_ |= kSpecialHeaders[i].load_flag;
   1729       break;
   1730     }
   1731   }
   1732 
   1733   // Check for conditionalization headers which may correspond with a
   1734   // cache validation request.
   1735   for (size_t i = 0; i < arraysize(kValidationHeaders); ++i) {
   1736     const ValidationHeaderInfo& info = kValidationHeaders[i];
   1737     std::string validation_value;
   1738     if (request_->extra_headers.GetHeader(
   1739             info.request_header_name, &validation_value)) {
   1740       if (!external_validation_.values[i].empty() ||
   1741           validation_value.empty()) {
   1742         external_validation_error = true;
   1743       }
   1744       external_validation_.values[i] = validation_value;
   1745       external_validation_.initialized = true;
   1746     }
   1747   }
   1748 
   1749   // We don't support ranges and validation headers.
   1750   if (range_found && external_validation_.initialized) {
   1751     LOG(WARNING) << "Byte ranges AND validation headers found.";
   1752     effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1753   }
   1754 
   1755   // If there is more than one validation header, we can't treat this request as
   1756   // a cache validation, since we don't know for sure which header the server
   1757   // will give us a response for (and they could be contradictory).
   1758   if (external_validation_error) {
   1759     LOG(WARNING) << "Multiple or malformed validation headers found.";
   1760     effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1761   }
   1762 
   1763   if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
   1764     UpdateTransactionPattern(PATTERN_NOT_COVERED);
   1765     partial_.reset(new PartialData);
   1766     if (request_->method == "GET" && partial_->Init(request_->extra_headers)) {
   1767       // We will be modifying the actual range requested to the server, so
   1768       // let's remove the header here.
   1769       custom_request_.reset(new HttpRequestInfo(*request_));
   1770       custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
   1771       request_ = custom_request_.get();
   1772       partial_->SetHeaders(custom_request_->extra_headers);
   1773     } else {
   1774       // The range is invalid or we cannot handle it properly.
   1775       VLOG(1) << "Invalid byte range found.";
   1776       effective_load_flags_ |= LOAD_DISABLE_CACHE;
   1777       partial_.reset(NULL);
   1778     }
   1779   }
   1780 }
   1781 
   1782 bool HttpCache::Transaction::ShouldPassThrough() {
   1783   // We may have a null disk_cache if there is an error we cannot recover from,
   1784   // like not enough disk space, or sharing violations.
   1785   if (!cache_->disk_cache_.get())
   1786     return true;
   1787 
   1788   // When using the record/playback modes, we always use the cache
   1789   // and we never pass through.
   1790   if (cache_->mode() == RECORD || cache_->mode() == PLAYBACK)
   1791     return false;
   1792 
   1793   if (effective_load_flags_ & LOAD_DISABLE_CACHE)
   1794     return true;
   1795 
   1796   if (request_->method == "GET")
   1797     return false;
   1798 
   1799   if (request_->method == "POST" && request_->upload_data_stream &&
   1800       request_->upload_data_stream->identifier()) {
   1801     return false;
   1802   }
   1803 
   1804   if (request_->method == "PUT" && request_->upload_data_stream)
   1805     return false;
   1806 
   1807   if (request_->method == "DELETE")
   1808     return false;
   1809 
   1810   // TODO(darin): add support for caching HEAD responses
   1811   return true;
   1812 }
   1813 
   1814 int HttpCache::Transaction::BeginCacheRead() {
   1815   // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges.
   1816   if (response_.headers->response_code() == 206 || partial_.get()) {
   1817     NOTREACHED();
   1818     return ERR_CACHE_MISS;
   1819   }
   1820 
   1821   // We don't have the whole resource.
   1822   if (truncated_)
   1823     return ERR_CACHE_MISS;
   1824 
   1825   if (entry_->disk_entry->GetDataSize(kMetadataIndex))
   1826     next_state_ = STATE_CACHE_READ_METADATA;
   1827 
   1828   return OK;
   1829 }
   1830 
   1831 int HttpCache::Transaction::BeginCacheValidation() {
   1832   DCHECK(mode_ == READ_WRITE);
   1833 
   1834   bool skip_validation = !RequiresValidation();
   1835 
   1836   if (truncated_) {
   1837     // Truncated entries can cause partial gets, so we shouldn't record this
   1838     // load in histograms.
   1839     UpdateTransactionPattern(PATTERN_NOT_COVERED);
   1840     skip_validation = !partial_->initial_validation();
   1841   }
   1842 
   1843   if (partial_.get() && (is_sparse_ || truncated_) &&
   1844       (!partial_->IsCurrentRangeCached() || invalid_range_)) {
   1845     // Force revalidation for sparse or truncated entries. Note that we don't
   1846     // want to ignore the regular validation logic just because a byte range was
   1847     // part of the request.
   1848     skip_validation = false;
   1849   }
   1850 
   1851   if (skip_validation) {
   1852     UpdateTransactionPattern(PATTERN_ENTRY_USED);
   1853     RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE);
   1854     return SetupEntryForRead();
   1855   } else {
   1856     // Make the network request conditional, to see if we may reuse our cached
   1857     // response.  If we cannot do so, then we just resort to a normal fetch.
   1858     // Our mode remains READ_WRITE for a conditional request.  Even if the
   1859     // conditionalization fails, we don't switch to WRITE mode until we
   1860     // know we won't be falling back to using the cache entry in the
   1861     // LOAD_FROM_CACHE_IF_OFFLINE case.
   1862     if (!ConditionalizeRequest()) {
   1863       couldnt_conditionalize_request_ = true;
   1864       UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE);
   1865       if (partial_.get())
   1866         return DoRestartPartialRequest();
   1867 
   1868       DCHECK_NE(206, response_.headers->response_code());
   1869     }
   1870     next_state_ = STATE_SEND_REQUEST;
   1871   }
   1872   return OK;
   1873 }
   1874 
   1875 int HttpCache::Transaction::BeginPartialCacheValidation() {
   1876   DCHECK(mode_ == READ_WRITE);
   1877 
   1878   if (response_.headers->response_code() != 206 && !partial_.get() &&
   1879       !truncated_) {
   1880     return BeginCacheValidation();
   1881   }
   1882 
   1883   // Partial requests should not be recorded in histograms.
   1884   UpdateTransactionPattern(PATTERN_NOT_COVERED);
   1885   if (range_requested_) {
   1886     next_state_ = STATE_CACHE_QUERY_DATA;
   1887     return OK;
   1888   }
   1889   // The request is not for a range, but we have stored just ranges.
   1890   partial_.reset(new PartialData());
   1891   partial_->SetHeaders(request_->extra_headers);
   1892   if (!custom_request_.get()) {
   1893     custom_request_.reset(new HttpRequestInfo(*request_));
   1894     request_ = custom_request_.get();
   1895   }
   1896 
   1897   return ValidateEntryHeadersAndContinue();
   1898 }
   1899 
   1900 // This should only be called once per request.
   1901 int HttpCache::Transaction::ValidateEntryHeadersAndContinue() {
   1902   DCHECK(mode_ == READ_WRITE);
   1903 
   1904   if (!partial_->UpdateFromStoredHeaders(
   1905           response_.headers.get(), entry_->disk_entry, truncated_)) {
   1906     return DoRestartPartialRequest();
   1907   }
   1908 
   1909   if (response_.headers->response_code() == 206)
   1910     is_sparse_ = true;
   1911 
   1912   if (!partial_->IsRequestedRangeOK()) {
   1913     // The stored data is fine, but the request may be invalid.
   1914     invalid_range_ = true;
   1915   }
   1916 
   1917   next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   1918   return OK;
   1919 }
   1920 
   1921 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
   1922   DCHECK_EQ(UPDATE, mode_);
   1923   DCHECK(external_validation_.initialized);
   1924 
   1925   for (size_t i = 0;  i < arraysize(kValidationHeaders); i++) {
   1926     if (external_validation_.values[i].empty())
   1927       continue;
   1928     // Retrieve either the cached response's "etag" or "last-modified" header.
   1929     std::string validator;
   1930     response_.headers->EnumerateHeader(
   1931         NULL,
   1932         kValidationHeaders[i].related_response_header_name,
   1933         &validator);
   1934 
   1935     if (response_.headers->response_code() != 200 || truncated_ ||
   1936         validator.empty() || validator != external_validation_.values[i]) {
   1937       // The externally conditionalized request is not a validation request
   1938       // for our existing cache entry. Proceed with caching disabled.
   1939       UpdateTransactionPattern(PATTERN_NOT_COVERED);
   1940       DoneWritingToEntry(true);
   1941     }
   1942   }
   1943 
   1944   next_state_ = STATE_SEND_REQUEST;
   1945   return OK;
   1946 }
   1947 
   1948 int HttpCache::Transaction::RestartNetworkRequest() {
   1949   DCHECK(mode_ & WRITE || mode_ == NONE);
   1950   DCHECK(network_trans_.get());
   1951   DCHECK_EQ(STATE_NONE, next_state_);
   1952 
   1953   next_state_ = STATE_SEND_REQUEST_COMPLETE;
   1954   int rv = network_trans_->RestartIgnoringLastError(io_callback_);
   1955   if (rv != ERR_IO_PENDING)
   1956     return DoLoop(rv);
   1957   return rv;
   1958 }
   1959 
   1960 int HttpCache::Transaction::RestartNetworkRequestWithCertificate(
   1961     X509Certificate* client_cert) {
   1962   DCHECK(mode_ & WRITE || mode_ == NONE);
   1963   DCHECK(network_trans_.get());
   1964   DCHECK_EQ(STATE_NONE, next_state_);
   1965 
   1966   next_state_ = STATE_SEND_REQUEST_COMPLETE;
   1967   int rv = network_trans_->RestartWithCertificate(client_cert, io_callback_);
   1968   if (rv != ERR_IO_PENDING)
   1969     return DoLoop(rv);
   1970   return rv;
   1971 }
   1972 
   1973 int HttpCache::Transaction::RestartNetworkRequestWithAuth(
   1974     const AuthCredentials& credentials) {
   1975   DCHECK(mode_ & WRITE || mode_ == NONE);
   1976   DCHECK(network_trans_.get());
   1977   DCHECK_EQ(STATE_NONE, next_state_);
   1978 
   1979   next_state_ = STATE_SEND_REQUEST_COMPLETE;
   1980   int rv = network_trans_->RestartWithAuth(credentials, io_callback_);
   1981   if (rv != ERR_IO_PENDING)
   1982     return DoLoop(rv);
   1983   return rv;
   1984 }
   1985 
   1986 bool HttpCache::Transaction::RequiresValidation() {
   1987   // TODO(darin): need to do more work here:
   1988   //  - make sure we have a matching request method
   1989   //  - watch out for cached responses that depend on authentication
   1990 
   1991   // In playback mode, nothing requires validation.
   1992   if (cache_->mode() == net::HttpCache::PLAYBACK)
   1993     return false;
   1994 
   1995   if (response_.vary_data.is_valid() &&
   1996       !response_.vary_data.MatchesRequest(*request_,
   1997                                           *response_.headers.get())) {
   1998     vary_mismatch_ = true;
   1999     return true;
   2000   }
   2001 
   2002   if (effective_load_flags_ & LOAD_PREFERRING_CACHE)
   2003     return false;
   2004 
   2005   if (effective_load_flags_ & LOAD_VALIDATE_CACHE)
   2006     return true;
   2007 
   2008   if (request_->method == "PUT" || request_->method == "DELETE")
   2009     return true;
   2010 
   2011   if (response_.headers->RequiresValidation(
   2012           response_.request_time, response_.response_time, Time::Now())) {
   2013     return true;
   2014   }
   2015 
   2016   return false;
   2017 }
   2018 
   2019 bool HttpCache::Transaction::ConditionalizeRequest() {
   2020   DCHECK(response_.headers.get());
   2021 
   2022   if (request_->method == "PUT" || request_->method == "DELETE")
   2023     return false;
   2024 
   2025   // This only makes sense for cached 200 or 206 responses.
   2026   if (response_.headers->response_code() != 200 &&
   2027       response_.headers->response_code() != 206) {
   2028     return false;
   2029   }
   2030 
   2031   // We should have handled this case before.
   2032   DCHECK(response_.headers->response_code() != 206 ||
   2033          response_.headers->HasStrongValidators());
   2034 
   2035   // Just use the first available ETag and/or Last-Modified header value.
   2036   // TODO(darin): Or should we use the last?
   2037 
   2038   std::string etag_value;
   2039   if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1))
   2040     response_.headers->EnumerateHeader(NULL, "etag", &etag_value);
   2041 
   2042   std::string last_modified_value;
   2043   if (!vary_mismatch_) {
   2044     response_.headers->EnumerateHeader(NULL, "last-modified",
   2045                                        &last_modified_value);
   2046   }
   2047 
   2048   if (etag_value.empty() && last_modified_value.empty())
   2049     return false;
   2050 
   2051   if (!partial_.get()) {
   2052     // Need to customize the request, so this forces us to allocate :(
   2053     custom_request_.reset(new HttpRequestInfo(*request_));
   2054     request_ = custom_request_.get();
   2055   }
   2056   DCHECK(custom_request_.get());
   2057 
   2058   bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() &&
   2059                       !invalid_range_;
   2060 
   2061   if (!etag_value.empty()) {
   2062     if (use_if_range) {
   2063       // We don't want to switch to WRITE mode if we don't have this block of a
   2064       // byte-range request because we may have other parts cached.
   2065       custom_request_->extra_headers.SetHeader(
   2066           HttpRequestHeaders::kIfRange, etag_value);
   2067     } else {
   2068       custom_request_->extra_headers.SetHeader(
   2069           HttpRequestHeaders::kIfNoneMatch, etag_value);
   2070     }
   2071     // For byte-range requests, make sure that we use only one way to validate
   2072     // the request.
   2073     if (partial_.get() && !partial_->IsCurrentRangeCached())
   2074       return true;
   2075   }
   2076 
   2077   if (!last_modified_value.empty()) {
   2078     if (use_if_range) {
   2079       custom_request_->extra_headers.SetHeader(
   2080           HttpRequestHeaders::kIfRange, last_modified_value);
   2081     } else {
   2082       custom_request_->extra_headers.SetHeader(
   2083           HttpRequestHeaders::kIfModifiedSince, last_modified_value);
   2084     }
   2085   }
   2086 
   2087   return true;
   2088 }
   2089 
   2090 // We just received some headers from the server. We may have asked for a range,
   2091 // in which case partial_ has an object. This could be the first network request
   2092 // we make to fulfill the original request, or we may be already reading (from
   2093 // the net and / or the cache). If we are not expecting a certain response, we
   2094 // just bypass the cache for this request (but again, maybe we are reading), and
   2095 // delete partial_ (so we are not able to "fix" the headers that we return to
   2096 // the user). This results in either a weird response for the caller (we don't
   2097 // expect it after all), or maybe a range that was not exactly what it was asked
   2098 // for.
   2099 //
   2100 // If the server is simply telling us that the resource has changed, we delete
   2101 // the cached entry and restart the request as the caller intended (by returning
   2102 // false from this method). However, we may not be able to do that at any point,
   2103 // for instance if we already returned the headers to the user.
   2104 //
   2105 // WARNING: Whenever this code returns false, it has to make sure that the next
   2106 // time it is called it will return true so that we don't keep retrying the
   2107 // request.
   2108 bool HttpCache::Transaction::ValidatePartialResponse() {
   2109   const HttpResponseHeaders* headers = new_response_->headers.get();
   2110   int response_code = headers->response_code();
   2111   bool partial_response = (response_code == 206);
   2112   handling_206_ = false;
   2113 
   2114   if (!entry_ || request_->method != "GET")
   2115     return true;
   2116 
   2117   if (invalid_range_) {
   2118     // We gave up trying to match this request with the stored data. If the
   2119     // server is ok with the request, delete the entry, otherwise just ignore
   2120     // this request
   2121     DCHECK(!reading_);
   2122     if (partial_response || response_code == 200) {
   2123       DoomPartialEntry(true);
   2124       mode_ = NONE;
   2125     } else {
   2126       if (response_code == 304)
   2127         FailRangeRequest();
   2128       IgnoreRangeRequest();
   2129     }
   2130     return true;
   2131   }
   2132 
   2133   if (!partial_.get()) {
   2134     // We are not expecting 206 but we may have one.
   2135     if (partial_response)
   2136       IgnoreRangeRequest();
   2137 
   2138     return true;
   2139   }
   2140 
   2141   // TODO(rvargas): Do we need to consider other results here?.
   2142   bool failure = response_code == 200 || response_code == 416;
   2143 
   2144   if (partial_->IsCurrentRangeCached()) {
   2145     // We asked for "If-None-Match: " so a 206 means a new object.
   2146     if (partial_response)
   2147       failure = true;
   2148 
   2149     if (response_code == 304 && partial_->ResponseHeadersOK(headers))
   2150       return true;
   2151   } else {
   2152     // We asked for "If-Range: " so a 206 means just another range.
   2153     if (partial_response && partial_->ResponseHeadersOK(headers)) {
   2154       handling_206_ = true;
   2155       return true;
   2156     }
   2157 
   2158     if (!reading_ && !is_sparse_ && !partial_response) {
   2159       // See if we can ignore the fact that we issued a byte range request.
   2160       // If the server sends 200, just store it. If it sends an error, redirect
   2161       // or something else, we may store the response as long as we didn't have
   2162       // anything already stored.
   2163       if (response_code == 200 ||
   2164           (!truncated_ && response_code != 304 && response_code != 416)) {
   2165         // The server is sending something else, and we can save it.
   2166         DCHECK((truncated_ && !partial_->IsLastRange()) || range_requested_);
   2167         partial_.reset();
   2168         truncated_ = false;
   2169         return true;
   2170       }
   2171     }
   2172 
   2173     // 304 is not expected here, but we'll spare the entry (unless it was
   2174     // truncated).
   2175     if (truncated_)
   2176       failure = true;
   2177   }
   2178 
   2179   if (failure) {
   2180     // We cannot truncate this entry, it has to be deleted.
   2181     UpdateTransactionPattern(PATTERN_NOT_COVERED);
   2182     DoomPartialEntry(false);
   2183     mode_ = NONE;
   2184     if (!reading_ && !partial_->IsLastRange()) {
   2185       // We'll attempt to issue another network request, this time without us
   2186       // messing up the headers.
   2187       partial_->RestoreHeaders(&custom_request_->extra_headers);
   2188       partial_.reset();
   2189       truncated_ = false;
   2190       return false;
   2191     }
   2192     LOG(WARNING) << "Failed to revalidate partial entry";
   2193     partial_.reset();
   2194     return true;
   2195   }
   2196 
   2197   IgnoreRangeRequest();
   2198   return true;
   2199 }
   2200 
   2201 void HttpCache::Transaction::IgnoreRangeRequest() {
   2202   // We have a problem. We may or may not be reading already (in which case we
   2203   // returned the headers), but we'll just pretend that this request is not
   2204   // using the cache and see what happens. Most likely this is the first
   2205   // response from the server (it's not changing its mind midway, right?).
   2206   UpdateTransactionPattern(PATTERN_NOT_COVERED);
   2207   if (mode_ & WRITE)
   2208     DoneWritingToEntry(mode_ != WRITE);
   2209   else if (mode_ & READ && entry_)
   2210     cache_->DoneReadingFromEntry(entry_, this);
   2211 
   2212   partial_.reset(NULL);
   2213   entry_ = NULL;
   2214   mode_ = NONE;
   2215 }
   2216 
   2217 void HttpCache::Transaction::FailRangeRequest() {
   2218   response_ = *new_response_;
   2219   partial_->FixResponseHeaders(response_.headers.get(), false);
   2220 }
   2221 
   2222 int HttpCache::Transaction::SetupEntryForRead() {
   2223   if (network_trans_)
   2224     ResetNetworkTransaction();
   2225   if (partial_.get()) {
   2226     if (truncated_ || is_sparse_ || !invalid_range_) {
   2227       // We are going to return the saved response headers to the caller, so
   2228       // we may need to adjust them first.
   2229       next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
   2230       return OK;
   2231     } else {
   2232       partial_.reset();
   2233     }
   2234   }
   2235   cache_->ConvertWriterToReader(entry_);
   2236   mode_ = READ;
   2237 
   2238   if (entry_->disk_entry->GetDataSize(kMetadataIndex))
   2239     next_state_ = STATE_CACHE_READ_METADATA;
   2240   return OK;
   2241 }
   2242 
   2243 
   2244 int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
   2245   read_buf_ = data;
   2246   io_buf_len_ = data_len;
   2247   next_state_ = STATE_NETWORK_READ;
   2248   return DoLoop(OK);
   2249 }
   2250 
   2251 int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) {
   2252   read_buf_ = data;
   2253   io_buf_len_ = data_len;
   2254   next_state_ = STATE_CACHE_READ_DATA;
   2255   return DoLoop(OK);
   2256 }
   2257 
   2258 int HttpCache::Transaction::WriteToEntry(int index, int offset,
   2259                                          IOBuffer* data, int data_len,
   2260                                          const CompletionCallback& callback) {
   2261   if (!entry_)
   2262     return data_len;
   2263 
   2264   int rv = 0;
   2265   if (!partial_.get() || !data_len) {
   2266     rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback,
   2267                                        true);
   2268   } else {
   2269     rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback);
   2270   }
   2271   return rv;
   2272 }
   2273 
   2274 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
   2275   next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
   2276   if (!entry_)
   2277     return OK;
   2278 
   2279   // Do not cache no-store content (unless we are record mode).  Do not cache
   2280   // content with cert errors either.  This is to prevent not reporting net
   2281   // errors when loading a resource from the cache.  When we load a page over
   2282   // HTTPS with a cert error we show an SSL blocking page.  If the user clicks
   2283   // proceed we reload the resource ignoring the errors.  The loaded resource
   2284   // is then cached.  If that resource is subsequently loaded from the cache,
   2285   // no net error is reported (even though the cert status contains the actual
   2286   // errors) and no SSL blocking page is shown.  An alternative would be to
   2287   // reverse-map the cert status to a net error and replay the net error.
   2288   if ((cache_->mode() != RECORD &&
   2289        response_.headers->HasHeaderValue("cache-control", "no-store")) ||
   2290       net::IsCertStatusError(response_.ssl_info.cert_status)) {
   2291     DoneWritingToEntry(false);
   2292     if (net_log_.IsLogging())
   2293       net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
   2294     return OK;
   2295   }
   2296 
   2297   // When writing headers, we normally only write the non-transient
   2298   // headers; when in record mode, record everything.
   2299   bool skip_transient_headers = (cache_->mode() != RECORD);
   2300 
   2301   if (truncated)
   2302     DCHECK_EQ(200, response_.headers->response_code());
   2303 
   2304   scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
   2305   response_.Persist(data->pickle(), skip_transient_headers, truncated);
   2306   data->Done();
   2307 
   2308   io_buf_len_ = data->pickle()->size();
   2309   return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
   2310                                        io_buf_len_, io_callback_, true);
   2311 }
   2312 
   2313 int HttpCache::Transaction::AppendResponseDataToEntry(
   2314     IOBuffer* data, int data_len, const CompletionCallback& callback) {
   2315   if (!entry_ || !data_len)
   2316     return data_len;
   2317 
   2318   int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
   2319   return WriteToEntry(kResponseContentIndex, current_size, data, data_len,
   2320                       callback);
   2321 }
   2322 
   2323 void HttpCache::Transaction::DoneWritingToEntry(bool success) {
   2324   if (!entry_)
   2325     return;
   2326 
   2327   RecordHistograms();
   2328 
   2329   cache_->DoneWritingToEntry(entry_, success);
   2330   entry_ = NULL;
   2331   mode_ = NONE;  // switch to 'pass through' mode
   2332 }
   2333 
   2334 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
   2335   DLOG(ERROR) << "ReadData failed: " << result;
   2336   const int result_for_histogram = std::max(0, -result);
   2337   if (restart) {
   2338     UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
   2339                                 result_for_histogram);
   2340   } else {
   2341     UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
   2342                                 result_for_histogram);
   2343   }
   2344 
   2345   // Avoid using this entry in the future.
   2346   if (cache_.get())
   2347     cache_->DoomActiveEntry(cache_key_);
   2348 
   2349   if (restart) {
   2350     DCHECK(!reading_);
   2351     DCHECK(!network_trans_.get());
   2352     cache_->DoneWithEntry(entry_, this, false);
   2353     entry_ = NULL;
   2354     is_sparse_ = false;
   2355     partial_.reset();
   2356     next_state_ = STATE_GET_BACKEND;
   2357     return OK;
   2358   }
   2359 
   2360   return ERR_CACHE_READ_FAILURE;
   2361 }
   2362 
   2363 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
   2364   DVLOG(2) << "DoomPartialEntry";
   2365   int rv = cache_->DoomEntry(cache_key_, NULL);
   2366   DCHECK_EQ(OK, rv);
   2367   cache_->DoneWithEntry(entry_, this, false);
   2368   entry_ = NULL;
   2369   is_sparse_ = false;
   2370   if (delete_object)
   2371     partial_.reset(NULL);
   2372 }
   2373 
   2374 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
   2375   partial_->OnNetworkReadCompleted(result);
   2376 
   2377   if (result == 0) {
   2378     // We need to move on to the next range.
   2379     ResetNetworkTransaction();
   2380     next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   2381   }
   2382   return result;
   2383 }
   2384 
   2385 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
   2386   partial_->OnCacheReadCompleted(result);
   2387 
   2388   if (result == 0 && mode_ == READ_WRITE) {
   2389     // We need to move on to the next range.
   2390     next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
   2391   } else if (result < 0) {
   2392     return OnCacheReadError(result, false);
   2393   }
   2394   return result;
   2395 }
   2396 
   2397 int HttpCache::Transaction::DoRestartPartialRequest() {
   2398   // The stored data cannot be used. Get rid of it and restart this request.
   2399   // We need to also reset the |truncated_| flag as a new entry is created.
   2400   DoomPartialEntry(!range_requested_);
   2401   mode_ = WRITE;
   2402   truncated_ = false;
   2403   next_state_ = STATE_INIT_ENTRY;
   2404   return OK;
   2405 }
   2406 
   2407 void HttpCache::Transaction::ResetNetworkTransaction() {
   2408   DCHECK(!old_network_trans_load_timing_);
   2409   DCHECK(network_trans_);
   2410   LoadTimingInfo load_timing;
   2411   if (network_trans_->GetLoadTimingInfo(&load_timing))
   2412     old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
   2413   total_received_bytes_ += network_trans_->GetTotalReceivedBytes();
   2414   network_trans_.reset();
   2415 }
   2416 
   2417 // Histogram data from the end of 2010 show the following distribution of
   2418 // response headers:
   2419 //
   2420 //   Content-Length............... 87%
   2421 //   Date......................... 98%
   2422 //   Last-Modified................ 49%
   2423 //   Etag......................... 19%
   2424 //   Accept-Ranges: bytes......... 25%
   2425 //   Accept-Ranges: none.......... 0.4%
   2426 //   Strong Validator............. 50%
   2427 //   Strong Validator + ranges.... 24%
   2428 //   Strong Validator + CL........ 49%
   2429 //
   2430 bool HttpCache::Transaction::CanResume(bool has_data) {
   2431   // Double check that there is something worth keeping.
   2432   if (has_data && !entry_->disk_entry->GetDataSize(kResponseContentIndex))
   2433     return false;
   2434 
   2435   if (request_->method != "GET")
   2436     return false;
   2437 
   2438   // Note that if this is a 206, content-length was already fixed after calling
   2439   // PartialData::ResponseHeadersOK().
   2440   if (response_.headers->GetContentLength() <= 0 ||
   2441       response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
   2442       !response_.headers->HasStrongValidators()) {
   2443     return false;
   2444   }
   2445 
   2446   return true;
   2447 }
   2448 
   2449 void HttpCache::Transaction::UpdateTransactionPattern(
   2450     TransactionPattern new_transaction_pattern) {
   2451   if (transaction_pattern_ == PATTERN_NOT_COVERED)
   2452     return;
   2453   DCHECK(transaction_pattern_ == PATTERN_UNDEFINED ||
   2454          new_transaction_pattern == PATTERN_NOT_COVERED);
   2455   transaction_pattern_ = new_transaction_pattern;
   2456 }
   2457 
   2458 void HttpCache::Transaction::RecordHistograms() {
   2459   DCHECK_NE(PATTERN_UNDEFINED, transaction_pattern_);
   2460   if (!cache_.get() || !cache_->GetCurrentBackend() ||
   2461       cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE ||
   2462       cache_->mode() != NORMAL || request_->method != "GET") {
   2463     return;
   2464   }
   2465   UMA_HISTOGRAM_ENUMERATION(
   2466       "HttpCache.Pattern", transaction_pattern_, PATTERN_MAX);
   2467   if (transaction_pattern_ == PATTERN_NOT_COVERED)
   2468     return;
   2469   DCHECK(!range_requested_);
   2470   DCHECK(!first_cache_access_since_.is_null());
   2471 
   2472   TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
   2473 
   2474   UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
   2475 
   2476   bool did_send_request = !send_request_since_.is_null();
   2477   DCHECK(
   2478       (did_send_request &&
   2479        (transaction_pattern_ == PATTERN_ENTRY_NOT_CACHED ||
   2480         transaction_pattern_ == PATTERN_ENTRY_VALIDATED ||
   2481         transaction_pattern_ == PATTERN_ENTRY_UPDATED ||
   2482         transaction_pattern_ == PATTERN_ENTRY_CANT_CONDITIONALIZE)) ||
   2483       (!did_send_request && transaction_pattern_ == PATTERN_ENTRY_USED));
   2484 
   2485   if (!did_send_request) {
   2486     DCHECK(transaction_pattern_ == PATTERN_ENTRY_USED);
   2487     UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time);
   2488     return;
   2489   }
   2490 
   2491   TimeDelta before_send_time = send_request_since_ - first_cache_access_since_;
   2492   int before_send_percent =
   2493       total_time.ToInternalValue() == 0 ? 0
   2494                                         : before_send_time * 100 / total_time;
   2495   DCHECK_LE(0, before_send_percent);
   2496   DCHECK_GE(100, before_send_percent);
   2497 
   2498   UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time);
   2499   UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
   2500   UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_percent);
   2501 
   2502   // TODO(gavinp): Remove or minimize these histograms, particularly the ones
   2503   // below this comment after we have received initial data.
   2504   switch (transaction_pattern_) {
   2505     case PATTERN_ENTRY_CANT_CONDITIONALIZE: {
   2506       UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize",
   2507                           before_send_time);
   2508       UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize",
   2509                                before_send_percent);
   2510       break;
   2511     }
   2512     case PATTERN_ENTRY_NOT_CACHED: {
   2513       UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
   2514       UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached",
   2515                                before_send_percent);
   2516       break;
   2517     }
   2518     case PATTERN_ENTRY_VALIDATED: {
   2519       UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
   2520       UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated",
   2521                                before_send_percent);
   2522       break;
   2523     }
   2524     case PATTERN_ENTRY_UPDATED: {
   2525       UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
   2526       UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated",
   2527                                before_send_percent);
   2528       break;
   2529     }
   2530     default:
   2531       NOTREACHED();
   2532   }
   2533 }
   2534 
   2535 void HttpCache::Transaction::OnIOComplete(int result) {
   2536   DoLoop(result);
   2537 }
   2538 
   2539 }  // namespace net
   2540