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