15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_cache_transaction.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <algorithm>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/field_trial.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/metrics/sparse_histogram.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/load_timing_info.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_data_stream.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_status_flags.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/disk_cache/disk_cache.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_transaction.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_transaction_delegate.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/partial_data.h"
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_config_service.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//      a "non-error response" is one with a 2xx (Successful) or 3xx
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//      (Redirection) status code.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NonErrorResponse(int status_code) {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int status_code_range = status_code / 100;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return status_code_range == 2 || status_code_range == 3;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Error codes that will be considered indicative of a page being offline/
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// unreachable for LOAD_FROM_CACHE_IF_OFFLINE.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOfflineError(int error) {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (error == net::ERR_NAME_NOT_RESOLVED ||
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          error == net::ERR_INTERNET_DISCONNECTED ||
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          error == net::ERR_ADDRESS_UNREACHABLE ||
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          error == net::ERR_CONNECTION_TIMED_OUT);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Enum for UMA, indicating the status (with regard to offline mode) of
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// a particular request.
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum RequestOfflineStatus {
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // A cache transaction hit in cache (data was present and not stale)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // and returned it.
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OFFLINE_STATUS_FRESH_CACHE,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // A network request was required for a cache entry, and it succeeded.
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OFFLINE_STATUS_NETWORK_SUCCEEDED,
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // A network request was required for a cache entry, and it failed with
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // a non-offline error.
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OFFLINE_STATUS_NETWORK_FAILED,
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // A network request was required for a cache entry, it failed with an
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // offline error, and we could serve stale data if
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // LOAD_FROM_CACHE_IF_OFFLINE was set.
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // A network request was required for a cache entry, it failed with
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // an offline error, and there was no servable data in cache (even
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // stale data).
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OFFLINE_STATUS_MAX_ENTRIES
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RecordOfflineStatus(int load_flags, RequestOfflineStatus status) {
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Restrict to main frame to keep statistics close to
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // "would have shown them something useful if offline mode was enabled".
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (load_flags & net::LOAD_MAIN_FRAME) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("HttpCache.OfflineStatus", status,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              OFFLINE_STATUS_MAX_ENTRIES);
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// TODO(rvargas): Remove once we get the data.
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void RecordVaryHeaderHistogram(const net::HttpResponseInfo* response) {
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  enum VaryType {
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VARY_NOT_PRESENT,
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VARY_UA,
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VARY_OTHER,
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VARY_MAX
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  };
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VaryType vary = VARY_NOT_PRESENT;
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (response->vary_data.is_valid()) {
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    vary = VARY_OTHER;
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (response->headers->HasHeaderValue("vary", "user-agent"))
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      vary = VARY_UA;
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("HttpCache.Vary", vary, VARY_MAX);
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HeaderNameAndValue {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* name;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* value;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the request includes one of these request headers, then avoid caching
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to avoid getting confused.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const HeaderNameAndValue kPassThroughHeaders[] = {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "if-unmodified-since", NULL },  // causes unexpected 412s
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "if-match", NULL },             // causes unexpected 412s
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "if-range", NULL },
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { NULL, NULL }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ValidationHeaderInfo {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* request_header_name;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* related_response_header_name;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ValidationHeaderInfo kValidationHeaders[] = {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "if-modified-since", "last-modified" },
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "if-none-match", "etag" },
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the request includes one of these request headers, then avoid reusing
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// our cached copy if any.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const HeaderNameAndValue kForceFetchHeaders[] = {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "cache-control", "no-cache" },
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pragma", "no-cache" },
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { NULL, NULL }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the request includes one of these request headers, then force our
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cached copy (if any) to be revalidated before reusing it.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const HeaderNameAndValue kForceValidateHeaders[] = {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "cache-control", "max-age=0" },
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { NULL, NULL }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool HeaderMatches(const HttpRequestHeaders& headers,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const HeaderNameAndValue* search) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; search->name; ++search) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string header_value;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!headers.GetHeader(search->name, &header_value))
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!search->value)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ',');
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (v.GetNext()) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (LowerCaseEqualsASCII(v.value_begin(), v.value_end(), search->value))
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::Transaction::Transaction(
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RequestPriority priority,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpCache* cache,
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    HttpTransactionDelegate* transaction_delegate)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : next_state_(STATE_NONE),
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_(NULL),
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      priority_(priority),
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_(cache->AsWeakPtr()),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry_(NULL),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_entry_(NULL),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_response_(NULL),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_(NONE),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_state_(STATE_NONE),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reading_(false),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      invalid_range_(false),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      truncated_(false),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_sparse_(false),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      range_requested_(false),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handling_206_(false),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_pending_(false),
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      done_reading_(false),
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      vary_mismatch_(false),
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      couldnt_conditionalize_request_(false),
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_buf_len_(0),
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_offset_(0),
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_load_flags_(0),
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_len_(0),
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      io_callback_(base::Bind(&Transaction::OnIOComplete,
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                              weak_factory_.GetWeakPtr())),
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transaction_pattern_(PATTERN_UNDEFINED),
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      transaction_delegate_(transaction_delegate),
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      websocket_handshake_stream_base_create_helper_(NULL) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 arraysize(kValidationHeaders),
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 Invalid_number_of_validation_headers);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::Transaction::~Transaction() {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have to issue another IO, but we should never invoke the callback_
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after this point.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Reset();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transaction_delegate_ = NULL;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (cache_) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry_) {
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      bool cancel_request = reading_ && response_.headers;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cancel_request) {
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (partial_) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          entry_->disk_entry->CancelSparseIO();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cancel_request &= (response_.headers->response_code() == 200);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_->DoneWithEntry(entry_, this, cancel_request);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (cache_pending_) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_->RemovePendingTransaction(this);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const CompletionCallback& callback) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(buf_len, 0);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get() || !entry_)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need to track this operation for anything.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It could be possible to check if there is something already written and
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // avoid writing again (it should be the same, right?), but let's allow the
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caller to "update" the contents with something new.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       callback, true);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::Transaction::AddTruncatedFlag() {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ & WRITE || mode_ == NONE);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't set the flag for sparse entries.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (partial_.get() && !truncated_)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanResume(true))
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have received the whole resource already.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (done_reading_)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  truncated_ = true;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_state_ = STATE_NONE;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoLoop(OK);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState HttpCache::Transaction::GetWriterLoadState() const {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (network_trans_.get())
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return network_trans_->GetLoadState();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_ || !request_)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LOAD_STATE_WAITING_FOR_CACHE;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& HttpCache::Transaction::net_log() const {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_log_;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::Start(const HttpRequestInfo* request,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const CompletionCallback& callback,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const BoundNetLog& net_log) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that we only have one asynchronous call at a time.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback_.is_null());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!reading_);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!network_trans_.get());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry_);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRequest(net_log, request);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have to wait until the backend is initialized so we start the SM.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_GET_BACKEND;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoLoop(OK);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setting this here allows us to check for the existence of a callback_ to
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // determine if we are still inside Start.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::RestartIgnoringLastError(
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& callback) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that we only have one asynchronous call at a time.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback_.is_null());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = RestartNetworkRequest();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::RestartWithCertificate(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    X509Certificate* client_cert,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& callback) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that we only have one asynchronous call at a time.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback_.is_null());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = RestartNetworkRequestWithCertificate(client_cert);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::RestartWithAuth(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AuthCredentials& credentials,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& callback) {
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(auth_response_.headers.get());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that we only have one asynchronous call at a time.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback_.is_null());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear the intermediate response since we are going to start over.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_response_ = HttpResponseInfo();
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = RestartNetworkRequestWithAuth(credentials);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::Transaction::IsReadyToRestartForAuth() {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!network_trans_.get())
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_trans_->IsReadyToRestartForAuth();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const CompletionCallback& callback) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(buf_len, 0);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback_.is_null());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have an intermediate auth response at this point, then it means the
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // user wishes to read the network response (the error page).  If there is a
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // previous response in the cache then we should leave it intact.
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (auth_response_.headers.get() && mode_ != NONE) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_NOT_COVERED);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(mode_ & WRITE);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(mode_ == READ_WRITE);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reading_ = true;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (mode_) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READ_WRITE:
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(partial_.get());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!network_trans_.get()) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We are just reading from the cache, but we may be writing later.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ReadFromEntry(buf, buf_len);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NONE:
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WRITE:
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(network_trans_.get());
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = ReadFromNetwork(buf, buf_len);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READ:
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = ReadFromEntry(buf, buf_len);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = ERR_FAILED;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(callback_.is_null());
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::StopCaching() {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We really don't know where we are now. Hopefully there is no operation in
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // progress, but nothing really prevents this method to be called after we
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // point because we need the state machine for that (and even if we are really
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // free, that would be an asynchronous operation). In other words, keep the
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry how it is (it will be marked as truncated at destruction), and let
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the next piece of code that executes know that we are now reading directly
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the net.
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() &&
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !is_sparse_ && !range_requested_) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool HttpCache::Transaction::GetFullRequestHeaders(
460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpRequestHeaders* headers) const {
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (network_trans_)
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return network_trans_->GetFullRequestHeaders(headers);
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(ttuttle): Read headers from cache.
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::DoneReading() {
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cache_.get() && entry_) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(mode_, UPDATE);
471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (mode_ & WRITE) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoneWritingToEntry(true);
47368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else if (mode_ & READ) {
47468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // It is necessary to check mode_ & READ because it is possible
47568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // for mode_ to be NONE and entry_ non-NULL with a write entry
47668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // if StopCaching was called.
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      cache_->DoneReadingFromEntry(entry_, this);
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      entry_ = NULL;
479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Null headers means we encountered an error or haven't a response yet
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (auth_response_.headers.get())
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &auth_response_;
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return (response_.headers.get() || response_.ssl_info.cert.get() ||
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          response_.cert_request_info.get())
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)             ? &response_
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)             : NULL;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState HttpCache::Transaction::GetLoadState() const {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadState state = GetWriterLoadState();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state != LOAD_STATE_WAITING_FOR_CACHE)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return state;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cache_.get())
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cache_->GetLoadStateForPendingTransaction(this);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LOAD_STATE_IDLE;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UploadProgress HttpCache::Transaction::GetUploadProgress() const {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (network_trans_.get())
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return network_trans_->GetUploadProgress();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return final_upload_progress_;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HttpCache::Transaction::GetLoadTimingInfo(
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LoadTimingInfo* load_timing_info) const {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (network_trans_)
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return network_trans_->GetLoadTimingInfo(load_timing_info);
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (old_network_trans_load_timing_) {
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *load_timing_info = *old_network_trans_load_timing_;
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (first_cache_access_since_.is_null())
52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
52290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
52390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If the cache entry was opened, return that time.
52490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_info->send_start = first_cache_access_since_;
52590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This time doesn't make much sense when reading from the cache, so just use
52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the same time as send_start.
52790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_info->send_end = first_cache_access_since_;
52890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpCache::Transaction::SetPriority(RequestPriority priority) {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  priority_ = priority;
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (network_trans_)
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    network_trans_->SetPriority(priority_);
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
538f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  websocket_handshake_stream_base_create_helper_ = create_helper;
540f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (network_trans_)
541f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
542f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
543f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::DoCallback(int rv) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(rv != ERR_IO_PENDING);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback_.is_null());
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buf_ = NULL;  // Release the buffer before invoking the callback.
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since Run may result in Read being called, clear callback_ up front.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback c = callback_;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Reset();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  c.Run(rv);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::HandleResult(int rv) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(rv != ERR_IO_PENDING);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback_.is_null())
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoCallback(rv);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A few common patterns: (Foo* means Foo -> FooComplete)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Not-cached entry:
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Start():
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* ->
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* ->
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   PartialHeadersReceived
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Read():
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   NetworkRead* -> CacheWriteData*
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cached entry, no validation:
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Start():
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   -> BeginPartialCacheValidation() -> BeginCacheValidation()
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Read():
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CacheReadData*
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cached entry, validation (304):
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Start():
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   -> BeginPartialCacheValidation() -> BeginCacheValidation() ->
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   SendRequest* -> SuccessfulSendRequest -> UpdateCachedResponse ->
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CacheWriteResponse* -> UpdateCachedResponseComplete ->
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   OverwriteCachedResponse -> PartialHeadersReceived
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Read():
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CacheReadData*
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cached entry, validation and replace (200):
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Start():
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   -> BeginPartialCacheValidation() -> BeginCacheValidation() ->
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CacheWriteResponse* -> DoTruncateCachedData* -> TruncateCachedMetadata* ->
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   PartialHeadersReceived
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Read():
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   NetworkRead* -> CacheWriteData*
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sparse entry, partially cached, byte range request:
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Start():
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   -> BeginPartialCacheValidation() -> CacheQueryData* ->
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   ValidateEntryHeadersAndContinue() -> StartPartialCacheValidation ->
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteResponse* ->
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   UpdateCachedResponseComplete -> OverwriteCachedResponse ->
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   PartialHeadersReceived
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Read() 1:
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   NetworkRead* -> CacheWriteData*
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Read() 2:
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   NetworkRead* -> CacheWriteData* -> StartPartialCacheValidation ->
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CompletePartialCacheValidation -> CacheReadData* ->
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Read() 3:
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CacheReadData* -> StartPartialCacheValidation ->
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   -> PartialHeadersReceived -> NetworkRead* -> CacheWriteData*
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoLoop(int result) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(next_state_ != STATE_NONE);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = result;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_state_;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_NONE;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GET_BACKEND:
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoGetBackend();
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GET_BACKEND_COMPLETE:
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoGetBackendComplete(rv);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SEND_REQUEST:
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSendRequest();
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SEND_REQUEST_COMPLETE:
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSendRequestComplete(rv);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SUCCESSFUL_SEND_REQUEST:
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSuccessfulSendRequest();
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NETWORK_READ:
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoNetworkRead();
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NETWORK_READ_COMPLETE:
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoNetworkReadComplete(rv);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_INIT_ENTRY:
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoInitEntry();
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_OPEN_ENTRY:
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoOpenEntry();
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_OPEN_ENTRY_COMPLETE:
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoOpenEntryComplete(rv);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CREATE_ENTRY:
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCreateEntry();
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CREATE_ENTRY_COMPLETE:
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCreateEntryComplete(rv);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_DOOM_ENTRY:
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoDoomEntry();
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_DOOM_ENTRY_COMPLETE:
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoDoomEntryComplete(rv);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_ADD_TO_ENTRY:
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoAddToEntry();
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_ADD_TO_ENTRY_COMPLETE:
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoAddToEntryComplete(rv);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_START_PARTIAL_CACHE_VALIDATION:
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoStartPartialCacheValidation();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION:
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCompletePartialCacheValidation(rv);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_UPDATE_CACHED_RESPONSE:
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoUpdateCachedResponse();
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_UPDATE_CACHED_RESPONSE_COMPLETE:
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoUpdateCachedResponseComplete(rv);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_OVERWRITE_CACHED_RESPONSE:
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoOverwriteCachedResponse();
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TRUNCATE_CACHED_DATA:
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTruncateCachedData();
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TRUNCATE_CACHED_DATA_COMPLETE:
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTruncateCachedDataComplete(rv);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TRUNCATE_CACHED_METADATA:
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTruncateCachedMetadata();
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TRUNCATE_CACHED_METADATA_COMPLETE:
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTruncateCachedMetadataComplete(rv);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_PARTIAL_HEADERS_RECEIVED:
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoPartialHeadersReceived();
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_READ_RESPONSE:
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheReadResponse();
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_READ_RESPONSE_COMPLETE:
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheReadResponseComplete(rv);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_WRITE_RESPONSE:
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheWriteResponse();
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheWriteTruncatedResponse();
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheWriteResponseComplete(rv);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_READ_METADATA:
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheReadMetadata();
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_READ_METADATA_COMPLETE:
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheReadMetadataComplete(rv);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_QUERY_DATA:
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheQueryData();
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_QUERY_DATA_COMPLETE:
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheQueryDataComplete(rv);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_READ_DATA:
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheReadData();
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_READ_DATA_COMPLETE:
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheReadDataComplete(rv);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_WRITE_DATA:
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheWriteData(rv);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CACHE_WRITE_DATA_COMPLETE:
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoCacheWriteDataComplete(rv);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "bad state";
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_FAILED;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HandleResult(rv);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoGetBackend() {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = true;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_GET_BACKEND_COMPLETE;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cache_->GetBackendForTransaction(this);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoGetBackendComplete(int result) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result == OK || result == ERR_FAILED);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_GET_BACKEND,
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    result);
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = false;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldPassThrough()) {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_key_ = cache_->GenerateCacheKey(request_);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Requested cache access mode.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_ = READ;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_ = WRITE;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_ = READ_WRITE;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Downgrade to UPDATE if the request has been externally conditionalized.
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (external_validation_.initialized) {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (mode_ & WRITE) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Strip off the READ_DATA bit (and maybe add back a READ_META bit
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // in case READ was off).
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mode_ = UPDATE;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mode_ = NONE;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use PUT and DELETE only to invalidate existing stored entries.
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((request_->method == "PUT" || request_->method == "DELETE") &&
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_ != READ_WRITE && mode_ != WRITE) {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If must use cache, then we must fail.  This can happen for back/forward
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // navigations to a page generated via a form post.
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CACHE_MISS;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == NONE) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_.get()) {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_->RestoreHeaders(&custom_request_->extra_headers);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_.reset();
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_INIT_ENTRY;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is only set if we have something to do with the response.
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  range_requested_ = (partial_.get() != NULL);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoSendRequest() {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ & WRITE || mode_ == NONE);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!network_trans_.get());
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  send_request_since_ = TimeTicks::Now();
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a network transaction.
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv = cache_->network_layer_->CreateTransaction(
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      priority_, &network_trans_, NULL);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Old load timing information, if any, is now obsolete.
86990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  old_network_trans_load_timing_.reset();
87090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
871a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (websocket_handshake_stream_base_create_helper_)
872a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    network_trans_->SetWebSocketHandshakeStreamCreateHelper(
873a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        websocket_handshake_stream_base_create_helper_);
874a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportNetworkActionStart();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SEND_REQUEST_COMPLETE;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = network_trans_->Start(request_, io_callback_, net_log_);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoSendRequestComplete(int result) {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportNetworkActionFinish();
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If requested, and we have a readable cache entry, and we have
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // an error indicating that we're offline as opposed to in contact
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // with a bad server, read from cache anyway.
890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsOfflineError(result)) {
891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (mode_ == READ_WRITE && entry_ && !partial_) {
892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOfflineStatus(effective_load_flags_,
893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE);
894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) {
895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        UpdateTransactionPattern(PATTERN_NOT_COVERED);
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_.server_data_unavailable = true;
897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return SetupEntryForRead();
898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOfflineStatus(effective_load_flags_,
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE);
902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecordOfflineStatus(effective_load_flags_,
905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        (result == OK ? OFFLINE_STATUS_NETWORK_SUCCEEDED :
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        OFFLINE_STATUS_NETWORK_FAILED));
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we tried to conditionalize the request and failed, we know
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we won't be reading from the cache after this point.
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (couldnt_conditionalize_request_)
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mode_ = WRITE;
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not record requests that have network errors or restarts.
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateTransactionPattern(PATTERN_NOT_COVERED);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCertificateError(result)) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response = network_trans_->GetResponseInfo();
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we get a certificate error, then there is a certificate in ssl_info,
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so GetResponseInfo() should never return NULL here.
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(response);
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_.ssl_info = response->ssl_info;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response = network_trans_->GetResponseInfo();
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(response);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_.cert_request_info = response->cert_request_info;
931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (response_.was_cached) {
932c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DoneWritingToEntry(true);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We received the response headers and there is no error.
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoSuccessfulSendRequest() {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!new_response_);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_response->headers->response_code() == 401 ||
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_response->headers->response_code() == 407) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    auth_response_ = *new_response;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_response_ = new_response;
949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ValidatePartialResponse() && !auth_response_.headers.get()) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Something went wrong with this request and we have to restart it.
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we have an authentication response, we are exposed to weird things
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // hapenning if the user cancels the authentication before we receive
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the new response.
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_NOT_COVERED);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_ = HttpResponseInfo();
95690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ResetNetworkTransaction();
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_response_ = NULL;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have stored the full entry, but it changed and the server is
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sending a range. We have to delete the old entry.
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_NOT_COVERED);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(false);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (new_response_->headers->response_code() == 416 &&
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (request_->method == "GET" || request_->method == "POST")) {
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(NONE, mode_);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_ = *new_response_;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mode_ == WRITE &&
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == WRITE &&
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (request_->method == "PUT" || request_->method == "DELETE")) {
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (NonErrorResponse(new_response->headers->response_code())) {
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ret = cache_->DoomEntry(cache_key_, NULL);
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(OK, ret);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cache_->DoneWritingToEntry(entry_, true);
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    entry_ = NULL;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
990d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (request_->method == "POST" &&
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NonErrorResponse(new_response->headers->response_code())) {
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cache_->DoomMainEntryForUrl(request_->url);
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  RecordVaryHeaderHistogram(new_response);
9964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Are we expecting a response to a conditional query?
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == READ_WRITE || mode_ == UPDATE) {
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_response->headers->response_code() == 304 || handling_206_) {
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED);
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_UPDATE_CACHED_RESPONSE;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OK;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_ENTRY_UPDATED);
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = WRITE;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoNetworkRead() {
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportNetworkActionStart();
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_NETWORK_READ_COMPLETE;
1015868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoNetworkReadComplete(int result) {
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ & WRITE || mode_ == NONE);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportNetworkActionFinish();
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1023868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is an error or we aren't saving the data, we are done; just wait
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until the destructor runs to see if we can keep the data.
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == NONE || result < 0)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_WRITE_DATA;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoInitEntry() {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!new_entry_);
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1038868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == WRITE) {
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_DOOM_ENTRY;
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_OPEN_ENTRY;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoOpenEntry() {
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!new_entry_);
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_OPEN_ENTRY_COMPLETE;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = true;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_cache_access_since_ = TimeTicks::Now();
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
105758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return cache_->OpenEntry(cache_key_, &new_entry_, this);
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoOpenEntryComplete(int result) {
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OK, otherwise the cache will end up with an active entry without any
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transaction attached.
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = false;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_ADD_TO_ENTRY;
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_CACHE_RACE) {
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_INIT_ENTRY;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->method == "PUT" || request_->method == "DELETE") {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(mode_ == READ_WRITE || mode_ == WRITE);
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == READ_WRITE) {
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = WRITE;
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CREATE_ENTRY;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == UPDATE) {
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There is no cache entry to update; proceed without caching.
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache_->mode() == PLAYBACK)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Playback Cache Miss: " << request_->url;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The entry does not exist, and we are not permitted to create a new entry,
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so we must fail.
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_CACHE_MISS;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCreateEntry() {
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!new_entry_);
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CREATE_ENTRY_COMPLETE;
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = true;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
110958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return cache_->CreateEntry(cache_key_, &new_entry_, this);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCreateEntryComplete(int result) {
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OK, otherwise the cache will end up with an active entry without any
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transaction attached.
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    result);
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = false;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_ADD_TO_ENTRY;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_CACHE_RACE) {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_INIT_ENTRY;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result == OK) {
11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("HttpCache.OpenToCreateRace", false);
11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("HttpCache.OpenToCreateRace", true);
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have a race here: Maybe we failed to open the entry and decided to
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // create one, but by the time we called create, another transaction already
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // created the entry. If we want to eliminate this issue, we need an atomic
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // OpenOrCreate() method exposed by the disk cache.
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Unable to create cache entry";
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_.get())
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_->RestoreHeaders(&custom_request_->extra_headers);
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoDoomEntry() {
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_DOOM_ENTRY_COMPLETE;
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = true;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_cache_access_since_.is_null())
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_cache_access_since_ = TimeTicks::Now();
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY);
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
115158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return cache_->DoomEntry(cache_key_, this);
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoDoomEntryComplete(int result) {
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CREATE_ENTRY;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = false;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_CACHE_RACE)
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_INIT_ENTRY;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoAddToEntry() {
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(new_entry_);
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = true;
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_ADD_TO_ENTRY_COMPLETE;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry_lock_waiting_since_.is_null());
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_lock_waiting_since_ = TimeTicks::Now();
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cache_->AddTransactionToEntry(new_entry_, this);
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoAddToEntryComplete(int result) {
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY,
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    result);
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TimeDelta entry_lock_wait =
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeTicks::Now() - entry_lock_waiting_since_;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("HttpCache.EntryLockWait", entry_lock_wait);
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_lock_waiting_since_ = TimeTicks();
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(new_entry_);
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_pending_ = false;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result == OK)
11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    entry_ = new_entry_;
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there is a failure, the cache should have taken care of new_entry_.
11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_entry_ = NULL;
11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_CACHE_RACE) {
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_INIT_ENTRY;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK) {
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == WRITE) {
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_.get())
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_->RestoreHeaders(&custom_request_->extra_headers);
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have to read the headers from the cached entry.
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(mode_ & READ_META);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CACHE_READ_RESPONSE;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We may end up here multiple times for a given request.
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoStartPartialCacheValidation() {
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == NONE)
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
121958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_);
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result) {
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is the end of the request.
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mode_ & WRITE) {
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoneWritingToEntry(true);
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_->DoneReadingFromEntry(entry_, this);
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry_ = NULL;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partial_->PrepareCacheValidation(entry_->disk_entry,
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &custom_request_->extra_headers);
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reading_ && partial_->IsCurrentRangeCached()) {
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CACHE_READ_DATA;
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return BeginCacheValidation();
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We received 304 or 206 and we want to update the cached response headers.
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoUpdateCachedResponse() {
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = OK;
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update cached response based on headers in new_response.
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(wtc): should we update cached certificate (response_.ssl_info), too?
1254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  response_.headers->Update(*new_response_->headers.get());
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_.response_time = new_response_->response_time;
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_.request_time = new_response_->request_time;
1257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response_.network_accessed = new_response_->network_accessed;
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->HasHeaderValue("cache-control", "no-store")) {
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!entry_->doomed) {
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ret = cache_->DoomEntry(cache_key_, NULL);
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(OK, ret);
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we are already reading, we already updated the headers for this
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // request; doing it again will change Content-Length.
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reading_) {
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_CACHE_WRITE_RESPONSE;
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = OK;
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == UPDATE) {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!handling_206_);
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We got a "not modified" response and already updated the corresponding
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // cache entry above.
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // By closing the cached entry now, we make sure that the 304 rather than
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the cached 200 response, is what will be returned to the user.
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(true);
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (entry_ && !handling_206_) {
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(READ_WRITE, mode_);
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!partial_.get() || partial_->IsLastRange()) {
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_->ConvertWriterToReader(entry_);
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_ = READ;
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We no longer need the network transaction, so destroy it.
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    final_upload_progress_ = network_trans_->GetUploadProgress();
129390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ResetNetworkTransaction();
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (entry_ && handling_206_ && truncated_ &&
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             partial_->initial_validation()) {
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We just finished the validation of a truncated entry, and the server
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is willing to resume the operation. Now we go back and start serving
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the first part to the user.
129990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ResetNetworkTransaction();
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_response_ = NULL;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    partial_->SetRangeToStartDownload();
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoOverwriteCachedResponse() {
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ & READ) {
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We change the value of Content-Length for partial content.
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handling_206_ && partial_.get())
1317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    partial_->FixContentLength(new_response_->headers.get());
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_ = *new_response_;
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handling_206_ && !CanResume(false)) {
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There is no point in storing this resource because it will never be used.
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(false);
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_.get())
1325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      partial_->FixResponseHeaders(response_.headers.get(), true);
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_state_ = STATE_TRUNCATE_CACHED_DATA;
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE :
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             STATE_CACHE_WRITE_RESPONSE;
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoTruncateCachedData() {
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_)
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_.IsLoggingAllEvents())
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Truncate the stream.
134458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_);
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_) {
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportCacheActionFinish();
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (net_log_.IsLoggingAllEvents()) {
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          result);
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TRUNCATE_CACHED_METADATA;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoTruncateCachedMetadata() {
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TRUNCATE_CACHED_METADATA_COMPLETE;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_)
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_.IsLoggingAllEvents())
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
136858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return WriteToEntry(kMetadataIndex, 0, NULL, 0, io_callback_);
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) {
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_) {
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportCacheActionFinish();
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_log_.IsLoggingAllEvents()) {
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        result);
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoPartialHeadersReceived() {
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_response_ = NULL;
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_ && !partial_.get() &&
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry_->disk_entry->GetDataSize(kMetadataIndex))
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CACHE_READ_METADATA;
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!partial_.get())
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reading_) {
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (network_trans_.get()) {
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_NETWORK_READ;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_CACHE_READ_DATA;
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (mode_ != NONE) {
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are about to return the headers for a byte-range request to the user,
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so let's fix them.
1402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    partial_->FixResponseHeaders(response_.headers.get(), true);
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheReadResponse() {
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry_);
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buf_ = new IOBuffer(io_buf_len_);
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
141658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
141758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      io_buf_len_, io_callback_);
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != io_buf_len_ ||
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_,
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &response_, &truncated_)) {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnCacheReadError(result, true);
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some resources may have slipped in as truncated when they're not.
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->GetContentLength() == current_size)
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    truncated_ = false;
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We now have access to the cache entry.
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  o if we are a reader for the transaction, then we can start reading the
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    cache entry.
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  o if we can read or write, then we should check if the cache entry needs
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    to be validated and then issue a network request if needed or just read
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    from the cache if the cache entry is already valid.
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  o if we are set to UPDATE, then we are handling an externally
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    conditionalized request (if-modified-since / if-none-match). We check
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    if the request headers define a validation request.
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (mode_) {
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READ:
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateTransactionPattern(PATTERN_ENTRY_USED);
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = BeginCacheRead();
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READ_WRITE:
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = BeginPartialCacheValidation();
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case UPDATE:
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = BeginExternallyConditionalizedRequest();
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WRITE:
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = ERR_FAILED;
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheWriteResponse() {
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_) {
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_log_.IsLoggingAllEvents())
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportCacheActionStart();
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WriteResponseInfoToEntry(false);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_) {
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_log_.IsLoggingAllEvents())
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportCacheActionStart();
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WriteResponseInfoToEntry(true);
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = target_state_;
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_state_ = STATE_NONE;
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_.IsLoggingAllEvents()) {
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      result);
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balance the AddRef from WriteResponseInfoToEntry.
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != io_buf_len_) {
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "failed to write response info to cache";
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(false);
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheReadMetadata() {
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry_);
1505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!response_.metadata.get());
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_READ_METADATA_COMPLETE;
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_.metadata =
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex));
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
151358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return entry_->disk_entry->ReadData(kMetadataIndex, 0,
151458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      response_.metadata.get(),
151558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      response_.metadata->size(),
151658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      io_callback_);
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != response_.metadata->size())
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnCacheReadError(result, false);
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheQueryData() {
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
152958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return entry_->disk_entry->ReadyForSparseIO(io_callback_);
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
153358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result == ERR_NOT_IMPLEMENTED) {
153458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Restart the request overwriting the cache entry.
153558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // TODO(pasko): remove this workaround as soon as the SimpleBackendImpl
153658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // supports Sparse IO.
153758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return DoRestartPartialRequest();
153858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(OK, result);
1540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ValidateEntryHeadersAndContinue();
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheReadData() {
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry_);
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_.IsLoggingAllEvents())
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA);
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionStart();
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (partial_.get()) {
155458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_,
155558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                               io_callback_);
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_,
155958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      read_buf_.get(), io_buf_len_,
156058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      io_callback_);
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportCacheActionFinish();
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_.IsLoggingAllEvents()) {
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      result);
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (partial_.get()) {
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Partial requests are confusing to report in histograms because they may
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // have multiple underlying requests.
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_NOT_COVERED);
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoPartialCacheReadCompleted(result);
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result > 0) {
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_offset_ += result;
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result == 0) {  // End of file.
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecordHistograms();
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_->DoneReadingFromEntry(entry_, this);
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry_ = NULL;
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnCacheReadError(result, false);
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_len_ = num_bytes;
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_) {
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_log_.IsLoggingAllEvents())
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportCacheActionStart();
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return AppendResponseDataToEntry(read_buf_.get(), num_bytes, io_callback_);
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_) {
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportCacheActionFinish();
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_log_.IsLoggingAllEvents()) {
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        result);
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balance the AddRef from DoCacheWriteData.
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get())
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != write_len_) {
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "failed to write response data to cache";
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(false);
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We want to ignore errors writing to disk and just keep reading from
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the network.
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = write_len_;
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!done_reading_ && entry_) {
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 body_size = response_.headers->GetContentLength();
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (body_size >= 0 && body_size <= current_size)
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      done_reading_ = true;
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (partial_.get()) {
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This may be the last request.
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(result == 0 && !truncated_ &&
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (partial_->IsLastRange() || mode_ == WRITE)))
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return DoPartialNetworkReadCompleted(result);
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0) {
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // End of file. This may be the result of a connection problem so see if we
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // have to keep the entry around to be flagged as truncated later on.
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (done_reading_ || !entry_ || partial_.get() ||
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_.headers->GetContentLength() <= 0)
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoneWritingToEntry(true);
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log,
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const HttpRequestInfo* request) {
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_ = net_log;
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_ = request;
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  effective_load_flags_ = request_->load_flags;
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (cache_->mode()) {
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NORMAL:
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RECORD:
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // When in record mode, we want to NEVER load from the cache.
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The reason for this is beacuse we save the Set-Cookie headers
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (intentionally).  If we read from the cache, we replay them
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // prematurely.
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_load_flags_ |= LOAD_BYPASS_CACHE;
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PLAYBACK:
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // When in playback mode, we want to load exclusively from the cache.
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_load_flags_ |= LOAD_ONLY_FROM_CACHE;
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DISABLE:
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_load_flags_ |= LOAD_DISABLE_CACHE;
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some headers imply load flags.  The order here is significant.
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   LOAD_DISABLE_CACHE   : no cache read or write
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   LOAD_BYPASS_CACHE    : no cache read
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   LOAD_VALIDATE_CACHE  : no cache read unless validation
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The former modes trump latter modes, so if we find a matching header we
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can stop iterating kSpecialHeaders.
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const struct {
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderNameAndValue* search;
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int load_flag;
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } kSpecialHeaders[] = {
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kPassThroughHeaders, LOAD_DISABLE_CACHE },
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kForceFetchHeaders, LOAD_BYPASS_CACHE },
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kForceValidateHeaders, LOAD_VALIDATE_CACHE },
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool range_found = false;
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool external_validation_error = false;
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange))
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range_found = true;
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSpecialHeaders); ++i) {
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HeaderMatches(request_->extra_headers, kSpecialHeaders[i].search)) {
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_load_flags_ |= kSpecialHeaders[i].load_flag;
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for conditionalization headers which may correspond with a
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cache validation request.
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kValidationHeaders); ++i) {
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ValidationHeaderInfo& info = kValidationHeaders[i];
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string validation_value;
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (request_->extra_headers.GetHeader(
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            info.request_header_name, &validation_value)) {
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!external_validation_.values[i].empty() ||
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          validation_value.empty()) {
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        external_validation_error = true;
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      external_validation_.values[i] = validation_value;
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      external_validation_.initialized = true;
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't support ranges and validation headers.
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (range_found && external_validation_.initialized) {
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Byte ranges AND validation headers found.";
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_load_flags_ |= LOAD_DISABLE_CACHE;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is more than one validation header, we can't treat this request as
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a cache validation, since we don't know for sure which header the server
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will give us a response for (and they could be contradictory).
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (external_validation_error) {
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Multiple or malformed validation headers found.";
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_load_flags_ |= LOAD_DISABLE_CACHE;
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_NOT_COVERED);
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    partial_.reset(new PartialData);
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (request_->method == "GET" && partial_->Init(request_->extra_headers)) {
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We will be modifying the actual range requested to the server, so
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // let's remove the header here.
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      custom_request_.reset(new HttpRequestInfo(*request_));
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_ = custom_request_.get();
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_->SetHeaders(custom_request_->extra_headers);
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The range is invalid or we cannot handle it properly.
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Invalid byte range found.";
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_load_flags_ |= LOAD_DISABLE_CACHE;
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_.reset(NULL);
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::Transaction::ShouldPassThrough() {
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have a null disk_cache if there is an error we cannot recover from,
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // like not enough disk space, or sharing violations.
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cache_->disk_cache_.get())
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When using the record/playback modes, we always use the cache
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and we never pass through.
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache_->mode() == RECORD || cache_->mode() == PLAYBACK)
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (effective_load_flags_ & LOAD_DISABLE_CACHE)
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->method == "GET")
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request_->method == "POST" && request_->upload_data_stream &&
17732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request_->upload_data_stream->identifier()) {
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request_->method == "PUT" && request_->upload_data_stream)
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->method == "DELETE")
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): add support for caching HEAD responses
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::BeginCacheRead() {
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges.
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->response_code() == 206 || partial_.get()) {
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CACHE_MISS;
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't have the whole resource.
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (truncated_)
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CACHE_MISS;
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_->disk_entry->GetDataSize(kMetadataIndex))
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CACHE_READ_METADATA;
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::BeginCacheValidation() {
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ == READ_WRITE);
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool skip_validation = !RequiresValidation();
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (truncated_) {
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Truncated entries can cause partial gets, so we shouldn't record this
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // load in histograms.
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_NOT_COVERED);
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    skip_validation = !partial_->initial_validation();
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (partial_.get() && (is_sparse_ || truncated_) &&
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (!partial_->IsCurrentRangeCached() || invalid_range_)) {
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Force revalidation for sparse or truncated entries. Note that we don't
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // want to ignore the regular validation logic just because a byte range was
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // part of the request.
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    skip_validation = false;
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (skip_validation) {
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_ENTRY_USED);
1826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE);
18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SetupEntryForRead();
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make the network request conditional, to see if we may reuse our cached
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // response.  If we cannot do so, then we just resort to a normal fetch.
18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Our mode remains READ_WRITE for a conditional request.  Even if the
18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // conditionalization fails, we don't switch to WRITE mode until we
18332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // know we won't be falling back to using the cache entry in the
18342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // LOAD_FROM_CACHE_IF_OFFLINE case.
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ConditionalizeRequest()) {
18362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      couldnt_conditionalize_request_ = true;
18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE);
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (partial_.get())
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return DoRestartPartialRequest();
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_NE(206, response_.headers->response_code());
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::BeginPartialCacheValidation() {
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ == READ_WRITE);
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->response_code() != 206 && !partial_.get() &&
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !truncated_) {
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return BeginCacheValidation();
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Partial requests should not be recorded in histograms.
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateTransactionPattern(PATTERN_NOT_COVERED);
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (range_requested_) {
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CACHE_QUERY_DATA;
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request is not for a range, but we have stored just ranges.
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partial_.reset(new PartialData());
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partial_->SetHeaders(request_->extra_headers);
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!custom_request_.get()) {
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    custom_request_.reset(new HttpRequestInfo(*request_));
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_ = custom_request_.get();
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ValidateEntryHeadersAndContinue();
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This should only be called once per request.
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::ValidateEntryHeadersAndContinue() {
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ == READ_WRITE);
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!partial_->UpdateFromStoredHeaders(
1878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          response_.headers.get(), entry_->disk_entry, truncated_)) {
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoRestartPartialRequest();
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->response_code() == 206)
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_sparse_ = true;
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!partial_->IsRequestedRangeOK()) {
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The stored data is fine, but the request may be invalid.
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalid_range_ = true;
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(UPDATE, mode_);
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(external_validation_.initialized);
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0;  i < arraysize(kValidationHeaders); i++) {
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (external_validation_.values[i].empty())
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Retrieve either the cached response's "etag" or "last-modified" header.
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string validator;
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_.headers->EnumerateHeader(
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL,
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kValidationHeaders[i].related_response_header_name,
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &validator);
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (response_.headers->response_code() != 200 || truncated_ ||
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        validator.empty() || validator != external_validation_.values[i]) {
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The externally conditionalized request is not a validation request
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // for our existing cache entry. Proceed with caching disabled.
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateTransactionPattern(PATTERN_NOT_COVERED);
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoneWritingToEntry(true);
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SEND_REQUEST;
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::RestartNetworkRequest() {
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ & WRITE || mode_ == NONE);
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(network_trans_.get());
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportNetworkActionStart();
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SEND_REQUEST_COMPLETE;
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = network_trans_->RestartIgnoringLastError(io_callback_);
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoLoop(rv);
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::RestartNetworkRequestWithCertificate(
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    X509Certificate* client_cert) {
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ & WRITE || mode_ == NONE);
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(network_trans_.get());
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportNetworkActionStart();
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SEND_REQUEST_COMPLETE;
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = network_trans_->RestartWithCertificate(client_cert, io_callback_);
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoLoop(rv);
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::RestartNetworkRequestWithAuth(
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AuthCredentials& credentials) {
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ & WRITE || mode_ == NONE);
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(network_trans_.get());
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportNetworkActionStart();
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SEND_REQUEST_COMPLETE;
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = network_trans_->RestartWithAuth(credentials, io_callback_);
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoLoop(rv);
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::Transaction::RequiresValidation() {
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): need to do more work here:
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - make sure we have a matching request method
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - watch out for cached responses that depend on authentication
19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In playback mode, nothing requires validation.
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache_->mode() == net::HttpCache::PLAYBACK)
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (response_.vary_data.is_valid() &&
1972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !response_.vary_data.MatchesRequest(*request_,
1973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          *response_.headers.get())) {
19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    vary_mismatch_ = true;
19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (effective_load_flags_ & LOAD_PREFERRING_CACHE)
19792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (effective_load_flags_ & LOAD_VALIDATE_CACHE)
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->method == "PUT" || request_->method == "DELETE")
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->RequiresValidation(
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response_.request_time, response_.response_time, Time::Now())) {
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::Transaction::ConditionalizeRequest() {
1996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(response_.headers.get());
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->method == "PUT" || request_->method == "DELETE")
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This only makes sense for cached 200 or 206 responses.
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->response_code() != 200 &&
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_.headers->response_code() != 206) {
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have handled this case before.
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(response_.headers->response_code() != 206 ||
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         response_.headers->HasStrongValidators());
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Just use the first available ETag and/or Last-Modified header value.
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): Or should we use the last?
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string etag_value;
20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1))
20162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response_.headers->EnumerateHeader(NULL, "etag", &etag_value);
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string last_modified_value;
20192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!vary_mismatch_) {
20202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response_.headers->EnumerateHeader(NULL, "last-modified",
20212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &last_modified_value);
20222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (etag_value.empty() && last_modified_value.empty())
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!partial_.get()) {
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Need to customize the request, so this forces us to allocate :(
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    custom_request_.reset(new HttpRequestInfo(*request_));
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_ = custom_request_.get();
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(custom_request_.get());
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() &&
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      !invalid_range_;
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!etag_value.empty()) {
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_if_range) {
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We don't want to switch to WRITE mode if we don't have this block of a
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // byte-range request because we may have other parts cached.
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      custom_request_->extra_headers.SetHeader(
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpRequestHeaders::kIfRange, etag_value);
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      custom_request_->extra_headers.SetHeader(
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpRequestHeaders::kIfNoneMatch, etag_value);
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For byte-range requests, make sure that we use only one way to validate
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the request.
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_.get() && !partial_->IsCurrentRangeCached())
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!last_modified_value.empty()) {
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_if_range) {
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      custom_request_->extra_headers.SetHeader(
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpRequestHeaders::kIfRange, last_modified_value);
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      custom_request_->extra_headers.SetHeader(
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpRequestHeaders::kIfModifiedSince, last_modified_value);
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We just received some headers from the server. We may have asked for a range,
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in which case partial_ has an object. This could be the first network request
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we make to fulfill the original request, or we may be already reading (from
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the net and / or the cache). If we are not expecting a certain response, we
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just bypass the cache for this request (but again, maybe we are reading), and
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// delete partial_ (so we are not able to "fix" the headers that we return to
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the user). This results in either a weird response for the caller (we don't
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expect it after all), or maybe a range that was not exactly what it was asked
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for.
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the server is simply telling us that the resource has changed, we delete
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the cached entry and restart the request as the caller intended (by returning
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// false from this method). However, we may not be able to do that at any point,
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for instance if we already returned the headers to the user.
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WARNING: Whenever this code returns false, it has to make sure that the next
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time it is called it will return true so that we don't keep retrying the
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// request.
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::Transaction::ValidatePartialResponse() {
2085868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const HttpResponseHeaders* headers = new_response_->headers.get();
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_code = headers->response_code();
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool partial_response = (response_code == 206);
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handling_206_ = false;
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_ || request_->method != "GET")
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (invalid_range_) {
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We gave up trying to match this request with the stored data. If the
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server is ok with the request, delete the entry, otherwise just ignore
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this request
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!reading_);
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_response || response_code == 200) {
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoomPartialEntry(true);
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_ = NONE;
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (response_code == 304)
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FailRangeRequest();
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IgnoreRangeRequest();
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!partial_.get()) {
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are not expecting 206 but we may have one.
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_response)
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IgnoreRangeRequest();
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rvargas): Do we need to consider other results here?.
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool failure = response_code == 200 || response_code == 416;
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (partial_->IsCurrentRangeCached()) {
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We asked for "If-None-Match: " so a 206 means a new object.
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_response)
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failure = true;
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (response_code == 304 && partial_->ResponseHeadersOK(headers))
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We asked for "If-Range: " so a 206 means just another range.
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (partial_response && partial_->ResponseHeadersOK(headers)) {
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handling_206_ = true;
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reading_ && !is_sparse_ && !partial_response) {
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See if we can ignore the fact that we issued a byte range request.
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the server sends 200, just store it. If it sends an error, redirect
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // or something else, we may store the response as long as we didn't have
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // anything already stored.
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (response_code == 200 ||
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (!truncated_ && response_code != 304 && response_code != 416)) {
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The server is sending something else, and we can save it.
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK((truncated_ && !partial_->IsLastRange()) || range_requested_);
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        partial_.reset();
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        truncated_ = false;
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 304 is not expected here, but we'll spare the entry (unless it was
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // truncated).
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (truncated_)
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failure = true;
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (failure) {
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We cannot truncate this entry, it has to be deleted.
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTransactionPattern(PATTERN_NOT_COVERED);
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoomPartialEntry(false);
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_ = NONE;
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reading_ && !partial_->IsLastRange()) {
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We'll attempt to issue another network request, this time without us
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // messing up the headers.
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_->RestoreHeaders(&custom_request_->extra_headers);
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partial_.reset();
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      truncated_ = false;
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to revalidate partial entry";
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    partial_.reset();
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IgnoreRangeRequest();
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::IgnoreRangeRequest() {
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have a problem. We may or may not be reading already (in which case we
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returned the headers), but we'll just pretend that this request is not
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using the cache and see what happens. Most likely this is the first
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response from the server (it's not changing its mind midway, right?).
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateTransactionPattern(PATTERN_NOT_COVERED);
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ & WRITE)
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(mode_ != WRITE);
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (mode_ & READ && entry_)
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_->DoneReadingFromEntry(entry_, this);
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partial_.reset(NULL);
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_ = NULL;
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode_ = NONE;
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::FailRangeRequest() {
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_ = *new_response_;
2195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  partial_->FixResponseHeaders(response_.headers.get(), false);
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HttpCache::Transaction::SetupEntryForRead() {
219990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (network_trans_)
220090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ResetNetworkTransaction();
22012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (partial_.get()) {
22022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (truncated_ || is_sparse_ || !invalid_range_) {
22032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // We are going to return the saved response headers to the caller, so
22042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // we may need to adjust them first.
22052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
22062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return OK;
22072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
22082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      partial_.reset();
22092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
22102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
22112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cache_->ConvertWriterToReader(entry_);
22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mode_ = READ;
22132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (entry_->disk_entry->GetDataSize(kMetadataIndex))
22152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    next_state_ = STATE_CACHE_READ_METADATA;
22162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return OK;
22172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
22182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buf_ = data;
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_buf_len_ = data_len;
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_NETWORK_READ;
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DoLoop(OK);
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) {
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buf_ = data;
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_buf_len_ = data_len;
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_READ_DATA;
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DoLoop(OK);
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::WriteToEntry(int index, int offset,
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         IOBuffer* data, int data_len,
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const CompletionCallback& callback) {
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_)
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data_len;
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = 0;
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!partial_.get() || !data_len) {
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback,
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       true);
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback);
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_)
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not cache no-store content (unless we are record mode).  Do not cache
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content with cert errors either.  This is to prevent not reporting net
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // errors when loading a resource from the cache.  When we load a page over
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // HTTPS with a cert error we show an SSL blocking page.  If the user clicks
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // proceed we reload the resource ignoring the errors.  The loaded resource
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is then cached.  If that resource is subsequently loaded from the cache,
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // no net error is reported (even though the cert status contains the actual
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // errors) and no SSL blocking page is shown.  An alternative would be to
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reverse-map the cert status to a net error and replay the net error.
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((cache_->mode() != RECORD &&
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       response_.headers->HasHeaderValue("cache-control", "no-store")) ||
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::IsCertStatusError(response_.ssl_info.cert_status)) {
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(false);
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportCacheActionFinish();
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_log_.IsLoggingAllEvents())
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When writing headers, we normally only write the non-transient
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // headers; when in record mode, record everything.
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool skip_transient_headers = (cache_->mode() != RECORD);
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (truncated)
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(200, response_.headers->response_code());
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_.Persist(data->pickle(), skip_transient_headers, truncated);
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->Done();
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_buf_len_ = data->pickle()->size();
228658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
228758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                       io_buf_len_, io_callback_, true);
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::AppendResponseDataToEntry(
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOBuffer* data, int data_len, const CompletionCallback& callback) {
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_ || !data_len)
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data_len;
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WriteToEntry(kResponseContentIndex, current_size, data, data_len,
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      callback);
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::DoneWritingToEntry(bool success) {
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry_)
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordHistograms();
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_->DoneWritingToEntry(entry_, success);
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_ = NULL;
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode_ = NONE;  // switch to 'pass through' mode
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(ERROR) << "ReadData failed: " << result;
231390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int result_for_histogram = std::max(0, -result);
231490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (restart) {
231590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
231690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                result_for_histogram);
231790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
231890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
231990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                result_for_histogram);
232090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Avoid using this entry in the future.
2323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cache_.get())
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_->DoomActiveEntry(cache_key_);
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (restart) {
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!reading_);
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!network_trans_.get());
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_->DoneWithEntry(entry_, this, false);
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry_ = NULL;
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_sparse_ = false;
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    partial_.reset();
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_GET_BACKEND;
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_CACHE_READ_FAILURE;
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(2) << "DoomPartialEntry";
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = cache_->DoomEntry(cache_key_, NULL);
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(OK, rv);
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_->DoneWithEntry(entry_, this, false);
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_ = NULL;
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_sparse_ = false;
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delete_object)
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    partial_.reset(NULL);
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partial_->OnNetworkReadCompleted(result);
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0) {
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to move on to the next range.
235690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ResetNetworkTransaction();
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partial_->OnCacheReadCompleted(result);
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0 && mode_ == READ_WRITE) {
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to move on to the next range.
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result < 0) {
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnCacheReadError(result, false);
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::Transaction::DoRestartPartialRequest() {
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The stored data cannot be used. Get rid of it and restart this request.
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to also reset the |truncated_| flag as a new entry is created.
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoomPartialEntry(!range_requested_);
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode_ = WRITE;
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  truncated_ = false;
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_INIT_ENTRY;
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
238458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void HttpCache::Transaction::ResetNetworkTransaction() {
238558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(!old_network_trans_load_timing_);
238658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(network_trans_);
238758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LoadTimingInfo load_timing;
238858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (network_trans_->GetLoadTimingInfo(&load_timing))
238958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
239058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  network_trans_.reset();
239158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
239258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Histogram data from the end of 2010 show the following distribution of
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// response headers:
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Content-Length............... 87%
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Date......................... 98%
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Last-Modified................ 49%
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Etag......................... 19%
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Accept-Ranges: bytes......... 25%
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Accept-Ranges: none.......... 0.4%
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Strong Validator............. 50%
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Strong Validator + ranges.... 24%
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Strong Validator + CL........ 49%
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::Transaction::CanResume(bool has_data) {
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Double check that there is something worth keeping.
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_data && !entry_->disk_entry->GetDataSize(kResponseContentIndex))
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->method != "GET")
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Note that if this is a 206, content-length was already fixed after calling
24150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // PartialData::ResponseHeadersOK().
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->GetContentLength() <= 0 ||
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !response_.headers->HasStrongValidators()) {
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::OnIOComplete(int result) {
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoLoop(result);
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::ReportCacheActionStart() {
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transaction_delegate_)
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_delegate_->OnCacheActionStart();
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::ReportCacheActionFinish() {
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transaction_delegate_)
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_delegate_->OnCacheActionFinish();
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::ReportNetworkActionStart() {
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transaction_delegate_)
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_delegate_->OnNetworkActionStart();
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::ReportNetworkActionFinish() {
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transaction_delegate_)
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transaction_delegate_->OnNetworkActionFinish();
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::UpdateTransactionPattern(
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionPattern new_transaction_pattern) {
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transaction_pattern_ == PATTERN_NOT_COVERED)
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transaction_pattern_ == PATTERN_UNDEFINED ||
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         new_transaction_pattern == PATTERN_NOT_COVERED);
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transaction_pattern_ = new_transaction_pattern;
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::Transaction::RecordHistograms() {
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(PATTERN_UNDEFINED, transaction_pattern_);
2460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache_.get() || !cache_->GetCurrentBackend() ||
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE ||
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_->mode() != NORMAL || request_->method != "GET") {
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
24662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "HttpCache.Pattern", transaction_pattern_, PATTERN_MAX);
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transaction_pattern_ == PATTERN_NOT_COVERED)
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!range_requested_);
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!first_cache_access_since_.is_null());
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_send_request = !send_request_since_.is_null();
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(
24782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (did_send_request &&
24792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       (transaction_pattern_ == PATTERN_ENTRY_NOT_CACHED ||
24802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        transaction_pattern_ == PATTERN_ENTRY_VALIDATED ||
24812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        transaction_pattern_ == PATTERN_ENTRY_UPDATED ||
24822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        transaction_pattern_ == PATTERN_ENTRY_CANT_CONDITIONALIZE)) ||
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (!did_send_request && transaction_pattern_ == PATTERN_ENTRY_USED));
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!did_send_request) {
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(transaction_pattern_ == PATTERN_ENTRY_USED);
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time);
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta before_send_time = send_request_since_ - first_cache_access_since_;
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int before_send_percent =
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_time.ToInternalValue() == 0 ? 0
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        : before_send_time * 100 / total_time;
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(0, before_send_percent);
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(100, before_send_percent);
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time);
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_percent);
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(gavinp): Remove or minimize these histograms, particularly the ones
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // below this comment after we have received initial data.
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (transaction_pattern_) {
25052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case PATTERN_ENTRY_CANT_CONDITIONALIZE: {
25062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize",
25072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          before_send_time);
25082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize",
25092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               before_send_percent);
25102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
25112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PATTERN_ENTRY_NOT_CACHED: {
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
25142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached",
25152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               before_send_percent);
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PATTERN_ENTRY_VALIDATED: {
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated",
25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               before_send_percent);
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PATTERN_ENTRY_UPDATED: {
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
25262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated",
25272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               before_send_percent);
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
2536