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