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