1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/http/http_cache_transaction.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
8*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" // For IS_POSIX
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX)
11*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
12*6777b538SAndroid Build Coastguard Worker #endif
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker #include <algorithm>
15*6777b538SAndroid Build Coastguard Worker #include <memory>
16*6777b538SAndroid Build Coastguard Worker #include <string>
17*6777b538SAndroid Build Coastguard Worker #include <type_traits>
18*6777b538SAndroid Build Coastguard Worker #include <utility>
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker #include "base/auto_reset.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/containers/fixed_flat_set.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/format_macros.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/power_monitor/power_monitor.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
33*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h" // For EqualsCaseInsensitiveASCII.
34*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
35*6777b538SAndroid Build Coastguard Worker #include "base/time/clock.h"
36*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/common/trace_event_common.h"
37*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/base/auth.h"
39*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
40*6777b538SAndroid Build Coastguard Worker #include "net/base/load_flags.h"
41*6777b538SAndroid Build Coastguard Worker #include "net/base/load_timing_info.h"
42*6777b538SAndroid Build Coastguard Worker #include "net/base/trace_constants.h"
43*6777b538SAndroid Build Coastguard Worker #include "net/base/tracing.h"
44*6777b538SAndroid Build Coastguard Worker #include "net/base/transport_info.h"
45*6777b538SAndroid Build Coastguard Worker #include "net/base/upload_data_stream.h"
46*6777b538SAndroid Build Coastguard Worker #include "net/cert/cert_status_flags.h"
47*6777b538SAndroid Build Coastguard Worker #include "net/cert/x509_certificate.h"
48*6777b538SAndroid Build Coastguard Worker #include "net/disk_cache/disk_cache.h"
49*6777b538SAndroid Build Coastguard Worker #include "net/http/http_cache_writers.h"
50*6777b538SAndroid Build Coastguard Worker #include "net/http/http_log_util.h"
51*6777b538SAndroid Build Coastguard Worker #include "net/http/http_network_session.h"
52*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_info.h"
53*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_headers.h"
54*6777b538SAndroid Build Coastguard Worker #include "net/http/http_status_code.h"
55*6777b538SAndroid Build Coastguard Worker #include "net/http/http_util.h"
56*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_event_type.h"
57*6777b538SAndroid Build Coastguard Worker #include "net/ssl/ssl_cert_request_info.h"
58*6777b538SAndroid Build Coastguard Worker #include "net/ssl/ssl_config_service.h"
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker using base::Time;
61*6777b538SAndroid Build Coastguard Worker using base::TimeTicks;
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker namespace net {
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker using CacheEntryStatus = HttpResponseInfo::CacheEntryStatus;
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker namespace {
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker constexpr base::TimeDelta kStaleRevalidateTimeout = base::Seconds(60);
70*6777b538SAndroid Build Coastguard Worker
GetNextTraceId(HttpCache * cache)71*6777b538SAndroid Build Coastguard Worker uint64_t GetNextTraceId(HttpCache* cache) {
72*6777b538SAndroid Build Coastguard Worker static uint32_t sNextTraceId = 0;
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker DCHECK(cache);
75*6777b538SAndroid Build Coastguard Worker return (reinterpret_cast<uint64_t>(cache) << 32) | sNextTraceId++;
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker // From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
79*6777b538SAndroid Build Coastguard Worker // a "non-error response" is one with a 2xx (Successful) or 3xx
80*6777b538SAndroid Build Coastguard Worker // (Redirection) status code.
NonErrorResponse(int status_code)81*6777b538SAndroid Build Coastguard Worker bool NonErrorResponse(int status_code) {
82*6777b538SAndroid Build Coastguard Worker int status_code_range = status_code / 100;
83*6777b538SAndroid Build Coastguard Worker return status_code_range == 2 || status_code_range == 3;
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker
IsOnBatteryPower()86*6777b538SAndroid Build Coastguard Worker bool IsOnBatteryPower() {
87*6777b538SAndroid Build Coastguard Worker if (base::PowerMonitor::IsInitialized()) {
88*6777b538SAndroid Build Coastguard Worker return base::PowerMonitor::IsOnBatteryPower();
89*6777b538SAndroid Build Coastguard Worker }
90*6777b538SAndroid Build Coastguard Worker return false;
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker enum ExternallyConditionalizedType {
94*6777b538SAndroid Build Coastguard Worker EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION,
95*6777b538SAndroid Build Coastguard Worker EXTERNALLY_CONDITIONALIZED_CACHE_USABLE,
96*6777b538SAndroid Build Coastguard Worker EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS,
97*6777b538SAndroid Build Coastguard Worker EXTERNALLY_CONDITIONALIZED_MAX
98*6777b538SAndroid Build Coastguard Worker };
99*6777b538SAndroid Build Coastguard Worker
ShouldByPassCacheForFirstPartySets(const std::optional<int64_t> & clear_at_run_id,const std::optional<int64_t> & written_at_run_id)100*6777b538SAndroid Build Coastguard Worker bool ShouldByPassCacheForFirstPartySets(
101*6777b538SAndroid Build Coastguard Worker const std::optional<int64_t>& clear_at_run_id,
102*6777b538SAndroid Build Coastguard Worker const std::optional<int64_t>& written_at_run_id) {
103*6777b538SAndroid Build Coastguard Worker return clear_at_run_id.has_value() &&
104*6777b538SAndroid Build Coastguard Worker (!written_at_run_id.has_value() ||
105*6777b538SAndroid Build Coastguard Worker written_at_run_id.value() < clear_at_run_id.value());
106*6777b538SAndroid Build Coastguard Worker }
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker struct HeaderNameAndValue {
109*6777b538SAndroid Build Coastguard Worker const char* name;
110*6777b538SAndroid Build Coastguard Worker const char* value;
111*6777b538SAndroid Build Coastguard Worker };
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker // If the request includes one of these request headers, then avoid caching
114*6777b538SAndroid Build Coastguard Worker // to avoid getting confused.
115*6777b538SAndroid Build Coastguard Worker constexpr HeaderNameAndValue kPassThroughHeaders[] = {
116*6777b538SAndroid Build Coastguard Worker {"if-unmodified-since", nullptr}, // causes unexpected 412s
117*6777b538SAndroid Build Coastguard Worker {"if-match", nullptr}, // causes unexpected 412s
118*6777b538SAndroid Build Coastguard Worker {"if-range", nullptr},
119*6777b538SAndroid Build Coastguard Worker {nullptr, nullptr}};
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker struct ValidationHeaderInfo {
122*6777b538SAndroid Build Coastguard Worker const char* request_header_name;
123*6777b538SAndroid Build Coastguard Worker const char* related_response_header_name;
124*6777b538SAndroid Build Coastguard Worker };
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker constexpr ValidationHeaderInfo kValidationHeaders[] = {
127*6777b538SAndroid Build Coastguard Worker {"if-modified-since", "last-modified"},
128*6777b538SAndroid Build Coastguard Worker {"if-none-match", "etag"},
129*6777b538SAndroid Build Coastguard Worker };
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker // If the request includes one of these request headers, then avoid reusing
132*6777b538SAndroid Build Coastguard Worker // our cached copy if any.
133*6777b538SAndroid Build Coastguard Worker constexpr HeaderNameAndValue kForceFetchHeaders[] = {
134*6777b538SAndroid Build Coastguard Worker {"cache-control", "no-cache"},
135*6777b538SAndroid Build Coastguard Worker {"pragma", "no-cache"},
136*6777b538SAndroid Build Coastguard Worker {nullptr, nullptr}};
137*6777b538SAndroid Build Coastguard Worker
138*6777b538SAndroid Build Coastguard Worker // If the request includes one of these request headers, then force our
139*6777b538SAndroid Build Coastguard Worker // cached copy (if any) to be revalidated before reusing it.
140*6777b538SAndroid Build Coastguard Worker constexpr HeaderNameAndValue kForceValidateHeaders[] = {
141*6777b538SAndroid Build Coastguard Worker {"cache-control", "max-age=0"},
142*6777b538SAndroid Build Coastguard Worker {nullptr, nullptr}};
143*6777b538SAndroid Build Coastguard Worker
HeaderMatches(const HttpRequestHeaders & headers,const HeaderNameAndValue * search)144*6777b538SAndroid Build Coastguard Worker bool HeaderMatches(const HttpRequestHeaders& headers,
145*6777b538SAndroid Build Coastguard Worker const HeaderNameAndValue* search) {
146*6777b538SAndroid Build Coastguard Worker for (; search->name; ++search) {
147*6777b538SAndroid Build Coastguard Worker std::string header_value;
148*6777b538SAndroid Build Coastguard Worker if (!headers.GetHeader(search->name, &header_value)) {
149*6777b538SAndroid Build Coastguard Worker continue;
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard Worker if (!search->value) {
153*6777b538SAndroid Build Coastguard Worker return true;
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ',');
157*6777b538SAndroid Build Coastguard Worker while (v.GetNext()) {
158*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(v.value_piece(), search->value)) {
159*6777b538SAndroid Build Coastguard Worker return true;
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker }
162*6777b538SAndroid Build Coastguard Worker }
163*6777b538SAndroid Build Coastguard Worker return false;
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker } // namespace
167*6777b538SAndroid Build Coastguard Worker
168*6777b538SAndroid Build Coastguard Worker #define CACHE_STATUS_HISTOGRAMS(type) \
169*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_ENUMERATION("HttpCache.Pattern" type, cache_entry_status_, \
170*6777b538SAndroid Build Coastguard Worker CacheEntryStatus::ENTRY_MAX)
171*6777b538SAndroid Build Coastguard Worker
172*6777b538SAndroid Build Coastguard Worker #define IS_NO_STORE_HISTOGRAMS(type, is_no_store) \
173*6777b538SAndroid Build Coastguard Worker base::UmaHistogramBoolean("HttpCache.IsNoStore" type, is_no_store)
174*6777b538SAndroid Build Coastguard Worker
175*6777b538SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
176*6777b538SAndroid Build Coastguard Worker
Transaction(RequestPriority priority,HttpCache * cache)177*6777b538SAndroid Build Coastguard Worker HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache)
178*6777b538SAndroid Build Coastguard Worker : trace_id_(GetNextTraceId(cache)),
179*6777b538SAndroid Build Coastguard Worker priority_(priority),
180*6777b538SAndroid Build Coastguard Worker cache_(cache->GetWeakPtr()) {
181*6777b538SAndroid Build Coastguard Worker static_assert(HttpCache::Transaction::kNumValidationHeaders ==
182*6777b538SAndroid Build Coastguard Worker std::size(kValidationHeaders),
183*6777b538SAndroid Build Coastguard Worker "invalid number of validation headers");
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker io_callback_ = base::BindRepeating(&Transaction::OnIOComplete,
186*6777b538SAndroid Build Coastguard Worker weak_factory_.GetWeakPtr());
187*6777b538SAndroid Build Coastguard Worker cache_io_callback_ = base::BindRepeating(&Transaction::OnCacheIOComplete,
188*6777b538SAndroid Build Coastguard Worker weak_factory_.GetWeakPtr());
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker
~Transaction()191*6777b538SAndroid Build Coastguard Worker HttpCache::Transaction::~Transaction() {
192*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_END("net", perfetto::Track(trace_id_));
193*6777b538SAndroid Build Coastguard Worker RecordHistograms();
194*6777b538SAndroid Build Coastguard Worker
195*6777b538SAndroid Build Coastguard Worker // We may have to issue another IO, but we should never invoke the callback_
196*6777b538SAndroid Build Coastguard Worker // after this point.
197*6777b538SAndroid Build Coastguard Worker callback_.Reset();
198*6777b538SAndroid Build Coastguard Worker
199*6777b538SAndroid Build Coastguard Worker if (cache_) {
200*6777b538SAndroid Build Coastguard Worker if (entry_) {
201*6777b538SAndroid Build Coastguard Worker DoneWithEntry(false /* entry_is_complete */);
202*6777b538SAndroid Build Coastguard Worker } else if (cache_pending_) {
203*6777b538SAndroid Build Coastguard Worker cache_->RemovePendingTransaction(this);
204*6777b538SAndroid Build Coastguard Worker }
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker }
207*6777b538SAndroid Build Coastguard Worker
mode() const208*6777b538SAndroid Build Coastguard Worker HttpCache::Transaction::Mode HttpCache::Transaction::mode() const {
209*6777b538SAndroid Build Coastguard Worker return mode_;
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker
GetWriterLoadState() const212*6777b538SAndroid Build Coastguard Worker LoadState HttpCache::Transaction::GetWriterLoadState() const {
213*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = network_transaction();
214*6777b538SAndroid Build Coastguard Worker if (transaction) {
215*6777b538SAndroid Build Coastguard Worker return transaction->GetLoadState();
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker if (entry_ || !request_) {
218*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_IDLE;
219*6777b538SAndroid Build Coastguard Worker }
220*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_WAITING_FOR_CACHE;
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker
net_log() const223*6777b538SAndroid Build Coastguard Worker const NetLogWithSource& HttpCache::Transaction::net_log() const {
224*6777b538SAndroid Build Coastguard Worker return net_log_;
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker
Start(const HttpRequestInfo * request,CompletionOnceCallback callback,const NetLogWithSource & net_log)227*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::Start(const HttpRequestInfo* request,
228*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback,
229*6777b538SAndroid Build Coastguard Worker const NetLogWithSource& net_log) {
230*6777b538SAndroid Build Coastguard Worker DCHECK(request);
231*6777b538SAndroid Build Coastguard Worker DCHECK(request->IsConsistent());
232*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
233*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_BEGIN("net", "HttpCacheTransaction", perfetto::Track(trace_id_),
234*6777b538SAndroid Build Coastguard Worker "url", request->url.spec());
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker // Ensure that we only have one asynchronous call at a time.
237*6777b538SAndroid Build Coastguard Worker DCHECK(callback_.is_null());
238*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
239*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_.get());
240*6777b538SAndroid Build Coastguard Worker DCHECK(!entry_);
241*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(next_state_, STATE_NONE);
242*6777b538SAndroid Build Coastguard Worker
243*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
244*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
245*6777b538SAndroid Build Coastguard Worker }
246*6777b538SAndroid Build Coastguard Worker
247*6777b538SAndroid Build Coastguard Worker initial_request_ = request;
248*6777b538SAndroid Build Coastguard Worker SetRequest(net_log);
249*6777b538SAndroid Build Coastguard Worker
250*6777b538SAndroid Build Coastguard Worker // We have to wait until the backend is initialized so we start the SM.
251*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_GET_BACKEND;
252*6777b538SAndroid Build Coastguard Worker int rv = DoLoop(OK);
253*6777b538SAndroid Build Coastguard Worker
254*6777b538SAndroid Build Coastguard Worker // Setting this here allows us to check for the existence of a callback_ to
255*6777b538SAndroid Build Coastguard Worker // determine if we are still inside Start.
256*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
257*6777b538SAndroid Build Coastguard Worker callback_ = std::move(callback);
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker
260*6777b538SAndroid Build Coastguard Worker return rv;
261*6777b538SAndroid Build Coastguard Worker }
262*6777b538SAndroid Build Coastguard Worker
RestartIgnoringLastError(CompletionOnceCallback callback)263*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::RestartIgnoringLastError(
264*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
265*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
266*6777b538SAndroid Build Coastguard Worker
267*6777b538SAndroid Build Coastguard Worker // Ensure that we only have one asynchronous call at a time.
268*6777b538SAndroid Build Coastguard Worker DCHECK(callback_.is_null());
269*6777b538SAndroid Build Coastguard Worker
270*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
271*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
272*6777b538SAndroid Build Coastguard Worker }
273*6777b538SAndroid Build Coastguard Worker
274*6777b538SAndroid Build Coastguard Worker int rv = RestartNetworkRequest();
275*6777b538SAndroid Build Coastguard Worker
276*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
277*6777b538SAndroid Build Coastguard Worker callback_ = std::move(callback);
278*6777b538SAndroid Build Coastguard Worker }
279*6777b538SAndroid Build Coastguard Worker
280*6777b538SAndroid Build Coastguard Worker return rv;
281*6777b538SAndroid Build Coastguard Worker }
282*6777b538SAndroid Build Coastguard Worker
RestartWithCertificate(scoped_refptr<X509Certificate> client_cert,scoped_refptr<SSLPrivateKey> client_private_key,CompletionOnceCallback callback)283*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::RestartWithCertificate(
284*6777b538SAndroid Build Coastguard Worker scoped_refptr<X509Certificate> client_cert,
285*6777b538SAndroid Build Coastguard Worker scoped_refptr<SSLPrivateKey> client_private_key,
286*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
287*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
288*6777b538SAndroid Build Coastguard Worker
289*6777b538SAndroid Build Coastguard Worker // Ensure that we only have one asynchronous call at a time.
290*6777b538SAndroid Build Coastguard Worker DCHECK(callback_.is_null());
291*6777b538SAndroid Build Coastguard Worker
292*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
293*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
294*6777b538SAndroid Build Coastguard Worker }
295*6777b538SAndroid Build Coastguard Worker
296*6777b538SAndroid Build Coastguard Worker int rv = RestartNetworkRequestWithCertificate(std::move(client_cert),
297*6777b538SAndroid Build Coastguard Worker std::move(client_private_key));
298*6777b538SAndroid Build Coastguard Worker
299*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
300*6777b538SAndroid Build Coastguard Worker callback_ = std::move(callback);
301*6777b538SAndroid Build Coastguard Worker }
302*6777b538SAndroid Build Coastguard Worker
303*6777b538SAndroid Build Coastguard Worker return rv;
304*6777b538SAndroid Build Coastguard Worker }
305*6777b538SAndroid Build Coastguard Worker
RestartWithAuth(const AuthCredentials & credentials,CompletionOnceCallback callback)306*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::RestartWithAuth(const AuthCredentials& credentials,
307*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
308*6777b538SAndroid Build Coastguard Worker DCHECK(auth_response_.headers.get());
309*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
310*6777b538SAndroid Build Coastguard Worker
311*6777b538SAndroid Build Coastguard Worker // Ensure that we only have one asynchronous call at a time.
312*6777b538SAndroid Build Coastguard Worker DCHECK(callback_.is_null());
313*6777b538SAndroid Build Coastguard Worker
314*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
315*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker
318*6777b538SAndroid Build Coastguard Worker // Clear the intermediate response since we are going to start over.
319*6777b538SAndroid Build Coastguard Worker SetAuthResponse(HttpResponseInfo());
320*6777b538SAndroid Build Coastguard Worker
321*6777b538SAndroid Build Coastguard Worker int rv = RestartNetworkRequestWithAuth(credentials);
322*6777b538SAndroid Build Coastguard Worker
323*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
324*6777b538SAndroid Build Coastguard Worker callback_ = std::move(callback);
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker return rv;
328*6777b538SAndroid Build Coastguard Worker }
329*6777b538SAndroid Build Coastguard Worker
IsReadyToRestartForAuth()330*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::IsReadyToRestartForAuth() {
331*6777b538SAndroid Build Coastguard Worker if (!network_trans_.get()) {
332*6777b538SAndroid Build Coastguard Worker return false;
333*6777b538SAndroid Build Coastguard Worker }
334*6777b538SAndroid Build Coastguard Worker return network_trans_->IsReadyToRestartForAuth();
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)337*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::Read(IOBuffer* buf,
338*6777b538SAndroid Build Coastguard Worker int buf_len,
339*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
340*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::Read",
341*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "buf_len", buf_len);
342*6777b538SAndroid Build Coastguard Worker
343*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(next_state_, STATE_NONE);
344*6777b538SAndroid Build Coastguard Worker DCHECK(buf);
345*6777b538SAndroid Build Coastguard Worker DCHECK_GT(buf_len, 0);
346*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker DCHECK(callback_.is_null());
349*6777b538SAndroid Build Coastguard Worker
350*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
351*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
352*6777b538SAndroid Build Coastguard Worker }
353*6777b538SAndroid Build Coastguard Worker
354*6777b538SAndroid Build Coastguard Worker // If we have an intermediate auth response at this point, then it means the
355*6777b538SAndroid Build Coastguard Worker // user wishes to read the network response (the error page). If there is a
356*6777b538SAndroid Build Coastguard Worker // previous response in the cache then we should leave it intact.
357*6777b538SAndroid Build Coastguard Worker if (auth_response_.headers.get() && mode_ != NONE) {
358*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
359*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ & WRITE);
360*6777b538SAndroid Build Coastguard Worker bool stopped = StopCachingImpl(mode_ == READ_WRITE);
361*6777b538SAndroid Build Coastguard Worker DCHECK(stopped);
362*6777b538SAndroid Build Coastguard Worker }
363*6777b538SAndroid Build Coastguard Worker
364*6777b538SAndroid Build Coastguard Worker reading_ = true;
365*6777b538SAndroid Build Coastguard Worker read_buf_ = buf;
366*6777b538SAndroid Build Coastguard Worker read_buf_len_ = buf_len;
367*6777b538SAndroid Build Coastguard Worker int rv = TransitionToReadingState();
368*6777b538SAndroid Build Coastguard Worker if (rv != OK || next_state_ == STATE_NONE) {
369*6777b538SAndroid Build Coastguard Worker return rv;
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker
372*6777b538SAndroid Build Coastguard Worker rv = DoLoop(OK);
373*6777b538SAndroid Build Coastguard Worker
374*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
375*6777b538SAndroid Build Coastguard Worker DCHECK(callback_.is_null());
376*6777b538SAndroid Build Coastguard Worker callback_ = std::move(callback);
377*6777b538SAndroid Build Coastguard Worker }
378*6777b538SAndroid Build Coastguard Worker return rv;
379*6777b538SAndroid Build Coastguard Worker }
380*6777b538SAndroid Build Coastguard Worker
TransitionToReadingState()381*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::TransitionToReadingState() {
382*6777b538SAndroid Build Coastguard Worker if (!entry_) {
383*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
384*6777b538SAndroid Build Coastguard Worker // This can happen when the request should be handled exclusively by
385*6777b538SAndroid Build Coastguard Worker // the network layer (skipping the cache entirely using
386*6777b538SAndroid Build Coastguard Worker // LOAD_DISABLE_CACHE) or there was an error during the headers phase
387*6777b538SAndroid Build Coastguard Worker // due to which the transaction cannot write to the cache or the consumer
388*6777b538SAndroid Build Coastguard Worker // is reading the auth response from the network.
389*6777b538SAndroid Build Coastguard Worker // TODO(http://crbug.com/740947) to get rid of this state in future.
390*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NETWORK_READ;
391*6777b538SAndroid Build Coastguard Worker
392*6777b538SAndroid Build Coastguard Worker return OK;
393*6777b538SAndroid Build Coastguard Worker }
394*6777b538SAndroid Build Coastguard Worker
395*6777b538SAndroid Build Coastguard Worker // If there is no network, and no cache entry, then there is nothing to read
396*6777b538SAndroid Build Coastguard Worker // from.
397*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NONE;
398*6777b538SAndroid Build Coastguard Worker
399*6777b538SAndroid Build Coastguard Worker // An error state should be set for the next read, else this transaction
400*6777b538SAndroid Build Coastguard Worker // should have been terminated once it reached this state. To assert we
401*6777b538SAndroid Build Coastguard Worker // could dcheck that shared_writing_error_ is set to a valid error value but
402*6777b538SAndroid Build Coastguard Worker // in some specific conditions (http://crbug.com/806344) it's possible that
403*6777b538SAndroid Build Coastguard Worker // the consumer does an extra Read in which case the assert will fail.
404*6777b538SAndroid Build Coastguard Worker return shared_writing_error_;
405*6777b538SAndroid Build Coastguard Worker }
406*6777b538SAndroid Build Coastguard Worker
407*6777b538SAndroid Build Coastguard Worker // If entry_ is present, the transaction is either a member of entry_->writers
408*6777b538SAndroid Build Coastguard Worker // or readers.
409*6777b538SAndroid Build Coastguard Worker if (!InWriters()) {
410*6777b538SAndroid Build Coastguard Worker // Since transaction is not a writer and we are in Read(), it must be a
411*6777b538SAndroid Build Coastguard Worker // reader.
412*6777b538SAndroid Build Coastguard Worker DCHECK(entry_->TransactionInReaders(this));
413*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
414*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_CACHE_READ_DATA;
415*6777b538SAndroid Build Coastguard Worker return OK;
416*6777b538SAndroid Build Coastguard Worker }
417*6777b538SAndroid Build Coastguard Worker
418*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ & WRITE || mode_ == NONE);
419*6777b538SAndroid Build Coastguard Worker
420*6777b538SAndroid Build Coastguard Worker // If it's a writer and it is partial then it may need to read from the cache
421*6777b538SAndroid Build Coastguard Worker // or from the network based on whether network transaction is present or not.
422*6777b538SAndroid Build Coastguard Worker if (partial_) {
423*6777b538SAndroid Build Coastguard Worker if (entry_->writers()->network_transaction()) {
424*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NETWORK_READ_CACHE_WRITE;
425*6777b538SAndroid Build Coastguard Worker } else {
426*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_CACHE_READ_DATA;
427*6777b538SAndroid Build Coastguard Worker }
428*6777b538SAndroid Build Coastguard Worker return OK;
429*6777b538SAndroid Build Coastguard Worker }
430*6777b538SAndroid Build Coastguard Worker
431*6777b538SAndroid Build Coastguard Worker // Full request.
432*6777b538SAndroid Build Coastguard Worker // If it's a writer and a full request then it may read from the cache if its
433*6777b538SAndroid Build Coastguard Worker // offset is behind the current offset else from the network.
434*6777b538SAndroid Build Coastguard Worker int disk_entry_size = entry_->GetEntry()->GetDataSize(kResponseContentIndex);
435*6777b538SAndroid Build Coastguard Worker if (read_offset_ == disk_entry_size ||
436*6777b538SAndroid Build Coastguard Worker entry_->writers()->network_read_only()) {
437*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_NETWORK_READ_CACHE_WRITE;
438*6777b538SAndroid Build Coastguard Worker } else {
439*6777b538SAndroid Build Coastguard Worker DCHECK_LT(read_offset_, disk_entry_size);
440*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_CACHE_READ_DATA;
441*6777b538SAndroid Build Coastguard Worker }
442*6777b538SAndroid Build Coastguard Worker return OK;
443*6777b538SAndroid Build Coastguard Worker }
444*6777b538SAndroid Build Coastguard Worker
StopCaching()445*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::StopCaching() {
446*6777b538SAndroid Build Coastguard Worker // We really don't know where we are now. Hopefully there is no operation in
447*6777b538SAndroid Build Coastguard Worker // progress, but nothing really prevents this method to be called after we
448*6777b538SAndroid Build Coastguard Worker // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this
449*6777b538SAndroid Build Coastguard Worker // point because we need the state machine for that (and even if we are really
450*6777b538SAndroid Build Coastguard Worker // free, that would be an asynchronous operation). In other words, keep the
451*6777b538SAndroid Build Coastguard Worker // entry how it is (it will be marked as truncated at destruction), and let
452*6777b538SAndroid Build Coastguard Worker // the next piece of code that executes know that we are now reading directly
453*6777b538SAndroid Build Coastguard Worker // from the net.
454*6777b538SAndroid Build Coastguard Worker if (cache_.get() && (mode_ & WRITE) && !is_sparse_ && !range_requested_ &&
455*6777b538SAndroid Build Coastguard Worker network_transaction()) {
456*6777b538SAndroid Build Coastguard Worker StopCachingImpl(false);
457*6777b538SAndroid Build Coastguard Worker }
458*6777b538SAndroid Build Coastguard Worker }
459*6777b538SAndroid Build Coastguard Worker
GetTotalReceivedBytes() const460*6777b538SAndroid Build Coastguard Worker int64_t HttpCache::Transaction::GetTotalReceivedBytes() const {
461*6777b538SAndroid Build Coastguard Worker int64_t total_received_bytes = network_transaction_info_.total_received_bytes;
462*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
463*6777b538SAndroid Build Coastguard Worker if (transaction) {
464*6777b538SAndroid Build Coastguard Worker total_received_bytes += transaction->GetTotalReceivedBytes();
465*6777b538SAndroid Build Coastguard Worker }
466*6777b538SAndroid Build Coastguard Worker return total_received_bytes;
467*6777b538SAndroid Build Coastguard Worker }
468*6777b538SAndroid Build Coastguard Worker
GetTotalSentBytes() const469*6777b538SAndroid Build Coastguard Worker int64_t HttpCache::Transaction::GetTotalSentBytes() const {
470*6777b538SAndroid Build Coastguard Worker int64_t total_sent_bytes = network_transaction_info_.total_sent_bytes;
471*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
472*6777b538SAndroid Build Coastguard Worker if (transaction) {
473*6777b538SAndroid Build Coastguard Worker total_sent_bytes += transaction->GetTotalSentBytes();
474*6777b538SAndroid Build Coastguard Worker }
475*6777b538SAndroid Build Coastguard Worker return total_sent_bytes;
476*6777b538SAndroid Build Coastguard Worker }
477*6777b538SAndroid Build Coastguard Worker
DoneReading()478*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::DoneReading() {
479*6777b538SAndroid Build Coastguard Worker if (cache_.get() && entry_) {
480*6777b538SAndroid Build Coastguard Worker DCHECK_NE(mode_, UPDATE);
481*6777b538SAndroid Build Coastguard Worker DoneWithEntry(true);
482*6777b538SAndroid Build Coastguard Worker }
483*6777b538SAndroid Build Coastguard Worker }
484*6777b538SAndroid Build Coastguard Worker
GetResponseInfo() const485*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
486*6777b538SAndroid Build Coastguard Worker // Null headers means we encountered an error or haven't a response yet
487*6777b538SAndroid Build Coastguard Worker if (auth_response_.headers.get()) {
488*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(cache_entry_status_, auth_response_.cache_entry_status)
489*6777b538SAndroid Build Coastguard Worker << "These must be in sync via SetResponse and SetAuthResponse.";
490*6777b538SAndroid Build Coastguard Worker return &auth_response_;
491*6777b538SAndroid Build Coastguard Worker }
492*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/1219402): This should check in `response_`
493*6777b538SAndroid Build Coastguard Worker return &response_;
494*6777b538SAndroid Build Coastguard Worker }
495*6777b538SAndroid Build Coastguard Worker
GetLoadState() const496*6777b538SAndroid Build Coastguard Worker LoadState HttpCache::Transaction::GetLoadState() const {
497*6777b538SAndroid Build Coastguard Worker // If there's no pending callback, the ball is not in the
498*6777b538SAndroid Build Coastguard Worker // HttpCache::Transaction's court, whatever else may be going on.
499*6777b538SAndroid Build Coastguard Worker if (!callback_) {
500*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_IDLE;
501*6777b538SAndroid Build Coastguard Worker }
502*6777b538SAndroid Build Coastguard Worker
503*6777b538SAndroid Build Coastguard Worker LoadState state = GetWriterLoadState();
504*6777b538SAndroid Build Coastguard Worker if (state != LOAD_STATE_WAITING_FOR_CACHE) {
505*6777b538SAndroid Build Coastguard Worker return state;
506*6777b538SAndroid Build Coastguard Worker }
507*6777b538SAndroid Build Coastguard Worker
508*6777b538SAndroid Build Coastguard Worker if (cache_.get()) {
509*6777b538SAndroid Build Coastguard Worker return cache_->GetLoadStateForPendingTransaction(this);
510*6777b538SAndroid Build Coastguard Worker }
511*6777b538SAndroid Build Coastguard Worker
512*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_IDLE;
513*6777b538SAndroid Build Coastguard Worker }
514*6777b538SAndroid Build Coastguard Worker
SetQuicServerInfo(QuicServerInfo * quic_server_info)515*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetQuicServerInfo(
516*6777b538SAndroid Build Coastguard Worker QuicServerInfo* quic_server_info) {}
517*6777b538SAndroid Build Coastguard Worker
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const518*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::GetLoadTimingInfo(
519*6777b538SAndroid Build Coastguard Worker LoadTimingInfo* load_timing_info) const {
520*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
521*6777b538SAndroid Build Coastguard Worker if (transaction) {
522*6777b538SAndroid Build Coastguard Worker return transaction->GetLoadTimingInfo(load_timing_info);
523*6777b538SAndroid Build Coastguard Worker }
524*6777b538SAndroid Build Coastguard Worker
525*6777b538SAndroid Build Coastguard Worker if (network_transaction_info_.old_network_trans_load_timing) {
526*6777b538SAndroid Build Coastguard Worker *load_timing_info =
527*6777b538SAndroid Build Coastguard Worker *network_transaction_info_.old_network_trans_load_timing;
528*6777b538SAndroid Build Coastguard Worker return true;
529*6777b538SAndroid Build Coastguard Worker }
530*6777b538SAndroid Build Coastguard Worker
531*6777b538SAndroid Build Coastguard Worker if (first_cache_access_since_.is_null()) {
532*6777b538SAndroid Build Coastguard Worker return false;
533*6777b538SAndroid Build Coastguard Worker }
534*6777b538SAndroid Build Coastguard Worker
535*6777b538SAndroid Build Coastguard Worker // If the cache entry was opened, return that time.
536*6777b538SAndroid Build Coastguard Worker load_timing_info->send_start = first_cache_access_since_;
537*6777b538SAndroid Build Coastguard Worker // This time doesn't make much sense when reading from the cache, so just use
538*6777b538SAndroid Build Coastguard Worker // the same time as send_start.
539*6777b538SAndroid Build Coastguard Worker load_timing_info->send_end = first_cache_access_since_;
540*6777b538SAndroid Build Coastguard Worker // Provide the time immediately before parsing a cached entry.
541*6777b538SAndroid Build Coastguard Worker load_timing_info->receive_headers_start = read_headers_since_;
542*6777b538SAndroid Build Coastguard Worker return true;
543*6777b538SAndroid Build Coastguard Worker }
544*6777b538SAndroid Build Coastguard Worker
GetRemoteEndpoint(IPEndPoint * endpoint) const545*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
546*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
547*6777b538SAndroid Build Coastguard Worker if (transaction) {
548*6777b538SAndroid Build Coastguard Worker return transaction->GetRemoteEndpoint(endpoint);
549*6777b538SAndroid Build Coastguard Worker }
550*6777b538SAndroid Build Coastguard Worker
551*6777b538SAndroid Build Coastguard Worker if (!network_transaction_info_.old_remote_endpoint.address().empty()) {
552*6777b538SAndroid Build Coastguard Worker *endpoint = network_transaction_info_.old_remote_endpoint;
553*6777b538SAndroid Build Coastguard Worker return true;
554*6777b538SAndroid Build Coastguard Worker }
555*6777b538SAndroid Build Coastguard Worker
556*6777b538SAndroid Build Coastguard Worker return false;
557*6777b538SAndroid Build Coastguard Worker }
558*6777b538SAndroid Build Coastguard Worker
PopulateNetErrorDetails(NetErrorDetails * details) const559*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::PopulateNetErrorDetails(
560*6777b538SAndroid Build Coastguard Worker NetErrorDetails* details) const {
561*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
562*6777b538SAndroid Build Coastguard Worker if (transaction) {
563*6777b538SAndroid Build Coastguard Worker return transaction->PopulateNetErrorDetails(details);
564*6777b538SAndroid Build Coastguard Worker }
565*6777b538SAndroid Build Coastguard Worker return;
566*6777b538SAndroid Build Coastguard Worker }
567*6777b538SAndroid Build Coastguard Worker
SetPriority(RequestPriority priority)568*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetPriority(RequestPriority priority) {
569*6777b538SAndroid Build Coastguard Worker priority_ = priority;
570*6777b538SAndroid Build Coastguard Worker
571*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
572*6777b538SAndroid Build Coastguard Worker network_trans_->SetPriority(priority_);
573*6777b538SAndroid Build Coastguard Worker }
574*6777b538SAndroid Build Coastguard Worker
575*6777b538SAndroid Build Coastguard Worker if (InWriters()) {
576*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_ || partial_);
577*6777b538SAndroid Build Coastguard Worker entry_->writers()->UpdatePriority();
578*6777b538SAndroid Build Coastguard Worker }
579*6777b538SAndroid Build Coastguard Worker }
580*6777b538SAndroid Build Coastguard Worker
SetWebSocketHandshakeStreamCreateHelper(WebSocketHandshakeStreamBase::CreateHelper * create_helper)581*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
582*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
583*6777b538SAndroid Build Coastguard Worker websocket_handshake_stream_base_create_helper_ = create_helper;
584*6777b538SAndroid Build Coastguard Worker
585*6777b538SAndroid Build Coastguard Worker // TODO(shivanisha). Since this function must be invoked before Start() as
586*6777b538SAndroid Build Coastguard Worker // per the API header, a network transaction should not exist at that point.
587*6777b538SAndroid Build Coastguard Worker HttpTransaction* transaction = network_transaction();
588*6777b538SAndroid Build Coastguard Worker if (transaction) {
589*6777b538SAndroid Build Coastguard Worker transaction->SetWebSocketHandshakeStreamCreateHelper(create_helper);
590*6777b538SAndroid Build Coastguard Worker }
591*6777b538SAndroid Build Coastguard Worker }
592*6777b538SAndroid Build Coastguard Worker
SetBeforeNetworkStartCallback(BeforeNetworkStartCallback callback)593*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetBeforeNetworkStartCallback(
594*6777b538SAndroid Build Coastguard Worker BeforeNetworkStartCallback callback) {
595*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_);
596*6777b538SAndroid Build Coastguard Worker before_network_start_callback_ = std::move(callback);
597*6777b538SAndroid Build Coastguard Worker }
598*6777b538SAndroid Build Coastguard Worker
SetConnectedCallback(const ConnectedCallback & callback)599*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetConnectedCallback(
600*6777b538SAndroid Build Coastguard Worker const ConnectedCallback& callback) {
601*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_);
602*6777b538SAndroid Build Coastguard Worker connected_callback_ = callback;
603*6777b538SAndroid Build Coastguard Worker }
604*6777b538SAndroid Build Coastguard Worker
SetRequestHeadersCallback(RequestHeadersCallback callback)605*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetRequestHeadersCallback(
606*6777b538SAndroid Build Coastguard Worker RequestHeadersCallback callback) {
607*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_);
608*6777b538SAndroid Build Coastguard Worker request_headers_callback_ = std::move(callback);
609*6777b538SAndroid Build Coastguard Worker }
610*6777b538SAndroid Build Coastguard Worker
SetResponseHeadersCallback(ResponseHeadersCallback callback)611*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetResponseHeadersCallback(
612*6777b538SAndroid Build Coastguard Worker ResponseHeadersCallback callback) {
613*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_);
614*6777b538SAndroid Build Coastguard Worker response_headers_callback_ = std::move(callback);
615*6777b538SAndroid Build Coastguard Worker }
616*6777b538SAndroid Build Coastguard Worker
SetEarlyResponseHeadersCallback(ResponseHeadersCallback callback)617*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetEarlyResponseHeadersCallback(
618*6777b538SAndroid Build Coastguard Worker ResponseHeadersCallback callback) {
619*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_);
620*6777b538SAndroid Build Coastguard Worker early_response_headers_callback_ = std::move(callback);
621*6777b538SAndroid Build Coastguard Worker }
622*6777b538SAndroid Build Coastguard Worker
SetModifyRequestHeadersCallback(base::RepeatingCallback<void (net::HttpRequestHeaders *)> callback)623*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetModifyRequestHeadersCallback(
624*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void(net::HttpRequestHeaders*)> callback) {
625*6777b538SAndroid Build Coastguard Worker // This method should not be called for this class.
626*6777b538SAndroid Build Coastguard Worker NOTREACHED();
627*6777b538SAndroid Build Coastguard Worker }
628*6777b538SAndroid Build Coastguard Worker
SetIsSharedDictionaryReadAllowedCallback(base::RepeatingCallback<bool ()> callback)629*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetIsSharedDictionaryReadAllowedCallback(
630*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<bool()> callback) {
631*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_);
632*6777b538SAndroid Build Coastguard Worker is_shared_dictionary_read_allowed_callback_ = std::move(callback);
633*6777b538SAndroid Build Coastguard Worker }
634*6777b538SAndroid Build Coastguard Worker
ResumeNetworkStart()635*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::ResumeNetworkStart() {
636*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
637*6777b538SAndroid Build Coastguard Worker return network_trans_->ResumeNetworkStart();
638*6777b538SAndroid Build Coastguard Worker }
639*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
640*6777b538SAndroid Build Coastguard Worker }
641*6777b538SAndroid Build Coastguard Worker
GetConnectionAttempts() const642*6777b538SAndroid Build Coastguard Worker ConnectionAttempts HttpCache::Transaction::GetConnectionAttempts() const {
643*6777b538SAndroid Build Coastguard Worker ConnectionAttempts attempts;
644*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
645*6777b538SAndroid Build Coastguard Worker if (transaction) {
646*6777b538SAndroid Build Coastguard Worker attempts = transaction->GetConnectionAttempts();
647*6777b538SAndroid Build Coastguard Worker }
648*6777b538SAndroid Build Coastguard Worker
649*6777b538SAndroid Build Coastguard Worker attempts.insert(attempts.begin(),
650*6777b538SAndroid Build Coastguard Worker network_transaction_info_.old_connection_attempts.begin(),
651*6777b538SAndroid Build Coastguard Worker network_transaction_info_.old_connection_attempts.end());
652*6777b538SAndroid Build Coastguard Worker return attempts;
653*6777b538SAndroid Build Coastguard Worker }
654*6777b538SAndroid Build Coastguard Worker
CloseConnectionOnDestruction()655*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::CloseConnectionOnDestruction() {
656*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
657*6777b538SAndroid Build Coastguard Worker network_trans_->CloseConnectionOnDestruction();
658*6777b538SAndroid Build Coastguard Worker } else if (InWriters()) {
659*6777b538SAndroid Build Coastguard Worker entry_->writers()->CloseConnectionOnDestruction();
660*6777b538SAndroid Build Coastguard Worker }
661*6777b538SAndroid Build Coastguard Worker }
662*6777b538SAndroid Build Coastguard Worker
IsMdlMatchForMetrics() const663*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::IsMdlMatchForMetrics() const {
664*6777b538SAndroid Build Coastguard Worker if (network_transaction_info_.previous_mdl_match_for_metrics) {
665*6777b538SAndroid Build Coastguard Worker return true;
666*6777b538SAndroid Build Coastguard Worker }
667*6777b538SAndroid Build Coastguard Worker const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
668*6777b538SAndroid Build Coastguard Worker if (transaction) {
669*6777b538SAndroid Build Coastguard Worker return transaction->IsMdlMatchForMetrics();
670*6777b538SAndroid Build Coastguard Worker } else {
671*6777b538SAndroid Build Coastguard Worker return false;
672*6777b538SAndroid Build Coastguard Worker }
673*6777b538SAndroid Build Coastguard Worker }
674*6777b538SAndroid Build Coastguard Worker
SetValidatingCannotProceed()675*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetValidatingCannotProceed() {
676*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
677*6777b538SAndroid Build Coastguard Worker // Ensure this transaction is waiting for a callback.
678*6777b538SAndroid Build Coastguard Worker DCHECK_NE(STATE_UNSET, next_state_);
679*6777b538SAndroid Build Coastguard Worker
680*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_HEADERS_PHASE_CANNOT_PROCEED;
681*6777b538SAndroid Build Coastguard Worker entry_.reset();
682*6777b538SAndroid Build Coastguard Worker }
683*6777b538SAndroid Build Coastguard Worker
WriterAboutToBeRemovedFromEntry(int result)684*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::WriterAboutToBeRemovedFromEntry(int result) {
685*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net",
686*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::WriterAboutToBeRemovedFromEntry",
687*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
688*6777b538SAndroid Build Coastguard Worker // Since the transaction can no longer access the network transaction, save
689*6777b538SAndroid Build Coastguard Worker // all network related info now.
690*6777b538SAndroid Build Coastguard Worker if (moved_network_transaction_to_writers_ &&
691*6777b538SAndroid Build Coastguard Worker entry_->writers()->network_transaction()) {
692*6777b538SAndroid Build Coastguard Worker SaveNetworkTransactionInfo(*(entry_->writers()->network_transaction()));
693*6777b538SAndroid Build Coastguard Worker }
694*6777b538SAndroid Build Coastguard Worker
695*6777b538SAndroid Build Coastguard Worker entry_.reset();
696*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
697*6777b538SAndroid Build Coastguard Worker
698*6777b538SAndroid Build Coastguard Worker // Transactions in the midst of a Read call through writers will get any error
699*6777b538SAndroid Build Coastguard Worker // code through the IO callback but for idle transactions/transactions reading
700*6777b538SAndroid Build Coastguard Worker // from the cache, the error for a future Read must be stored here.
701*6777b538SAndroid Build Coastguard Worker if (result < 0) {
702*6777b538SAndroid Build Coastguard Worker shared_writing_error_ = result;
703*6777b538SAndroid Build Coastguard Worker }
704*6777b538SAndroid Build Coastguard Worker }
705*6777b538SAndroid Build Coastguard Worker
WriteModeTransactionAboutToBecomeReader()706*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::WriteModeTransactionAboutToBecomeReader() {
707*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
708*6777b538SAndroid Build Coastguard Worker "net", "HttpCacheTransaction::WriteModeTransactionAboutToBecomeReader",
709*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
710*6777b538SAndroid Build Coastguard Worker mode_ = READ;
711*6777b538SAndroid Build Coastguard Worker if (moved_network_transaction_to_writers_ &&
712*6777b538SAndroid Build Coastguard Worker entry_->writers()->network_transaction()) {
713*6777b538SAndroid Build Coastguard Worker SaveNetworkTransactionInfo(*(entry_->writers()->network_transaction()));
714*6777b538SAndroid Build Coastguard Worker }
715*6777b538SAndroid Build Coastguard Worker }
716*6777b538SAndroid Build Coastguard Worker
AddDiskCacheWriteTime(base::TimeDelta elapsed)717*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::AddDiskCacheWriteTime(base::TimeDelta elapsed) {
718*6777b538SAndroid Build Coastguard Worker total_disk_cache_write_time_ += elapsed;
719*6777b538SAndroid Build Coastguard Worker }
720*6777b538SAndroid Build Coastguard Worker
721*6777b538SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
722*6777b538SAndroid Build Coastguard Worker
723*6777b538SAndroid Build Coastguard Worker // A few common patterns: (Foo* means Foo -> FooComplete)
724*6777b538SAndroid Build Coastguard Worker //
725*6777b538SAndroid Build Coastguard Worker // 1. Not-cached entry:
726*6777b538SAndroid Build Coastguard Worker // Start():
727*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
728*6777b538SAndroid Build Coastguard Worker // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
729*6777b538SAndroid Build Coastguard Worker // CacheWriteResponse* -> TruncateCachedData* -> PartialHeadersReceived ->
730*6777b538SAndroid Build Coastguard Worker // FinishHeaders*
731*6777b538SAndroid Build Coastguard Worker //
732*6777b538SAndroid Build Coastguard Worker // Read():
733*6777b538SAndroid Build Coastguard Worker // NetworkReadCacheWrite*/CacheReadData* (if other writers are also writing to
734*6777b538SAndroid Build Coastguard Worker // the cache)
735*6777b538SAndroid Build Coastguard Worker //
736*6777b538SAndroid Build Coastguard Worker // 2. Cached entry, no validation:
737*6777b538SAndroid Build Coastguard Worker // Start():
738*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
739*6777b538SAndroid Build Coastguard Worker // CacheReadResponse* -> CacheDispatchValidation ->
740*6777b538SAndroid Build Coastguard Worker // BeginPartialCacheValidation() -> BeginCacheValidation() ->
741*6777b538SAndroid Build Coastguard Worker // ConnectedCallback* -> SetupEntryForRead() -> FinishHeaders*
742*6777b538SAndroid Build Coastguard Worker //
743*6777b538SAndroid Build Coastguard Worker // Read():
744*6777b538SAndroid Build Coastguard Worker // CacheReadData*
745*6777b538SAndroid Build Coastguard Worker //
746*6777b538SAndroid Build Coastguard Worker // 3. Cached entry, validation (304):
747*6777b538SAndroid Build Coastguard Worker // Start():
748*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
749*6777b538SAndroid Build Coastguard Worker // CacheReadResponse* -> CacheDispatchValidation ->
750*6777b538SAndroid Build Coastguard Worker // BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
751*6777b538SAndroid Build Coastguard Worker // SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteUpdatedResponse*
752*6777b538SAndroid Build Coastguard Worker // -> UpdateCachedResponseComplete -> OverwriteCachedResponse ->
753*6777b538SAndroid Build Coastguard Worker // PartialHeadersReceived -> FinishHeaders*
754*6777b538SAndroid Build Coastguard Worker //
755*6777b538SAndroid Build Coastguard Worker // Read():
756*6777b538SAndroid Build Coastguard Worker // CacheReadData*
757*6777b538SAndroid Build Coastguard Worker //
758*6777b538SAndroid Build Coastguard Worker // 4. Cached entry, validation and replace (200):
759*6777b538SAndroid Build Coastguard Worker // Start():
760*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
761*6777b538SAndroid Build Coastguard Worker // CacheReadResponse* -> CacheDispatchValidation ->
762*6777b538SAndroid Build Coastguard Worker // BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
763*6777b538SAndroid Build Coastguard Worker // SuccessfulSendRequest -> OverwriteCachedResponse -> CacheWriteResponse* ->
764*6777b538SAndroid Build Coastguard Worker // DoTruncateCachedData* -> PartialHeadersReceived -> FinishHeaders*
765*6777b538SAndroid Build Coastguard Worker //
766*6777b538SAndroid Build Coastguard Worker // Read():
767*6777b538SAndroid Build Coastguard Worker // NetworkReadCacheWrite*/CacheReadData* (if other writers are also writing to
768*6777b538SAndroid Build Coastguard Worker // the cache)
769*6777b538SAndroid Build Coastguard Worker //
770*6777b538SAndroid Build Coastguard Worker // 5. Sparse entry, partially cached, byte range request:
771*6777b538SAndroid Build Coastguard Worker // Start():
772*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
773*6777b538SAndroid Build Coastguard Worker // CacheReadResponse* -> CacheDispatchValidation ->
774*6777b538SAndroid Build Coastguard Worker // BeginPartialCacheValidation() -> CacheQueryData* ->
775*6777b538SAndroid Build Coastguard Worker // ValidateEntryHeadersAndContinue() -> StartPartialCacheValidation ->
776*6777b538SAndroid Build Coastguard Worker // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
777*6777b538SAndroid Build Coastguard Worker // SuccessfulSendRequest -> UpdateCachedResponse -> CacheWriteUpdatedResponse*
778*6777b538SAndroid Build Coastguard Worker // -> UpdateCachedResponseComplete -> OverwriteCachedResponse ->
779*6777b538SAndroid Build Coastguard Worker // PartialHeadersReceived -> FinishHeaders*
780*6777b538SAndroid Build Coastguard Worker //
781*6777b538SAndroid Build Coastguard Worker // Read() 1:
782*6777b538SAndroid Build Coastguard Worker // NetworkReadCacheWrite*
783*6777b538SAndroid Build Coastguard Worker //
784*6777b538SAndroid Build Coastguard Worker // Read() 2:
785*6777b538SAndroid Build Coastguard Worker // NetworkReadCacheWrite* -> StartPartialCacheValidation ->
786*6777b538SAndroid Build Coastguard Worker // CompletePartialCacheValidation -> ConnectedCallback* -> CacheReadData*
787*6777b538SAndroid Build Coastguard Worker //
788*6777b538SAndroid Build Coastguard Worker // Read() 3:
789*6777b538SAndroid Build Coastguard Worker // CacheReadData* -> StartPartialCacheValidation ->
790*6777b538SAndroid Build Coastguard Worker // CompletePartialCacheValidation -> BeginCacheValidation() -> SendRequest* ->
791*6777b538SAndroid Build Coastguard Worker // SuccessfulSendRequest -> UpdateCachedResponse* -> OverwriteCachedResponse
792*6777b538SAndroid Build Coastguard Worker // -> PartialHeadersReceived -> NetworkReadCacheWrite*
793*6777b538SAndroid Build Coastguard Worker //
794*6777b538SAndroid Build Coastguard Worker // 6. HEAD. Not-cached entry:
795*6777b538SAndroid Build Coastguard Worker // Pass through. Don't save a HEAD by itself.
796*6777b538SAndroid Build Coastguard Worker // Start():
797*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> SendRequest*
798*6777b538SAndroid Build Coastguard Worker //
799*6777b538SAndroid Build Coastguard Worker // 7. HEAD. Cached entry, no validation:
800*6777b538SAndroid Build Coastguard Worker // Start():
801*6777b538SAndroid Build Coastguard Worker // The same flow as for a GET request (example #2)
802*6777b538SAndroid Build Coastguard Worker //
803*6777b538SAndroid Build Coastguard Worker // Read():
804*6777b538SAndroid Build Coastguard Worker // CacheReadData (returns 0)
805*6777b538SAndroid Build Coastguard Worker //
806*6777b538SAndroid Build Coastguard Worker // 8. HEAD. Cached entry, validation (304):
807*6777b538SAndroid Build Coastguard Worker // The request updates the stored headers.
808*6777b538SAndroid Build Coastguard Worker // Start(): Same as for a GET request (example #3)
809*6777b538SAndroid Build Coastguard Worker //
810*6777b538SAndroid Build Coastguard Worker // Read():
811*6777b538SAndroid Build Coastguard Worker // CacheReadData (returns 0)
812*6777b538SAndroid Build Coastguard Worker //
813*6777b538SAndroid Build Coastguard Worker // 9. HEAD. Cached entry, validation and replace (200):
814*6777b538SAndroid Build Coastguard Worker // Pass through. The request dooms the old entry, as a HEAD won't be stored by
815*6777b538SAndroid Build Coastguard Worker // itself.
816*6777b538SAndroid Build Coastguard Worker // Start():
817*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
818*6777b538SAndroid Build Coastguard Worker // CacheReadResponse* -> CacheDispatchValidation ->
819*6777b538SAndroid Build Coastguard Worker // BeginPartialCacheValidation() -> BeginCacheValidation() -> SendRequest* ->
820*6777b538SAndroid Build Coastguard Worker // SuccessfulSendRequest -> OverwriteCachedResponse -> FinishHeaders*
821*6777b538SAndroid Build Coastguard Worker //
822*6777b538SAndroid Build Coastguard Worker // 10. HEAD. Sparse entry, partially cached:
823*6777b538SAndroid Build Coastguard Worker // Serve the request from the cache, as long as it doesn't require
824*6777b538SAndroid Build Coastguard Worker // revalidation. Ignore missing ranges when deciding to revalidate. If the
825*6777b538SAndroid Build Coastguard Worker // entry requires revalidation, ignore the whole request and go to full pass
826*6777b538SAndroid Build Coastguard Worker // through (the result of the HEAD request will NOT update the entry).
827*6777b538SAndroid Build Coastguard Worker //
828*6777b538SAndroid Build Coastguard Worker // Start(): Basically the same as example 7, as we never create a partial_
829*6777b538SAndroid Build Coastguard Worker // object for this request.
830*6777b538SAndroid Build Coastguard Worker //
831*6777b538SAndroid Build Coastguard Worker // 11. Prefetch, not-cached entry:
832*6777b538SAndroid Build Coastguard Worker // The same as example 1. The "unused_since_prefetch" bit is stored as true in
833*6777b538SAndroid Build Coastguard Worker // UpdateCachedResponse.
834*6777b538SAndroid Build Coastguard Worker //
835*6777b538SAndroid Build Coastguard Worker // 12. Prefetch, cached entry:
836*6777b538SAndroid Build Coastguard Worker // Like examples 2-4, only CacheWriteUpdatedPrefetchResponse* is inserted
837*6777b538SAndroid Build Coastguard Worker // between CacheReadResponse* and CacheDispatchValidation if the
838*6777b538SAndroid Build Coastguard Worker // unused_since_prefetch bit is unset.
839*6777b538SAndroid Build Coastguard Worker //
840*6777b538SAndroid Build Coastguard Worker // 13. Cached entry less than 5 minutes old, unused_since_prefetch is true:
841*6777b538SAndroid Build Coastguard Worker // Skip validation, similar to example 2.
842*6777b538SAndroid Build Coastguard Worker // GetBackend* -> InitEntry -> OpenOrCreateEntry* -> AddToEntry* ->
843*6777b538SAndroid Build Coastguard Worker // CacheReadResponse* -> CacheToggleUnusedSincePrefetch* ->
844*6777b538SAndroid Build Coastguard Worker // CacheDispatchValidation -> BeginPartialCacheValidation() ->
845*6777b538SAndroid Build Coastguard Worker // BeginCacheValidation() -> ConnectedCallback* -> SetupEntryForRead() ->
846*6777b538SAndroid Build Coastguard Worker // FinishHeaders*
847*6777b538SAndroid Build Coastguard Worker //
848*6777b538SAndroid Build Coastguard Worker // Read():
849*6777b538SAndroid Build Coastguard Worker // CacheReadData*
850*6777b538SAndroid Build Coastguard Worker //
851*6777b538SAndroid Build Coastguard Worker // 14. Cached entry more than 5 minutes old, unused_since_prefetch is true:
852*6777b538SAndroid Build Coastguard Worker // Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between
853*6777b538SAndroid Build Coastguard Worker // CacheReadResponse* and CacheDispatchValidation.
DoLoop(int result)854*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoLoop(int result) {
855*6777b538SAndroid Build Coastguard Worker DCHECK_NE(STATE_UNSET, next_state_);
856*6777b538SAndroid Build Coastguard Worker DCHECK_NE(STATE_NONE, next_state_);
857*6777b538SAndroid Build Coastguard Worker DCHECK(!in_do_loop_);
858*6777b538SAndroid Build Coastguard Worker
859*6777b538SAndroid Build Coastguard Worker int rv = result;
860*6777b538SAndroid Build Coastguard Worker State state = next_state_;
861*6777b538SAndroid Build Coastguard Worker do {
862*6777b538SAndroid Build Coastguard Worker state = next_state_;
863*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_UNSET;
864*6777b538SAndroid Build Coastguard Worker base::AutoReset<bool> scoped_in_do_loop(&in_do_loop_, true);
865*6777b538SAndroid Build Coastguard Worker
866*6777b538SAndroid Build Coastguard Worker switch (state) {
867*6777b538SAndroid Build Coastguard Worker case STATE_GET_BACKEND:
868*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
869*6777b538SAndroid Build Coastguard Worker rv = DoGetBackend();
870*6777b538SAndroid Build Coastguard Worker break;
871*6777b538SAndroid Build Coastguard Worker case STATE_GET_BACKEND_COMPLETE:
872*6777b538SAndroid Build Coastguard Worker rv = DoGetBackendComplete(rv);
873*6777b538SAndroid Build Coastguard Worker break;
874*6777b538SAndroid Build Coastguard Worker case STATE_INIT_ENTRY:
875*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
876*6777b538SAndroid Build Coastguard Worker rv = DoInitEntry();
877*6777b538SAndroid Build Coastguard Worker break;
878*6777b538SAndroid Build Coastguard Worker case STATE_OPEN_OR_CREATE_ENTRY:
879*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
880*6777b538SAndroid Build Coastguard Worker rv = DoOpenOrCreateEntry();
881*6777b538SAndroid Build Coastguard Worker break;
882*6777b538SAndroid Build Coastguard Worker case STATE_OPEN_OR_CREATE_ENTRY_COMPLETE:
883*6777b538SAndroid Build Coastguard Worker rv = DoOpenOrCreateEntryComplete(rv);
884*6777b538SAndroid Build Coastguard Worker break;
885*6777b538SAndroid Build Coastguard Worker case STATE_DOOM_ENTRY:
886*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
887*6777b538SAndroid Build Coastguard Worker rv = DoDoomEntry();
888*6777b538SAndroid Build Coastguard Worker break;
889*6777b538SAndroid Build Coastguard Worker case STATE_DOOM_ENTRY_COMPLETE:
890*6777b538SAndroid Build Coastguard Worker rv = DoDoomEntryComplete(rv);
891*6777b538SAndroid Build Coastguard Worker break;
892*6777b538SAndroid Build Coastguard Worker case STATE_CREATE_ENTRY:
893*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
894*6777b538SAndroid Build Coastguard Worker rv = DoCreateEntry();
895*6777b538SAndroid Build Coastguard Worker break;
896*6777b538SAndroid Build Coastguard Worker case STATE_CREATE_ENTRY_COMPLETE:
897*6777b538SAndroid Build Coastguard Worker rv = DoCreateEntryComplete(rv);
898*6777b538SAndroid Build Coastguard Worker break;
899*6777b538SAndroid Build Coastguard Worker case STATE_ADD_TO_ENTRY:
900*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
901*6777b538SAndroid Build Coastguard Worker rv = DoAddToEntry();
902*6777b538SAndroid Build Coastguard Worker break;
903*6777b538SAndroid Build Coastguard Worker case STATE_ADD_TO_ENTRY_COMPLETE:
904*6777b538SAndroid Build Coastguard Worker rv = DoAddToEntryComplete(rv);
905*6777b538SAndroid Build Coastguard Worker break;
906*6777b538SAndroid Build Coastguard Worker case STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE:
907*6777b538SAndroid Build Coastguard Worker rv = DoDoneHeadersAddToEntryComplete(rv);
908*6777b538SAndroid Build Coastguard Worker break;
909*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_READ_RESPONSE:
910*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
911*6777b538SAndroid Build Coastguard Worker rv = DoCacheReadResponse();
912*6777b538SAndroid Build Coastguard Worker break;
913*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_READ_RESPONSE_COMPLETE:
914*6777b538SAndroid Build Coastguard Worker rv = DoCacheReadResponseComplete(rv);
915*6777b538SAndroid Build Coastguard Worker break;
916*6777b538SAndroid Build Coastguard Worker case STATE_WRITE_UPDATED_PREFETCH_RESPONSE:
917*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
918*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteUpdatedPrefetchResponse(rv);
919*6777b538SAndroid Build Coastguard Worker break;
920*6777b538SAndroid Build Coastguard Worker case STATE_WRITE_UPDATED_PREFETCH_RESPONSE_COMPLETE:
921*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteUpdatedPrefetchResponseComplete(rv);
922*6777b538SAndroid Build Coastguard Worker break;
923*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_DISPATCH_VALIDATION:
924*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
925*6777b538SAndroid Build Coastguard Worker rv = DoCacheDispatchValidation();
926*6777b538SAndroid Build Coastguard Worker break;
927*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_QUERY_DATA:
928*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
929*6777b538SAndroid Build Coastguard Worker rv = DoCacheQueryData();
930*6777b538SAndroid Build Coastguard Worker break;
931*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_QUERY_DATA_COMPLETE:
932*6777b538SAndroid Build Coastguard Worker rv = DoCacheQueryDataComplete(rv);
933*6777b538SAndroid Build Coastguard Worker break;
934*6777b538SAndroid Build Coastguard Worker case STATE_START_PARTIAL_CACHE_VALIDATION:
935*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
936*6777b538SAndroid Build Coastguard Worker rv = DoStartPartialCacheValidation();
937*6777b538SAndroid Build Coastguard Worker break;
938*6777b538SAndroid Build Coastguard Worker case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION:
939*6777b538SAndroid Build Coastguard Worker rv = DoCompletePartialCacheValidation(rv);
940*6777b538SAndroid Build Coastguard Worker break;
941*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT:
942*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
943*6777b538SAndroid Build Coastguard Worker rv = DoCacheUpdateStaleWhileRevalidateTimeout();
944*6777b538SAndroid Build Coastguard Worker break;
945*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT_COMPLETE:
946*6777b538SAndroid Build Coastguard Worker rv = DoCacheUpdateStaleWhileRevalidateTimeoutComplete(rv);
947*6777b538SAndroid Build Coastguard Worker break;
948*6777b538SAndroid Build Coastguard Worker case STATE_CONNECTED_CALLBACK:
949*6777b538SAndroid Build Coastguard Worker rv = DoConnectedCallback();
950*6777b538SAndroid Build Coastguard Worker break;
951*6777b538SAndroid Build Coastguard Worker case STATE_CONNECTED_CALLBACK_COMPLETE:
952*6777b538SAndroid Build Coastguard Worker rv = DoConnectedCallbackComplete(rv);
953*6777b538SAndroid Build Coastguard Worker break;
954*6777b538SAndroid Build Coastguard Worker case STATE_SETUP_ENTRY_FOR_READ:
955*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
956*6777b538SAndroid Build Coastguard Worker rv = DoSetupEntryForRead();
957*6777b538SAndroid Build Coastguard Worker break;
958*6777b538SAndroid Build Coastguard Worker case STATE_SEND_REQUEST:
959*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
960*6777b538SAndroid Build Coastguard Worker rv = DoSendRequest();
961*6777b538SAndroid Build Coastguard Worker break;
962*6777b538SAndroid Build Coastguard Worker case STATE_SEND_REQUEST_COMPLETE:
963*6777b538SAndroid Build Coastguard Worker rv = DoSendRequestComplete(rv);
964*6777b538SAndroid Build Coastguard Worker break;
965*6777b538SAndroid Build Coastguard Worker case STATE_SUCCESSFUL_SEND_REQUEST:
966*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
967*6777b538SAndroid Build Coastguard Worker rv = DoSuccessfulSendRequest();
968*6777b538SAndroid Build Coastguard Worker break;
969*6777b538SAndroid Build Coastguard Worker case STATE_UPDATE_CACHED_RESPONSE:
970*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
971*6777b538SAndroid Build Coastguard Worker rv = DoUpdateCachedResponse();
972*6777b538SAndroid Build Coastguard Worker break;
973*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_WRITE_UPDATED_RESPONSE:
974*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
975*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteUpdatedResponse();
976*6777b538SAndroid Build Coastguard Worker break;
977*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE:
978*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteUpdatedResponseComplete(rv);
979*6777b538SAndroid Build Coastguard Worker break;
980*6777b538SAndroid Build Coastguard Worker case STATE_UPDATE_CACHED_RESPONSE_COMPLETE:
981*6777b538SAndroid Build Coastguard Worker rv = DoUpdateCachedResponseComplete(rv);
982*6777b538SAndroid Build Coastguard Worker break;
983*6777b538SAndroid Build Coastguard Worker case STATE_OVERWRITE_CACHED_RESPONSE:
984*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
985*6777b538SAndroid Build Coastguard Worker rv = DoOverwriteCachedResponse();
986*6777b538SAndroid Build Coastguard Worker break;
987*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_WRITE_RESPONSE:
988*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
989*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteResponse();
990*6777b538SAndroid Build Coastguard Worker break;
991*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
992*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteResponseComplete(rv);
993*6777b538SAndroid Build Coastguard Worker break;
994*6777b538SAndroid Build Coastguard Worker case STATE_TRUNCATE_CACHED_DATA:
995*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
996*6777b538SAndroid Build Coastguard Worker rv = DoTruncateCachedData();
997*6777b538SAndroid Build Coastguard Worker break;
998*6777b538SAndroid Build Coastguard Worker case STATE_TRUNCATE_CACHED_DATA_COMPLETE:
999*6777b538SAndroid Build Coastguard Worker rv = DoTruncateCachedDataComplete(rv);
1000*6777b538SAndroid Build Coastguard Worker break;
1001*6777b538SAndroid Build Coastguard Worker case STATE_PARTIAL_HEADERS_RECEIVED:
1002*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
1003*6777b538SAndroid Build Coastguard Worker rv = DoPartialHeadersReceived();
1004*6777b538SAndroid Build Coastguard Worker break;
1005*6777b538SAndroid Build Coastguard Worker case STATE_HEADERS_PHASE_CANNOT_PROCEED:
1006*6777b538SAndroid Build Coastguard Worker rv = DoHeadersPhaseCannotProceed(rv);
1007*6777b538SAndroid Build Coastguard Worker break;
1008*6777b538SAndroid Build Coastguard Worker case STATE_FINISH_HEADERS:
1009*6777b538SAndroid Build Coastguard Worker rv = DoFinishHeaders(rv);
1010*6777b538SAndroid Build Coastguard Worker break;
1011*6777b538SAndroid Build Coastguard Worker case STATE_FINISH_HEADERS_COMPLETE:
1012*6777b538SAndroid Build Coastguard Worker rv = DoFinishHeadersComplete(rv);
1013*6777b538SAndroid Build Coastguard Worker break;
1014*6777b538SAndroid Build Coastguard Worker case STATE_NETWORK_READ_CACHE_WRITE:
1015*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
1016*6777b538SAndroid Build Coastguard Worker rv = DoNetworkReadCacheWrite();
1017*6777b538SAndroid Build Coastguard Worker break;
1018*6777b538SAndroid Build Coastguard Worker case STATE_NETWORK_READ_CACHE_WRITE_COMPLETE:
1019*6777b538SAndroid Build Coastguard Worker rv = DoNetworkReadCacheWriteComplete(rv);
1020*6777b538SAndroid Build Coastguard Worker break;
1021*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_READ_DATA:
1022*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
1023*6777b538SAndroid Build Coastguard Worker rv = DoCacheReadData();
1024*6777b538SAndroid Build Coastguard Worker break;
1025*6777b538SAndroid Build Coastguard Worker case STATE_CACHE_READ_DATA_COMPLETE:
1026*6777b538SAndroid Build Coastguard Worker rv = DoCacheReadDataComplete(rv);
1027*6777b538SAndroid Build Coastguard Worker break;
1028*6777b538SAndroid Build Coastguard Worker case STATE_NETWORK_READ:
1029*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
1030*6777b538SAndroid Build Coastguard Worker rv = DoNetworkRead();
1031*6777b538SAndroid Build Coastguard Worker break;
1032*6777b538SAndroid Build Coastguard Worker case STATE_NETWORK_READ_COMPLETE:
1033*6777b538SAndroid Build Coastguard Worker rv = DoNetworkReadComplete(rv);
1034*6777b538SAndroid Build Coastguard Worker break;
1035*6777b538SAndroid Build Coastguard Worker default:
1036*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "bad state " << state;
1037*6777b538SAndroid Build Coastguard Worker rv = ERR_FAILED;
1038*6777b538SAndroid Build Coastguard Worker break;
1039*6777b538SAndroid Build Coastguard Worker }
1040*6777b538SAndroid Build Coastguard Worker DCHECK(next_state_ != STATE_UNSET) << "Previous state was " << state;
1041*6777b538SAndroid Build Coastguard Worker
1042*6777b538SAndroid Build Coastguard Worker } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
1043*6777b538SAndroid Build Coastguard Worker
1044*6777b538SAndroid Build Coastguard Worker // Assert Start() state machine's allowed last state in successful cases when
1045*6777b538SAndroid Build Coastguard Worker // caching is happening.
1046*6777b538SAndroid Build Coastguard Worker DCHECK(reading_ || rv != OK || !entry_ ||
1047*6777b538SAndroid Build Coastguard Worker state == STATE_FINISH_HEADERS_COMPLETE);
1048*6777b538SAndroid Build Coastguard Worker
1049*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING && !callback_.is_null()) {
1050*6777b538SAndroid Build Coastguard Worker read_buf_ = nullptr; // Release the buffer before invoking the callback.
1051*6777b538SAndroid Build Coastguard Worker std::move(callback_).Run(rv);
1052*6777b538SAndroid Build Coastguard Worker }
1053*6777b538SAndroid Build Coastguard Worker
1054*6777b538SAndroid Build Coastguard Worker return rv;
1055*6777b538SAndroid Build Coastguard Worker }
1056*6777b538SAndroid Build Coastguard Worker
DoGetBackend()1057*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoGetBackend() {
1058*6777b538SAndroid Build Coastguard Worker cache_pending_ = true;
1059*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_GET_BACKEND_COMPLETE);
1060*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_GET_BACKEND);
1061*6777b538SAndroid Build Coastguard Worker return cache_->GetBackendForTransaction(this);
1062*6777b538SAndroid Build Coastguard Worker }
1063*6777b538SAndroid Build Coastguard Worker
DoGetBackendComplete(int result)1064*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoGetBackendComplete(int result) {
1065*6777b538SAndroid Build Coastguard Worker DCHECK(result == OK || result == ERR_FAILED);
1066*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_GET_BACKEND,
1067*6777b538SAndroid Build Coastguard Worker result);
1068*6777b538SAndroid Build Coastguard Worker cache_pending_ = false;
1069*6777b538SAndroid Build Coastguard Worker
1070*6777b538SAndroid Build Coastguard Worker // Reset mode_ that might get set in this function. This is done because this
1071*6777b538SAndroid Build Coastguard Worker // function can be invoked multiple times for a transaction.
1072*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1073*6777b538SAndroid Build Coastguard Worker const bool should_pass_through = ShouldPassThrough();
1074*6777b538SAndroid Build Coastguard Worker
1075*6777b538SAndroid Build Coastguard Worker if (!should_pass_through) {
1076*6777b538SAndroid Build Coastguard Worker cache_key_ = *cache_->GenerateCacheKeyForRequest(request_);
1077*6777b538SAndroid Build Coastguard Worker
1078*6777b538SAndroid Build Coastguard Worker // Requested cache access mode.
1079*6777b538SAndroid Build Coastguard Worker if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
1080*6777b538SAndroid Build Coastguard Worker if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
1081*6777b538SAndroid Build Coastguard Worker // The client has asked for nonsense.
1082*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1083*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_MISS;
1084*6777b538SAndroid Build Coastguard Worker }
1085*6777b538SAndroid Build Coastguard Worker mode_ = READ;
1086*6777b538SAndroid Build Coastguard Worker } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
1087*6777b538SAndroid Build Coastguard Worker mode_ = WRITE;
1088*6777b538SAndroid Build Coastguard Worker } else {
1089*6777b538SAndroid Build Coastguard Worker mode_ = READ_WRITE;
1090*6777b538SAndroid Build Coastguard Worker }
1091*6777b538SAndroid Build Coastguard Worker
1092*6777b538SAndroid Build Coastguard Worker // Downgrade to UPDATE if the request has been externally conditionalized.
1093*6777b538SAndroid Build Coastguard Worker if (external_validation_.initialized) {
1094*6777b538SAndroid Build Coastguard Worker if (mode_ & WRITE) {
1095*6777b538SAndroid Build Coastguard Worker // Strip off the READ_DATA bit (and maybe add back a READ_META bit
1096*6777b538SAndroid Build Coastguard Worker // in case READ was off).
1097*6777b538SAndroid Build Coastguard Worker mode_ = UPDATE;
1098*6777b538SAndroid Build Coastguard Worker } else {
1099*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1100*6777b538SAndroid Build Coastguard Worker }
1101*6777b538SAndroid Build Coastguard Worker }
1102*6777b538SAndroid Build Coastguard Worker }
1103*6777b538SAndroid Build Coastguard Worker
1104*6777b538SAndroid Build Coastguard Worker // Use PUT, DELETE, and PATCH only to invalidate existing stored entries.
1105*6777b538SAndroid Build Coastguard Worker if ((method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH") &&
1106*6777b538SAndroid Build Coastguard Worker mode_ != READ_WRITE && mode_ != WRITE) {
1107*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1108*6777b538SAndroid Build Coastguard Worker }
1109*6777b538SAndroid Build Coastguard Worker
1110*6777b538SAndroid Build Coastguard Worker // Note that if mode_ == UPDATE (which is tied to external_validation_), the
1111*6777b538SAndroid Build Coastguard Worker // transaction behaves the same for GET and HEAD requests at this point: if it
1112*6777b538SAndroid Build Coastguard Worker // was not modified, the entry is updated and a response is not returned from
1113*6777b538SAndroid Build Coastguard Worker // the cache. If we receive 200, it doesn't matter if there was a validation
1114*6777b538SAndroid Build Coastguard Worker // header or not.
1115*6777b538SAndroid Build Coastguard Worker if (method_ == "HEAD" && mode_ == WRITE) {
1116*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1117*6777b538SAndroid Build Coastguard Worker }
1118*6777b538SAndroid Build Coastguard Worker
1119*6777b538SAndroid Build Coastguard Worker // If must use cache, then we must fail. This can happen for back/forward
1120*6777b538SAndroid Build Coastguard Worker // navigations to a page generated via a form post.
1121*6777b538SAndroid Build Coastguard Worker if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
1122*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1123*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_MISS;
1124*6777b538SAndroid Build Coastguard Worker }
1125*6777b538SAndroid Build Coastguard Worker
1126*6777b538SAndroid Build Coastguard Worker if (mode_ == NONE) {
1127*6777b538SAndroid Build Coastguard Worker if (partial_) {
1128*6777b538SAndroid Build Coastguard Worker partial_->RestoreHeaders(&custom_request_->extra_headers);
1129*6777b538SAndroid Build Coastguard Worker partial_.reset();
1130*6777b538SAndroid Build Coastguard Worker }
1131*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1132*6777b538SAndroid Build Coastguard Worker } else {
1133*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_INIT_ENTRY);
1134*6777b538SAndroid Build Coastguard Worker }
1135*6777b538SAndroid Build Coastguard Worker
1136*6777b538SAndroid Build Coastguard Worker // This is only set if we have something to do with the response.
1137*6777b538SAndroid Build Coastguard Worker range_requested_ = (partial_.get() != nullptr);
1138*6777b538SAndroid Build Coastguard Worker
1139*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoGetBackendComplete",
1140*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "mode", mode_,
1141*6777b538SAndroid Build Coastguard Worker "should_pass_through", should_pass_through);
1142*6777b538SAndroid Build Coastguard Worker return OK;
1143*6777b538SAndroid Build Coastguard Worker }
1144*6777b538SAndroid Build Coastguard Worker
DoInitEntry()1145*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoInitEntry() {
1146*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoInitEntry",
1147*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1148*6777b538SAndroid Build Coastguard Worker DCHECK(!new_entry_);
1149*6777b538SAndroid Build Coastguard Worker
1150*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
1151*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1152*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
1153*6777b538SAndroid Build Coastguard Worker }
1154*6777b538SAndroid Build Coastguard Worker
1155*6777b538SAndroid Build Coastguard Worker if (mode_ == WRITE) {
1156*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_DOOM_ENTRY);
1157*6777b538SAndroid Build Coastguard Worker return OK;
1158*6777b538SAndroid Build Coastguard Worker }
1159*6777b538SAndroid Build Coastguard Worker
1160*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_OPEN_OR_CREATE_ENTRY);
1161*6777b538SAndroid Build Coastguard Worker return OK;
1162*6777b538SAndroid Build Coastguard Worker }
1163*6777b538SAndroid Build Coastguard Worker
DoOpenOrCreateEntry()1164*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoOpenOrCreateEntry() {
1165*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoOpenOrCreateEntry",
1166*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1167*6777b538SAndroid Build Coastguard Worker DCHECK(!new_entry_);
1168*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_OPEN_OR_CREATE_ENTRY_COMPLETE);
1169*6777b538SAndroid Build Coastguard Worker cache_pending_ = true;
1170*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY);
1171*6777b538SAndroid Build Coastguard Worker first_cache_access_since_ = TimeTicks::Now();
1172*6777b538SAndroid Build Coastguard Worker const bool has_opened_or_created_entry = has_opened_or_created_entry_;
1173*6777b538SAndroid Build Coastguard Worker has_opened_or_created_entry_ = true;
1174*6777b538SAndroid Build Coastguard Worker record_entry_open_or_creation_time_ = false;
1175*6777b538SAndroid Build Coastguard Worker
1176*6777b538SAndroid Build Coastguard Worker // See if we already have something working with this cache key.
1177*6777b538SAndroid Build Coastguard Worker new_entry_ = cache_->GetActiveEntry(cache_key_);
1178*6777b538SAndroid Build Coastguard Worker if (new_entry_) {
1179*6777b538SAndroid Build Coastguard Worker return OK;
1180*6777b538SAndroid Build Coastguard Worker }
1181*6777b538SAndroid Build Coastguard Worker
1182*6777b538SAndroid Build Coastguard Worker // See if we could potentially doom the entry based on hints the backend keeps
1183*6777b538SAndroid Build Coastguard Worker // in memory.
1184*6777b538SAndroid Build Coastguard Worker // Currently only SimpleCache utilizes in memory hints. If an entry is found
1185*6777b538SAndroid Build Coastguard Worker // unsuitable, and thus Doomed, SimpleCache can also optimize the
1186*6777b538SAndroid Build Coastguard Worker // OpenOrCreateEntry() call to reduce the overhead of trying to open an entry
1187*6777b538SAndroid Build Coastguard Worker // we know is doomed.
1188*6777b538SAndroid Build Coastguard Worker uint8_t in_memory_info =
1189*6777b538SAndroid Build Coastguard Worker cache_->GetCurrentBackend()->GetEntryInMemoryData(cache_key_);
1190*6777b538SAndroid Build Coastguard Worker bool entry_not_suitable = false;
1191*6777b538SAndroid Build Coastguard Worker if (MaybeRejectBasedOnEntryInMemoryData(in_memory_info)) {
1192*6777b538SAndroid Build Coastguard Worker cache_->GetCurrentBackend()->DoomEntry(cache_key_, priority_,
1193*6777b538SAndroid Build Coastguard Worker base::DoNothing());
1194*6777b538SAndroid Build Coastguard Worker entry_not_suitable = true;
1195*6777b538SAndroid Build Coastguard Worker // Documents the case this applies in
1196*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(mode_, READ_WRITE);
1197*6777b538SAndroid Build Coastguard Worker // Record this as CantConditionalize, but otherwise proceed as we would
1198*6777b538SAndroid Build Coastguard Worker // below --- as we've already dropped the old entry.
1199*6777b538SAndroid Build Coastguard Worker couldnt_conditionalize_request_ = true;
1200*6777b538SAndroid Build Coastguard Worker validation_cause_ = VALIDATION_CAUSE_ZERO_FRESHNESS;
1201*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
1202*6777b538SAndroid Build Coastguard Worker }
1203*6777b538SAndroid Build Coastguard Worker
1204*6777b538SAndroid Build Coastguard Worker if (!has_opened_or_created_entry) {
1205*6777b538SAndroid Build Coastguard Worker record_entry_open_or_creation_time_ = true;
1206*6777b538SAndroid Build Coastguard Worker }
1207*6777b538SAndroid Build Coastguard Worker
1208*6777b538SAndroid Build Coastguard Worker // mode_ can be anything but NONE or WRITE at this point (READ, UPDATE, or
1209*6777b538SAndroid Build Coastguard Worker // READ_WRITE).
1210*6777b538SAndroid Build Coastguard Worker // READ, UPDATE, certain READ_WRITEs, and some methods shouldn't create, so
1211*6777b538SAndroid Build Coastguard Worker // try only opening.
1212*6777b538SAndroid Build Coastguard Worker if (mode_ != READ_WRITE || ShouldOpenOnlyMethods()) {
1213*6777b538SAndroid Build Coastguard Worker if (entry_not_suitable) {
1214*6777b538SAndroid Build Coastguard Worker // The entry isn't suitable and we can't create a new one.
1215*6777b538SAndroid Build Coastguard Worker return net::ERR_CACHE_ENTRY_NOT_SUITABLE;
1216*6777b538SAndroid Build Coastguard Worker }
1217*6777b538SAndroid Build Coastguard Worker
1218*6777b538SAndroid Build Coastguard Worker return cache_->OpenEntry(cache_key_, &new_entry_, this);
1219*6777b538SAndroid Build Coastguard Worker }
1220*6777b538SAndroid Build Coastguard Worker
1221*6777b538SAndroid Build Coastguard Worker return cache_->OpenOrCreateEntry(cache_key_, &new_entry_, this);
1222*6777b538SAndroid Build Coastguard Worker }
1223*6777b538SAndroid Build Coastguard Worker
DoOpenOrCreateEntryComplete(int result)1224*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoOpenOrCreateEntryComplete(int result) {
1225*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
1226*6777b538SAndroid Build Coastguard Worker "net", "HttpCacheTransaction::DoOpenOrCreateEntryComplete",
1227*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result",
1228*6777b538SAndroid Build Coastguard Worker (result == OK ? (new_entry_->opened() ? "opened" : "created")
1229*6777b538SAndroid Build Coastguard Worker : "failed"));
1230*6777b538SAndroid Build Coastguard Worker
1231*6777b538SAndroid Build Coastguard Worker const bool record_uma =
1232*6777b538SAndroid Build Coastguard Worker record_entry_open_or_creation_time_ && cache_ &&
1233*6777b538SAndroid Build Coastguard Worker cache_->GetCurrentBackend() &&
1234*6777b538SAndroid Build Coastguard Worker cache_->GetCurrentBackend()->GetCacheType() != MEMORY_CACHE;
1235*6777b538SAndroid Build Coastguard Worker record_entry_open_or_creation_time_ = false;
1236*6777b538SAndroid Build Coastguard Worker
1237*6777b538SAndroid Build Coastguard Worker // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
1238*6777b538SAndroid Build Coastguard Worker // OK, otherwise the cache will end up with an active entry without any
1239*6777b538SAndroid Build Coastguard Worker // transaction attached.
1240*6777b538SAndroid Build Coastguard Worker net_log_.EndEvent(NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY, [&] {
1241*6777b538SAndroid Build Coastguard Worker base::Value::Dict params;
1242*6777b538SAndroid Build Coastguard Worker if (result == OK) {
1243*6777b538SAndroid Build Coastguard Worker params.Set("result", new_entry_->opened() ? "opened" : "created");
1244*6777b538SAndroid Build Coastguard Worker } else {
1245*6777b538SAndroid Build Coastguard Worker params.Set("net_error", result);
1246*6777b538SAndroid Build Coastguard Worker }
1247*6777b538SAndroid Build Coastguard Worker return params;
1248*6777b538SAndroid Build Coastguard Worker });
1249*6777b538SAndroid Build Coastguard Worker
1250*6777b538SAndroid Build Coastguard Worker cache_pending_ = false;
1251*6777b538SAndroid Build Coastguard Worker
1252*6777b538SAndroid Build Coastguard Worker if (result == OK) {
1253*6777b538SAndroid Build Coastguard Worker if (new_entry_->opened()) {
1254*6777b538SAndroid Build Coastguard Worker if (record_uma) {
1255*6777b538SAndroid Build Coastguard Worker base::UmaHistogramTimes(
1256*6777b538SAndroid Build Coastguard Worker "HttpCache.OpenDiskEntry",
1257*6777b538SAndroid Build Coastguard Worker base::TimeTicks::Now() - first_cache_access_since_);
1258*6777b538SAndroid Build Coastguard Worker }
1259*6777b538SAndroid Build Coastguard Worker } else {
1260*6777b538SAndroid Build Coastguard Worker if (record_uma) {
1261*6777b538SAndroid Build Coastguard Worker base::UmaHistogramTimes(
1262*6777b538SAndroid Build Coastguard Worker "HttpCache.CreateDiskEntry",
1263*6777b538SAndroid Build Coastguard Worker base::TimeTicks::Now() - first_cache_access_since_);
1264*6777b538SAndroid Build Coastguard Worker }
1265*6777b538SAndroid Build Coastguard Worker
1266*6777b538SAndroid Build Coastguard Worker // Entry was created so mode changes to WRITE.
1267*6777b538SAndroid Build Coastguard Worker mode_ = WRITE;
1268*6777b538SAndroid Build Coastguard Worker }
1269*6777b538SAndroid Build Coastguard Worker
1270*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_ADD_TO_ENTRY);
1271*6777b538SAndroid Build Coastguard Worker return OK;
1272*6777b538SAndroid Build Coastguard Worker }
1273*6777b538SAndroid Build Coastguard Worker
1274*6777b538SAndroid Build Coastguard Worker if (result == ERR_CACHE_RACE) {
1275*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
1276*6777b538SAndroid Build Coastguard Worker return OK;
1277*6777b538SAndroid Build Coastguard Worker }
1278*6777b538SAndroid Build Coastguard Worker
1279*6777b538SAndroid Build Coastguard Worker // No need to explicitly handle ERR_CACHE_ENTRY_NOT_SUITABLE as the
1280*6777b538SAndroid Build Coastguard Worker // ShouldOpenOnlyMethods() check will handle it.
1281*6777b538SAndroid Build Coastguard Worker
1282*6777b538SAndroid Build Coastguard Worker if (mode_ & WRITE) {
1283*6777b538SAndroid Build Coastguard Worker // We were unable to open or create an entry.
1284*6777b538SAndroid Build Coastguard Worker DLOG(WARNING) << "Unable to open or create cache entry";
1285*6777b538SAndroid Build Coastguard Worker }
1286*6777b538SAndroid Build Coastguard Worker
1287*6777b538SAndroid Build Coastguard Worker if (ShouldOpenOnlyMethods()) {
1288*6777b538SAndroid Build Coastguard Worker // These methods, on failure, should bypass the cache.
1289*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1290*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1291*6777b538SAndroid Build Coastguard Worker return OK;
1292*6777b538SAndroid Build Coastguard Worker }
1293*6777b538SAndroid Build Coastguard Worker
1294*6777b538SAndroid Build Coastguard Worker // Since the operation failed, what we do next depends on the mode_ which can
1295*6777b538SAndroid Build Coastguard Worker // be the following: READ, READ_WRITE, or UPDATE. Note: mode_ cannot be WRITE
1296*6777b538SAndroid Build Coastguard Worker // or NONE at this point as DoInitEntry() handled those cases.
1297*6777b538SAndroid Build Coastguard Worker
1298*6777b538SAndroid Build Coastguard Worker switch (mode_) {
1299*6777b538SAndroid Build Coastguard Worker case READ:
1300*6777b538SAndroid Build Coastguard Worker // The entry does not exist, and we are not permitted to create a new
1301*6777b538SAndroid Build Coastguard Worker // entry, so we must fail.
1302*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1303*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_MISS;
1304*6777b538SAndroid Build Coastguard Worker case READ_WRITE:
1305*6777b538SAndroid Build Coastguard Worker // Unable to open or create; set the mode to NONE in order to bypass the
1306*6777b538SAndroid Build Coastguard Worker // cache entry and read from the network directly.
1307*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1308*6777b538SAndroid Build Coastguard Worker if (partial_) {
1309*6777b538SAndroid Build Coastguard Worker partial_->RestoreHeaders(&custom_request_->extra_headers);
1310*6777b538SAndroid Build Coastguard Worker }
1311*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1312*6777b538SAndroid Build Coastguard Worker break;
1313*6777b538SAndroid Build Coastguard Worker case UPDATE:
1314*6777b538SAndroid Build Coastguard Worker // There is no cache entry to update; proceed without caching.
1315*6777b538SAndroid Build Coastguard Worker DCHECK(!partial_);
1316*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1317*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1318*6777b538SAndroid Build Coastguard Worker break;
1319*6777b538SAndroid Build Coastguard Worker default:
1320*6777b538SAndroid Build Coastguard Worker NOTREACHED();
1321*6777b538SAndroid Build Coastguard Worker }
1322*6777b538SAndroid Build Coastguard Worker
1323*6777b538SAndroid Build Coastguard Worker return OK;
1324*6777b538SAndroid Build Coastguard Worker }
1325*6777b538SAndroid Build Coastguard Worker
DoDoomEntry()1326*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoDoomEntry() {
1327*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoDoomEntry",
1328*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1329*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_DOOM_ENTRY_COMPLETE);
1330*6777b538SAndroid Build Coastguard Worker cache_pending_ = true;
1331*6777b538SAndroid Build Coastguard Worker if (first_cache_access_since_.is_null()) {
1332*6777b538SAndroid Build Coastguard Worker first_cache_access_since_ = TimeTicks::Now();
1333*6777b538SAndroid Build Coastguard Worker }
1334*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_DOOM_ENTRY);
1335*6777b538SAndroid Build Coastguard Worker return cache_->DoomEntry(cache_key_, this);
1336*6777b538SAndroid Build Coastguard Worker }
1337*6777b538SAndroid Build Coastguard Worker
DoDoomEntryComplete(int result)1338*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoDoomEntryComplete(int result) {
1339*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoDoomEntryComplete",
1340*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
1341*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_DOOM_ENTRY,
1342*6777b538SAndroid Build Coastguard Worker result);
1343*6777b538SAndroid Build Coastguard Worker cache_pending_ = false;
1344*6777b538SAndroid Build Coastguard Worker TransitionToState(result == ERR_CACHE_RACE
1345*6777b538SAndroid Build Coastguard Worker ? STATE_HEADERS_PHASE_CANNOT_PROCEED
1346*6777b538SAndroid Build Coastguard Worker : STATE_CREATE_ENTRY);
1347*6777b538SAndroid Build Coastguard Worker return OK;
1348*6777b538SAndroid Build Coastguard Worker }
1349*6777b538SAndroid Build Coastguard Worker
DoCreateEntry()1350*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCreateEntry() {
1351*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoCreateEntry",
1352*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1353*6777b538SAndroid Build Coastguard Worker DCHECK(!new_entry_);
1354*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CREATE_ENTRY_COMPLETE);
1355*6777b538SAndroid Build Coastguard Worker cache_pending_ = true;
1356*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_CREATE_ENTRY);
1357*6777b538SAndroid Build Coastguard Worker return cache_->CreateEntry(cache_key_, &new_entry_, this);
1358*6777b538SAndroid Build Coastguard Worker }
1359*6777b538SAndroid Build Coastguard Worker
DoCreateEntryComplete(int result)1360*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCreateEntryComplete(int result) {
1361*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoCreateEntryComplete",
1362*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
1363*6777b538SAndroid Build Coastguard Worker // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
1364*6777b538SAndroid Build Coastguard Worker // OK, otherwise the cache will end up with an active entry without any
1365*6777b538SAndroid Build Coastguard Worker // transaction attached.
1366*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_CREATE_ENTRY,
1367*6777b538SAndroid Build Coastguard Worker result);
1368*6777b538SAndroid Build Coastguard Worker cache_pending_ = false;
1369*6777b538SAndroid Build Coastguard Worker switch (result) {
1370*6777b538SAndroid Build Coastguard Worker case OK:
1371*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_ADD_TO_ENTRY);
1372*6777b538SAndroid Build Coastguard Worker break;
1373*6777b538SAndroid Build Coastguard Worker
1374*6777b538SAndroid Build Coastguard Worker case ERR_CACHE_RACE:
1375*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
1376*6777b538SAndroid Build Coastguard Worker break;
1377*6777b538SAndroid Build Coastguard Worker
1378*6777b538SAndroid Build Coastguard Worker default:
1379*6777b538SAndroid Build Coastguard Worker DLOG(WARNING) << "Unable to create cache entry";
1380*6777b538SAndroid Build Coastguard Worker
1381*6777b538SAndroid Build Coastguard Worker // Set the mode to NONE in order to bypass the cache entry and read from
1382*6777b538SAndroid Build Coastguard Worker // the network directly.
1383*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1384*6777b538SAndroid Build Coastguard Worker if (!done_headers_create_new_entry_) {
1385*6777b538SAndroid Build Coastguard Worker if (partial_) {
1386*6777b538SAndroid Build Coastguard Worker partial_->RestoreHeaders(&custom_request_->extra_headers);
1387*6777b538SAndroid Build Coastguard Worker }
1388*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1389*6777b538SAndroid Build Coastguard Worker return OK;
1390*6777b538SAndroid Build Coastguard Worker }
1391*6777b538SAndroid Build Coastguard Worker // The headers have already been received as a result of validation,
1392*6777b538SAndroid Build Coastguard Worker // triggering the doom of the old entry. So no network request needs to
1393*6777b538SAndroid Build Coastguard Worker // be sent. Note that since mode_ is NONE, the response won't be written
1394*6777b538SAndroid Build Coastguard Worker // to cache. Transition to STATE_CACHE_WRITE_RESPONSE as that's the state
1395*6777b538SAndroid Build Coastguard Worker // the transaction left off on when it tried to create the new entry.
1396*6777b538SAndroid Build Coastguard Worker done_headers_create_new_entry_ = false;
1397*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_WRITE_RESPONSE);
1398*6777b538SAndroid Build Coastguard Worker }
1399*6777b538SAndroid Build Coastguard Worker return OK;
1400*6777b538SAndroid Build Coastguard Worker }
1401*6777b538SAndroid Build Coastguard Worker
DoAddToEntry()1402*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoAddToEntry() {
1403*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoAddToEntry",
1404*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1405*6777b538SAndroid Build Coastguard Worker DCHECK(new_entry_);
1406*6777b538SAndroid Build Coastguard Worker cache_pending_ = true;
1407*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY);
1408*6777b538SAndroid Build Coastguard Worker DCHECK(entry_lock_waiting_since_.is_null());
1409*6777b538SAndroid Build Coastguard Worker
1410*6777b538SAndroid Build Coastguard Worker // By this point whether the entry was created or opened is no longer relevant
1411*6777b538SAndroid Build Coastguard Worker // for this transaction. However there may be queued transactions that want to
1412*6777b538SAndroid Build Coastguard Worker // use this entry and from their perspective the entry was opened, so change
1413*6777b538SAndroid Build Coastguard Worker // the flag to reflect that.
1414*6777b538SAndroid Build Coastguard Worker new_entry_->set_opened(true);
1415*6777b538SAndroid Build Coastguard Worker
1416*6777b538SAndroid Build Coastguard Worker int rv = cache_->AddTransactionToEntry(new_entry_, this);
1417*6777b538SAndroid Build Coastguard Worker CHECK_EQ(rv, ERR_IO_PENDING);
1418*6777b538SAndroid Build Coastguard Worker
1419*6777b538SAndroid Build Coastguard Worker // If headers phase is already done then we are here because of validation not
1420*6777b538SAndroid Build Coastguard Worker // matching and creating a new entry. This transaction should be the
1421*6777b538SAndroid Build Coastguard Worker // first transaction of that new entry and thus it will not have cache lock
1422*6777b538SAndroid Build Coastguard Worker // delays, thus returning early from here.
1423*6777b538SAndroid Build Coastguard Worker if (done_headers_create_new_entry_) {
1424*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(mode_, WRITE);
1425*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE);
1426*6777b538SAndroid Build Coastguard Worker return rv;
1427*6777b538SAndroid Build Coastguard Worker }
1428*6777b538SAndroid Build Coastguard Worker
1429*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_ADD_TO_ENTRY_COMPLETE);
1430*6777b538SAndroid Build Coastguard Worker
1431*6777b538SAndroid Build Coastguard Worker // For a very-select case of creating a new non-range request entry, run the
1432*6777b538SAndroid Build Coastguard Worker // AddTransactionToEntry in parallel with sending the network request to
1433*6777b538SAndroid Build Coastguard Worker // hide the latency. This will run until the next ERR_IO_PENDING (or
1434*6777b538SAndroid Build Coastguard Worker // failure).
1435*6777b538SAndroid Build Coastguard Worker if (!partial_ && mode_ == WRITE) {
1436*6777b538SAndroid Build Coastguard Worker CHECK(!waiting_for_cache_io_);
1437*6777b538SAndroid Build Coastguard Worker waiting_for_cache_io_ = true;
1438*6777b538SAndroid Build Coastguard Worker rv = OK;
1439*6777b538SAndroid Build Coastguard Worker }
1440*6777b538SAndroid Build Coastguard Worker
1441*6777b538SAndroid Build Coastguard Worker entry_lock_waiting_since_ = TimeTicks::Now();
1442*6777b538SAndroid Build Coastguard Worker AddCacheLockTimeoutHandler(new_entry_.get());
1443*6777b538SAndroid Build Coastguard Worker return rv;
1444*6777b538SAndroid Build Coastguard Worker }
1445*6777b538SAndroid Build Coastguard Worker
AddCacheLockTimeoutHandler(ActiveEntry * entry)1446*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::AddCacheLockTimeoutHandler(ActiveEntry* entry) {
1447*6777b538SAndroid Build Coastguard Worker CHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
1448*6777b538SAndroid Build Coastguard Worker next_state_ == STATE_FINISH_HEADERS_COMPLETE);
1449*6777b538SAndroid Build Coastguard Worker if ((bypass_lock_for_test_ && next_state_ == STATE_ADD_TO_ENTRY_COMPLETE) ||
1450*6777b538SAndroid Build Coastguard Worker (bypass_lock_after_headers_for_test_ &&
1451*6777b538SAndroid Build Coastguard Worker next_state_ == STATE_FINISH_HEADERS_COMPLETE)) {
1452*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1453*6777b538SAndroid Build Coastguard Worker FROM_HERE,
1454*6777b538SAndroid Build Coastguard Worker base::BindOnce(&HttpCache::Transaction::OnCacheLockTimeout,
1455*6777b538SAndroid Build Coastguard Worker weak_factory_.GetWeakPtr(), entry_lock_waiting_since_));
1456*6777b538SAndroid Build Coastguard Worker } else {
1457*6777b538SAndroid Build Coastguard Worker int timeout_milliseconds = 20 * 1000;
1458*6777b538SAndroid Build Coastguard Worker if (partial_ && entry->HasWriters() && !entry->writers()->IsEmpty() &&
1459*6777b538SAndroid Build Coastguard Worker entry->writers()->IsExclusive()) {
1460*6777b538SAndroid Build Coastguard Worker // Even though entry_->writers takes care of allowing multiple writers to
1461*6777b538SAndroid Build Coastguard Worker // simultaneously govern reading from the network and writing to the cache
1462*6777b538SAndroid Build Coastguard Worker // for full requests, partial requests are still blocked by the
1463*6777b538SAndroid Build Coastguard Worker // reader/writer lock.
1464*6777b538SAndroid Build Coastguard Worker // Bypassing the cache after 25 ms of waiting for the cache lock
1465*6777b538SAndroid Build Coastguard Worker // eliminates a long running issue, http://crbug.com/31014, where
1466*6777b538SAndroid Build Coastguard Worker // two of the same media resources could not be played back simultaneously
1467*6777b538SAndroid Build Coastguard Worker // due to one locking the cache entry until the entire video was
1468*6777b538SAndroid Build Coastguard Worker // downloaded.
1469*6777b538SAndroid Build Coastguard Worker // Bypassing the cache is not ideal, as we are now ignoring the cache
1470*6777b538SAndroid Build Coastguard Worker // entirely for all range requests to a resource beyond the first. This
1471*6777b538SAndroid Build Coastguard Worker // is however a much more succinct solution than the alternatives, which
1472*6777b538SAndroid Build Coastguard Worker // would require somewhat significant changes to the http caching logic.
1473*6777b538SAndroid Build Coastguard Worker //
1474*6777b538SAndroid Build Coastguard Worker // Allow some timeout slack for the entry addition to complete in case
1475*6777b538SAndroid Build Coastguard Worker // the writer lock is imminently released; we want to avoid skipping
1476*6777b538SAndroid Build Coastguard Worker // the cache if at all possible. See http://crbug.com/408765
1477*6777b538SAndroid Build Coastguard Worker timeout_milliseconds = 25;
1478*6777b538SAndroid Build Coastguard Worker }
1479*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
1480*6777b538SAndroid Build Coastguard Worker FROM_HERE,
1481*6777b538SAndroid Build Coastguard Worker base::BindOnce(&HttpCache::Transaction::OnCacheLockTimeout,
1482*6777b538SAndroid Build Coastguard Worker weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
1483*6777b538SAndroid Build Coastguard Worker base::Milliseconds(timeout_milliseconds));
1484*6777b538SAndroid Build Coastguard Worker }
1485*6777b538SAndroid Build Coastguard Worker }
1486*6777b538SAndroid Build Coastguard Worker
DoAddToEntryComplete(int result)1487*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoAddToEntryComplete(int result) {
1488*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoAddToEntryComplete",
1489*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
1490*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY,
1491*6777b538SAndroid Build Coastguard Worker result);
1492*6777b538SAndroid Build Coastguard Worker if (cache_ && cache_->GetCurrentBackend() &&
1493*6777b538SAndroid Build Coastguard Worker cache_->GetCurrentBackend()->GetCacheType() != MEMORY_CACHE) {
1494*6777b538SAndroid Build Coastguard Worker const base::TimeDelta entry_lock_wait =
1495*6777b538SAndroid Build Coastguard Worker TimeTicks::Now() - entry_lock_waiting_since_;
1496*6777b538SAndroid Build Coastguard Worker base::UmaHistogramTimes("HttpCache.AddTransactionToEntry", entry_lock_wait);
1497*6777b538SAndroid Build Coastguard Worker }
1498*6777b538SAndroid Build Coastguard Worker
1499*6777b538SAndroid Build Coastguard Worker DCHECK(new_entry_);
1500*6777b538SAndroid Build Coastguard Worker
1501*6777b538SAndroid Build Coastguard Worker if (!waiting_for_cache_io_) {
1502*6777b538SAndroid Build Coastguard Worker entry_lock_waiting_since_ = TimeTicks();
1503*6777b538SAndroid Build Coastguard Worker cache_pending_ = false;
1504*6777b538SAndroid Build Coastguard Worker
1505*6777b538SAndroid Build Coastguard Worker if (result == OK) {
1506*6777b538SAndroid Build Coastguard Worker entry_ = std::move(new_entry_);
1507*6777b538SAndroid Build Coastguard Worker }
1508*6777b538SAndroid Build Coastguard Worker
1509*6777b538SAndroid Build Coastguard Worker // If there is a failure, the cache should have taken care of new_entry_.
1510*6777b538SAndroid Build Coastguard Worker new_entry_.reset();
1511*6777b538SAndroid Build Coastguard Worker }
1512*6777b538SAndroid Build Coastguard Worker
1513*6777b538SAndroid Build Coastguard Worker if (result == ERR_CACHE_RACE) {
1514*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
1515*6777b538SAndroid Build Coastguard Worker return OK;
1516*6777b538SAndroid Build Coastguard Worker }
1517*6777b538SAndroid Build Coastguard Worker
1518*6777b538SAndroid Build Coastguard Worker if (result == ERR_CACHE_LOCK_TIMEOUT) {
1519*6777b538SAndroid Build Coastguard Worker if (mode_ == READ) {
1520*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1521*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_MISS;
1522*6777b538SAndroid Build Coastguard Worker }
1523*6777b538SAndroid Build Coastguard Worker
1524*6777b538SAndroid Build Coastguard Worker // The cache is busy, bypass it for this transaction.
1525*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1526*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1527*6777b538SAndroid Build Coastguard Worker if (partial_) {
1528*6777b538SAndroid Build Coastguard Worker partial_->RestoreHeaders(&custom_request_->extra_headers);
1529*6777b538SAndroid Build Coastguard Worker partial_.reset();
1530*6777b538SAndroid Build Coastguard Worker }
1531*6777b538SAndroid Build Coastguard Worker return OK;
1532*6777b538SAndroid Build Coastguard Worker }
1533*6777b538SAndroid Build Coastguard Worker
1534*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/713354) Access timestamp for histograms only if entry is
1535*6777b538SAndroid Build Coastguard Worker // already written, to avoid data race since cache thread can also access
1536*6777b538SAndroid Build Coastguard Worker // this.
1537*6777b538SAndroid Build Coastguard Worker if (entry_ && !entry_->IsWritingInProgress()) {
1538*6777b538SAndroid Build Coastguard Worker open_entry_last_used_ = entry_->GetEntry()->GetLastUsed();
1539*6777b538SAndroid Build Coastguard Worker }
1540*6777b538SAndroid Build Coastguard Worker
1541*6777b538SAndroid Build Coastguard Worker // TODO(jkarlin): We should either handle the case or DCHECK.
1542*6777b538SAndroid Build Coastguard Worker if (result != OK) {
1543*6777b538SAndroid Build Coastguard Worker NOTREACHED();
1544*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1545*6777b538SAndroid Build Coastguard Worker return result;
1546*6777b538SAndroid Build Coastguard Worker }
1547*6777b538SAndroid Build Coastguard Worker
1548*6777b538SAndroid Build Coastguard Worker if (mode_ == WRITE) {
1549*6777b538SAndroid Build Coastguard Worker if (partial_) {
1550*6777b538SAndroid Build Coastguard Worker partial_->RestoreHeaders(&custom_request_->extra_headers);
1551*6777b538SAndroid Build Coastguard Worker }
1552*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1553*6777b538SAndroid Build Coastguard Worker } else {
1554*6777b538SAndroid Build Coastguard Worker // We have to read the headers from the cached entry.
1555*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ & READ_META);
1556*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_READ_RESPONSE);
1557*6777b538SAndroid Build Coastguard Worker }
1558*6777b538SAndroid Build Coastguard Worker return OK;
1559*6777b538SAndroid Build Coastguard Worker }
1560*6777b538SAndroid Build Coastguard Worker
DoDoneHeadersAddToEntryComplete(int result)1561*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoDoneHeadersAddToEntryComplete(int result) {
1562*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net",
1563*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoDoneHeadersAddToEntryComplete",
1564*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
1565*6777b538SAndroid Build Coastguard Worker // This transaction's response headers did not match its ActiveEntry so it
1566*6777b538SAndroid Build Coastguard Worker // created a new ActiveEntry (new_entry_) to write to (and doomed the old
1567*6777b538SAndroid Build Coastguard Worker // one). Now that the new entry has been created, start writing the response.
1568*6777b538SAndroid Build Coastguard Worker
1569*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(result, OK);
1570*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(mode_, WRITE);
1571*6777b538SAndroid Build Coastguard Worker DCHECK(new_entry_);
1572*6777b538SAndroid Build Coastguard Worker DCHECK(response_.headers);
1573*6777b538SAndroid Build Coastguard Worker
1574*6777b538SAndroid Build Coastguard Worker cache_pending_ = false;
1575*6777b538SAndroid Build Coastguard Worker done_headers_create_new_entry_ = false;
1576*6777b538SAndroid Build Coastguard Worker
1577*6777b538SAndroid Build Coastguard Worker // It is unclear exactly how this state is reached with an ERR_CACHE_RACE, but
1578*6777b538SAndroid Build Coastguard Worker // this check appears to fix a rare crash. See crbug.com/959194.
1579*6777b538SAndroid Build Coastguard Worker if (result == ERR_CACHE_RACE) {
1580*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
1581*6777b538SAndroid Build Coastguard Worker return OK;
1582*6777b538SAndroid Build Coastguard Worker }
1583*6777b538SAndroid Build Coastguard Worker
1584*6777b538SAndroid Build Coastguard Worker entry_ = std::move(new_entry_);
1585*6777b538SAndroid Build Coastguard Worker DCHECK_NE(response_.headers->response_code(), net::HTTP_NOT_MODIFIED);
1586*6777b538SAndroid Build Coastguard Worker DCHECK(entry_->CanTransactionWriteResponseHeaders(this, partial_ != nullptr,
1587*6777b538SAndroid Build Coastguard Worker false));
1588*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_WRITE_RESPONSE);
1589*6777b538SAndroid Build Coastguard Worker return OK;
1590*6777b538SAndroid Build Coastguard Worker }
1591*6777b538SAndroid Build Coastguard Worker
DoCacheReadResponse()1592*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheReadResponse() {
1593*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoCacheReadResponse",
1594*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1595*6777b538SAndroid Build Coastguard Worker DCHECK(entry_);
1596*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_READ_RESPONSE_COMPLETE);
1597*6777b538SAndroid Build Coastguard Worker
1598*6777b538SAndroid Build Coastguard Worker io_buf_len_ = entry_->GetEntry()->GetDataSize(kResponseInfoIndex);
1599*6777b538SAndroid Build Coastguard Worker read_buf_ = base::MakeRefCounted<IOBufferWithSize>(io_buf_len_);
1600*6777b538SAndroid Build Coastguard Worker
1601*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_INFO);
1602*6777b538SAndroid Build Coastguard Worker BeginDiskCacheAccessTimeCount();
1603*6777b538SAndroid Build Coastguard Worker return entry_->GetEntry()->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
1604*6777b538SAndroid Build Coastguard Worker io_buf_len_, io_callback_);
1605*6777b538SAndroid Build Coastguard Worker }
1606*6777b538SAndroid Build Coastguard Worker
DoCacheReadResponseComplete(int result)1607*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
1608*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
1609*6777b538SAndroid Build Coastguard Worker "net", "HttpCacheTransaction::DoCacheReadResponseComplete",
1610*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result, "io_buf_len", io_buf_len_);
1611*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO,
1612*6777b538SAndroid Build Coastguard Worker result);
1613*6777b538SAndroid Build Coastguard Worker EndDiskCacheAccessTimeCount(DiskCacheAccessType::kRead);
1614*6777b538SAndroid Build Coastguard Worker
1615*6777b538SAndroid Build Coastguard Worker // Record the time immediately before the cached response is parsed.
1616*6777b538SAndroid Build Coastguard Worker read_headers_since_ = TimeTicks::Now();
1617*6777b538SAndroid Build Coastguard Worker
1618*6777b538SAndroid Build Coastguard Worker if (result != io_buf_len_ ||
1619*6777b538SAndroid Build Coastguard Worker !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, &response_,
1620*6777b538SAndroid Build Coastguard Worker &truncated_)) {
1621*6777b538SAndroid Build Coastguard Worker return OnCacheReadError(result, true);
1622*6777b538SAndroid Build Coastguard Worker }
1623*6777b538SAndroid Build Coastguard Worker
1624*6777b538SAndroid Build Coastguard Worker // If the read response matches the clearing filter of FPS, doom the entry
1625*6777b538SAndroid Build Coastguard Worker // and restart transaction.
1626*6777b538SAndroid Build Coastguard Worker if (ShouldByPassCacheForFirstPartySets(initial_request_->fps_cache_filter,
1627*6777b538SAndroid Build Coastguard Worker response_.browser_run_id)) {
1628*6777b538SAndroid Build Coastguard Worker result = ERR_CACHE_ENTRY_NOT_SUITABLE;
1629*6777b538SAndroid Build Coastguard Worker return OnCacheReadError(result, true);
1630*6777b538SAndroid Build Coastguard Worker }
1631*6777b538SAndroid Build Coastguard Worker
1632*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/713354) Only get data size if there is no other transaction
1633*6777b538SAndroid Build Coastguard Worker // currently writing the response body due to the data race mentioned in the
1634*6777b538SAndroid Build Coastguard Worker // associated bug.
1635*6777b538SAndroid Build Coastguard Worker if (!entry_->IsWritingInProgress()) {
1636*6777b538SAndroid Build Coastguard Worker int current_size = entry_->GetEntry()->GetDataSize(kResponseContentIndex);
1637*6777b538SAndroid Build Coastguard Worker int64_t full_response_length = response_.headers->GetContentLength();
1638*6777b538SAndroid Build Coastguard Worker
1639*6777b538SAndroid Build Coastguard Worker // Some resources may have slipped in as truncated when they're not.
1640*6777b538SAndroid Build Coastguard Worker if (full_response_length == current_size) {
1641*6777b538SAndroid Build Coastguard Worker truncated_ = false;
1642*6777b538SAndroid Build Coastguard Worker }
1643*6777b538SAndroid Build Coastguard Worker
1644*6777b538SAndroid Build Coastguard Worker // The state machine's handling of StopCaching unfortunately doesn't deal
1645*6777b538SAndroid Build Coastguard Worker // well with resources that are larger than 2GB when there is a truncated or
1646*6777b538SAndroid Build Coastguard Worker // sparse cache entry. While the state machine is reworked to resolve this,
1647*6777b538SAndroid Build Coastguard Worker // the following logic is put in place to defer such requests to the
1648*6777b538SAndroid Build Coastguard Worker // network. The cache should not be storing multi gigabyte resources. See
1649*6777b538SAndroid Build Coastguard Worker // http://crbug.com/89567.
1650*6777b538SAndroid Build Coastguard Worker if ((truncated_ ||
1651*6777b538SAndroid Build Coastguard Worker response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT) &&
1652*6777b538SAndroid Build Coastguard Worker !range_requested_ &&
1653*6777b538SAndroid Build Coastguard Worker full_response_length > std::numeric_limits<int32_t>::max()) {
1654*6777b538SAndroid Build Coastguard Worker DCHECK(!partial_);
1655*6777b538SAndroid Build Coastguard Worker
1656*6777b538SAndroid Build Coastguard Worker // Doom the entry so that no other transaction gets added to this entry
1657*6777b538SAndroid Build Coastguard Worker // and avoid a race of not being able to check this condition because
1658*6777b538SAndroid Build Coastguard Worker // writing is in progress.
1659*6777b538SAndroid Build Coastguard Worker DoneWithEntry(false);
1660*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1661*6777b538SAndroid Build Coastguard Worker return OK;
1662*6777b538SAndroid Build Coastguard Worker }
1663*6777b538SAndroid Build Coastguard Worker }
1664*6777b538SAndroid Build Coastguard Worker
1665*6777b538SAndroid Build Coastguard Worker if (response_.restricted_prefetch &&
1666*6777b538SAndroid Build Coastguard Worker !(request_->load_flags & LOAD_CAN_USE_RESTRICTED_PREFETCH)) {
1667*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1668*6777b538SAndroid Build Coastguard Worker return OK;
1669*6777b538SAndroid Build Coastguard Worker }
1670*6777b538SAndroid Build Coastguard Worker
1671*6777b538SAndroid Build Coastguard Worker // When a restricted prefetch is reused, we lift its reuse restriction.
1672*6777b538SAndroid Build Coastguard Worker bool restricted_prefetch_reuse =
1673*6777b538SAndroid Build Coastguard Worker response_.restricted_prefetch &&
1674*6777b538SAndroid Build Coastguard Worker request_->load_flags & LOAD_CAN_USE_RESTRICTED_PREFETCH;
1675*6777b538SAndroid Build Coastguard Worker DCHECK(!restricted_prefetch_reuse || response_.unused_since_prefetch);
1676*6777b538SAndroid Build Coastguard Worker
1677*6777b538SAndroid Build Coastguard Worker if (response_.unused_since_prefetch !=
1678*6777b538SAndroid Build Coastguard Worker !!(request_->load_flags & LOAD_PREFETCH)) {
1679*6777b538SAndroid Build Coastguard Worker // Either this is the first use of an entry since it was prefetched XOR
1680*6777b538SAndroid Build Coastguard Worker // this is a prefetch. The value of response.unused_since_prefetch is
1681*6777b538SAndroid Build Coastguard Worker // valid for this transaction but the bit needs to be flipped in storage.
1682*6777b538SAndroid Build Coastguard Worker DCHECK(!updated_prefetch_response_);
1683*6777b538SAndroid Build Coastguard Worker updated_prefetch_response_ = std::make_unique<HttpResponseInfo>(response_);
1684*6777b538SAndroid Build Coastguard Worker updated_prefetch_response_->unused_since_prefetch =
1685*6777b538SAndroid Build Coastguard Worker !response_.unused_since_prefetch;
1686*6777b538SAndroid Build Coastguard Worker if (response_.restricted_prefetch &&
1687*6777b538SAndroid Build Coastguard Worker request_->load_flags & LOAD_CAN_USE_RESTRICTED_PREFETCH) {
1688*6777b538SAndroid Build Coastguard Worker updated_prefetch_response_->restricted_prefetch = false;
1689*6777b538SAndroid Build Coastguard Worker }
1690*6777b538SAndroid Build Coastguard Worker
1691*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_WRITE_UPDATED_PREFETCH_RESPONSE);
1692*6777b538SAndroid Build Coastguard Worker return OK;
1693*6777b538SAndroid Build Coastguard Worker }
1694*6777b538SAndroid Build Coastguard Worker
1695*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_DISPATCH_VALIDATION);
1696*6777b538SAndroid Build Coastguard Worker return OK;
1697*6777b538SAndroid Build Coastguard Worker }
1698*6777b538SAndroid Build Coastguard Worker
DoCacheWriteUpdatedPrefetchResponse(int result)1699*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheWriteUpdatedPrefetchResponse(int result) {
1700*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
1701*6777b538SAndroid Build Coastguard Worker "net", "HttpCacheTransaction::DoCacheWriteUpdatedPrefetchResponse",
1702*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
1703*6777b538SAndroid Build Coastguard Worker DCHECK(updated_prefetch_response_);
1704*6777b538SAndroid Build Coastguard Worker // TODO(jkarlin): If DoUpdateCachedResponse is also called for this
1705*6777b538SAndroid Build Coastguard Worker // transaction then metadata will be written to cache twice. If prefetching
1706*6777b538SAndroid Build Coastguard Worker // becomes more common, consider combining the writes.
1707*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_WRITE_UPDATED_PREFETCH_RESPONSE_COMPLETE);
1708*6777b538SAndroid Build Coastguard Worker return WriteResponseInfoToEntry(*updated_prefetch_response_.get(),
1709*6777b538SAndroid Build Coastguard Worker truncated_);
1710*6777b538SAndroid Build Coastguard Worker }
1711*6777b538SAndroid Build Coastguard Worker
DoCacheWriteUpdatedPrefetchResponseComplete(int result)1712*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheWriteUpdatedPrefetchResponseComplete(
1713*6777b538SAndroid Build Coastguard Worker int result) {
1714*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
1715*6777b538SAndroid Build Coastguard Worker "net",
1716*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoCacheWriteUpdatedPrefetchResponseComplete",
1717*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
1718*6777b538SAndroid Build Coastguard Worker updated_prefetch_response_.reset();
1719*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_DISPATCH_VALIDATION);
1720*6777b538SAndroid Build Coastguard Worker return OnWriteResponseInfoToEntryComplete(result);
1721*6777b538SAndroid Build Coastguard Worker }
1722*6777b538SAndroid Build Coastguard Worker
DoCacheDispatchValidation()1723*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheDispatchValidation() {
1724*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoCacheDispatchValidation",
1725*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1726*6777b538SAndroid Build Coastguard Worker if (!entry_) {
1727*6777b538SAndroid Build Coastguard Worker // Entry got destroyed when twiddling unused-since-prefetch bit.
1728*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
1729*6777b538SAndroid Build Coastguard Worker return OK;
1730*6777b538SAndroid Build Coastguard Worker }
1731*6777b538SAndroid Build Coastguard Worker
1732*6777b538SAndroid Build Coastguard Worker // We now have access to the cache entry.
1733*6777b538SAndroid Build Coastguard Worker //
1734*6777b538SAndroid Build Coastguard Worker // o if we are a reader for the transaction, then we can start reading the
1735*6777b538SAndroid Build Coastguard Worker // cache entry.
1736*6777b538SAndroid Build Coastguard Worker //
1737*6777b538SAndroid Build Coastguard Worker // o if we can read or write, then we should check if the cache entry needs
1738*6777b538SAndroid Build Coastguard Worker // to be validated and then issue a network request if needed or just read
1739*6777b538SAndroid Build Coastguard Worker // from the cache if the cache entry is already valid.
1740*6777b538SAndroid Build Coastguard Worker //
1741*6777b538SAndroid Build Coastguard Worker // o if we are set to UPDATE, then we are handling an externally
1742*6777b538SAndroid Build Coastguard Worker // conditionalized request (if-modified-since / if-none-match). We check
1743*6777b538SAndroid Build Coastguard Worker // if the request headers define a validation request.
1744*6777b538SAndroid Build Coastguard Worker //
1745*6777b538SAndroid Build Coastguard Worker int result = ERR_FAILED;
1746*6777b538SAndroid Build Coastguard Worker switch (mode_) {
1747*6777b538SAndroid Build Coastguard Worker case READ:
1748*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
1749*6777b538SAndroid Build Coastguard Worker result = BeginCacheRead();
1750*6777b538SAndroid Build Coastguard Worker break;
1751*6777b538SAndroid Build Coastguard Worker case READ_WRITE:
1752*6777b538SAndroid Build Coastguard Worker result = BeginPartialCacheValidation();
1753*6777b538SAndroid Build Coastguard Worker break;
1754*6777b538SAndroid Build Coastguard Worker case UPDATE:
1755*6777b538SAndroid Build Coastguard Worker result = BeginExternallyConditionalizedRequest();
1756*6777b538SAndroid Build Coastguard Worker break;
1757*6777b538SAndroid Build Coastguard Worker case WRITE:
1758*6777b538SAndroid Build Coastguard Worker default:
1759*6777b538SAndroid Build Coastguard Worker NOTREACHED();
1760*6777b538SAndroid Build Coastguard Worker }
1761*6777b538SAndroid Build Coastguard Worker return result;
1762*6777b538SAndroid Build Coastguard Worker }
1763*6777b538SAndroid Build Coastguard Worker
DoCacheQueryData()1764*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheQueryData() {
1765*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_QUERY_DATA_COMPLETE);
1766*6777b538SAndroid Build Coastguard Worker return entry_->GetEntry()->ReadyForSparseIO(io_callback_);
1767*6777b538SAndroid Build Coastguard Worker }
1768*6777b538SAndroid Build Coastguard Worker
DoCacheQueryDataComplete(int result)1769*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
1770*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, result);
1771*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
1772*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1773*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
1774*6777b538SAndroid Build Coastguard Worker }
1775*6777b538SAndroid Build Coastguard Worker
1776*6777b538SAndroid Build Coastguard Worker return ValidateEntryHeadersAndContinue();
1777*6777b538SAndroid Build Coastguard Worker }
1778*6777b538SAndroid Build Coastguard Worker
1779*6777b538SAndroid Build Coastguard Worker // We may end up here multiple times for a given request.
DoStartPartialCacheValidation()1780*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoStartPartialCacheValidation() {
1781*6777b538SAndroid Build Coastguard Worker if (mode_ == NONE) {
1782*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1783*6777b538SAndroid Build Coastguard Worker return OK;
1784*6777b538SAndroid Build Coastguard Worker }
1785*6777b538SAndroid Build Coastguard Worker
1786*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_COMPLETE_PARTIAL_CACHE_VALIDATION);
1787*6777b538SAndroid Build Coastguard Worker return partial_->ShouldValidateCache(entry_->GetEntry(), io_callback_);
1788*6777b538SAndroid Build Coastguard Worker }
1789*6777b538SAndroid Build Coastguard Worker
DoCompletePartialCacheValidation(int result)1790*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
1791*6777b538SAndroid Build Coastguard Worker if (!result && reading_) {
1792*6777b538SAndroid Build Coastguard Worker // This is the end of the request.
1793*6777b538SAndroid Build Coastguard Worker DoneWithEntry(true);
1794*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1795*6777b538SAndroid Build Coastguard Worker return result;
1796*6777b538SAndroid Build Coastguard Worker }
1797*6777b538SAndroid Build Coastguard Worker
1798*6777b538SAndroid Build Coastguard Worker if (result < 0) {
1799*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1800*6777b538SAndroid Build Coastguard Worker return result;
1801*6777b538SAndroid Build Coastguard Worker }
1802*6777b538SAndroid Build Coastguard Worker
1803*6777b538SAndroid Build Coastguard Worker partial_->PrepareCacheValidation(entry_->GetEntry(),
1804*6777b538SAndroid Build Coastguard Worker &custom_request_->extra_headers);
1805*6777b538SAndroid Build Coastguard Worker
1806*6777b538SAndroid Build Coastguard Worker if (reading_ && partial_->IsCurrentRangeCached()) {
1807*6777b538SAndroid Build Coastguard Worker // We're about to read a range of bytes from the cache. Signal it to the
1808*6777b538SAndroid Build Coastguard Worker // consumer through the "connected" callback.
1809*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CONNECTED_CALLBACK);
1810*6777b538SAndroid Build Coastguard Worker return OK;
1811*6777b538SAndroid Build Coastguard Worker }
1812*6777b538SAndroid Build Coastguard Worker
1813*6777b538SAndroid Build Coastguard Worker return BeginCacheValidation();
1814*6777b538SAndroid Build Coastguard Worker }
1815*6777b538SAndroid Build Coastguard Worker
DoCacheUpdateStaleWhileRevalidateTimeout()1816*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheUpdateStaleWhileRevalidateTimeout() {
1817*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
1818*6777b538SAndroid Build Coastguard Worker "net", "HttpCacheTransaction::DoCacheUpdateStaleWhileRevalidateTimeout",
1819*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1820*6777b538SAndroid Build Coastguard Worker response_.stale_revalidate_timeout =
1821*6777b538SAndroid Build Coastguard Worker cache_->clock_->Now() + kStaleRevalidateTimeout;
1822*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT_COMPLETE);
1823*6777b538SAndroid Build Coastguard Worker
1824*6777b538SAndroid Build Coastguard Worker // We shouldn't be using stale truncated entries; if we did, the false below
1825*6777b538SAndroid Build Coastguard Worker // would be wrong.
1826*6777b538SAndroid Build Coastguard Worker DCHECK(!truncated_);
1827*6777b538SAndroid Build Coastguard Worker return WriteResponseInfoToEntry(response_, false);
1828*6777b538SAndroid Build Coastguard Worker }
1829*6777b538SAndroid Build Coastguard Worker
DoCacheUpdateStaleWhileRevalidateTimeoutComplete(int result)1830*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheUpdateStaleWhileRevalidateTimeoutComplete(
1831*6777b538SAndroid Build Coastguard Worker int result) {
1832*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
1833*6777b538SAndroid Build Coastguard Worker "net",
1834*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoCacheUpdateStaleWhileRevalidateTimeoutComplete",
1835*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
1836*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
1837*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CONNECTED_CALLBACK);
1838*6777b538SAndroid Build Coastguard Worker return OnWriteResponseInfoToEntryComplete(result);
1839*6777b538SAndroid Build Coastguard Worker }
1840*6777b538SAndroid Build Coastguard Worker
DoSendRequest()1841*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoSendRequest() {
1842*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoSendRequest",
1843*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
1844*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ & WRITE || mode_ == NONE);
1845*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_.get());
1846*6777b538SAndroid Build Coastguard Worker
1847*6777b538SAndroid Build Coastguard Worker send_request_since_ = TimeTicks::Now();
1848*6777b538SAndroid Build Coastguard Worker
1849*6777b538SAndroid Build Coastguard Worker // Create a network transaction.
1850*6777b538SAndroid Build Coastguard Worker int rv =
1851*6777b538SAndroid Build Coastguard Worker cache_->network_layer_->CreateTransaction(priority_, &network_trans_);
1852*6777b538SAndroid Build Coastguard Worker
1853*6777b538SAndroid Build Coastguard Worker if (rv != OK) {
1854*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1855*6777b538SAndroid Build Coastguard Worker return rv;
1856*6777b538SAndroid Build Coastguard Worker }
1857*6777b538SAndroid Build Coastguard Worker
1858*6777b538SAndroid Build Coastguard Worker network_trans_->SetBeforeNetworkStartCallback(
1859*6777b538SAndroid Build Coastguard Worker std::move(before_network_start_callback_));
1860*6777b538SAndroid Build Coastguard Worker network_trans_->SetConnectedCallback(connected_callback_);
1861*6777b538SAndroid Build Coastguard Worker network_trans_->SetRequestHeadersCallback(request_headers_callback_);
1862*6777b538SAndroid Build Coastguard Worker network_trans_->SetEarlyResponseHeadersCallback(
1863*6777b538SAndroid Build Coastguard Worker early_response_headers_callback_);
1864*6777b538SAndroid Build Coastguard Worker network_trans_->SetResponseHeadersCallback(response_headers_callback_);
1865*6777b538SAndroid Build Coastguard Worker if (is_shared_dictionary_read_allowed_callback_) {
1866*6777b538SAndroid Build Coastguard Worker network_trans_->SetIsSharedDictionaryReadAllowedCallback(
1867*6777b538SAndroid Build Coastguard Worker is_shared_dictionary_read_allowed_callback_);
1868*6777b538SAndroid Build Coastguard Worker }
1869*6777b538SAndroid Build Coastguard Worker
1870*6777b538SAndroid Build Coastguard Worker // Old load timing information, if any, is now obsolete.
1871*6777b538SAndroid Build Coastguard Worker network_transaction_info_.old_network_trans_load_timing.reset();
1872*6777b538SAndroid Build Coastguard Worker network_transaction_info_.old_remote_endpoint = IPEndPoint();
1873*6777b538SAndroid Build Coastguard Worker
1874*6777b538SAndroid Build Coastguard Worker if (websocket_handshake_stream_base_create_helper_) {
1875*6777b538SAndroid Build Coastguard Worker network_trans_->SetWebSocketHandshakeStreamCreateHelper(
1876*6777b538SAndroid Build Coastguard Worker websocket_handshake_stream_base_create_helper_);
1877*6777b538SAndroid Build Coastguard Worker }
1878*6777b538SAndroid Build Coastguard Worker
1879*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST_COMPLETE);
1880*6777b538SAndroid Build Coastguard Worker rv = network_trans_->Start(request_, io_callback_, net_log_);
1881*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING && waiting_for_cache_io_) {
1882*6777b538SAndroid Build Coastguard Worker // queue the state transition until the HttpCache transaction completes
1883*6777b538SAndroid Build Coastguard Worker DCHECK(!pending_io_result_);
1884*6777b538SAndroid Build Coastguard Worker pending_io_result_ = rv;
1885*6777b538SAndroid Build Coastguard Worker rv = ERR_IO_PENDING;
1886*6777b538SAndroid Build Coastguard Worker }
1887*6777b538SAndroid Build Coastguard Worker return rv;
1888*6777b538SAndroid Build Coastguard Worker }
1889*6777b538SAndroid Build Coastguard Worker
DoSendRequestComplete(int result)1890*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoSendRequestComplete(int result) {
1891*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoSendRequestComplete",
1892*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result, "elapsed",
1893*6777b538SAndroid Build Coastguard Worker base::TimeTicks::Now() - send_request_since_);
1894*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
1895*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1896*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
1897*6777b538SAndroid Build Coastguard Worker }
1898*6777b538SAndroid Build Coastguard Worker
1899*6777b538SAndroid Build Coastguard Worker // If we tried to conditionalize the request and failed, we know
1900*6777b538SAndroid Build Coastguard Worker // we won't be reading from the cache after this point.
1901*6777b538SAndroid Build Coastguard Worker if (couldnt_conditionalize_request_) {
1902*6777b538SAndroid Build Coastguard Worker mode_ = WRITE;
1903*6777b538SAndroid Build Coastguard Worker }
1904*6777b538SAndroid Build Coastguard Worker
1905*6777b538SAndroid Build Coastguard Worker if (result == OK) {
1906*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SUCCESSFUL_SEND_REQUEST);
1907*6777b538SAndroid Build Coastguard Worker return OK;
1908*6777b538SAndroid Build Coastguard Worker }
1909*6777b538SAndroid Build Coastguard Worker
1910*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo* response = network_trans_->GetResponseInfo();
1911*6777b538SAndroid Build Coastguard Worker response_.network_accessed = response->network_accessed;
1912*6777b538SAndroid Build Coastguard Worker response_.was_fetched_via_proxy = response->was_fetched_via_proxy;
1913*6777b538SAndroid Build Coastguard Worker response_.proxy_chain = response->proxy_chain;
1914*6777b538SAndroid Build Coastguard Worker response_.restricted_prefetch = response->restricted_prefetch;
1915*6777b538SAndroid Build Coastguard Worker response_.resolve_error_info = response->resolve_error_info;
1916*6777b538SAndroid Build Coastguard Worker
1917*6777b538SAndroid Build Coastguard Worker // Do not record requests that have network errors or restarts.
1918*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
1919*6777b538SAndroid Build Coastguard Worker if (IsCertificateError(result)) {
1920*6777b538SAndroid Build Coastguard Worker // If we get a certificate error, then there is a certificate in ssl_info,
1921*6777b538SAndroid Build Coastguard Worker // so GetResponseInfo() should never return NULL here.
1922*6777b538SAndroid Build Coastguard Worker DCHECK(response);
1923*6777b538SAndroid Build Coastguard Worker response_.ssl_info = response->ssl_info;
1924*6777b538SAndroid Build Coastguard Worker } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
1925*6777b538SAndroid Build Coastguard Worker DCHECK(response);
1926*6777b538SAndroid Build Coastguard Worker response_.cert_request_info = response->cert_request_info;
1927*6777b538SAndroid Build Coastguard Worker } else if (result == ERR_INCONSISTENT_IP_ADDRESS_SPACE) {
1928*6777b538SAndroid Build Coastguard Worker DoomInconsistentEntry();
1929*6777b538SAndroid Build Coastguard Worker } else if (response_.was_cached) {
1930*6777b538SAndroid Build Coastguard Worker DoneWithEntry(/*entry_is_complete=*/true);
1931*6777b538SAndroid Build Coastguard Worker }
1932*6777b538SAndroid Build Coastguard Worker
1933*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1934*6777b538SAndroid Build Coastguard Worker return result;
1935*6777b538SAndroid Build Coastguard Worker }
1936*6777b538SAndroid Build Coastguard Worker
1937*6777b538SAndroid Build Coastguard Worker // We received the response headers and there is no error.
DoSuccessfulSendRequest()1938*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoSuccessfulSendRequest() {
1939*6777b538SAndroid Build Coastguard Worker DCHECK(!new_response_);
1940*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
1941*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoSuccessfulSendRequest",
1942*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "response_code",
1943*6777b538SAndroid Build Coastguard Worker new_response->headers->response_code());
1944*6777b538SAndroid Build Coastguard Worker
1945*6777b538SAndroid Build Coastguard Worker if (new_response->headers->response_code() == net::HTTP_UNAUTHORIZED ||
1946*6777b538SAndroid Build Coastguard Worker new_response->headers->response_code() ==
1947*6777b538SAndroid Build Coastguard Worker net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
1948*6777b538SAndroid Build Coastguard Worker SetAuthResponse(*new_response);
1949*6777b538SAndroid Build Coastguard Worker if (!reading_) {
1950*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1951*6777b538SAndroid Build Coastguard Worker return OK;
1952*6777b538SAndroid Build Coastguard Worker }
1953*6777b538SAndroid Build Coastguard Worker
1954*6777b538SAndroid Build Coastguard Worker // We initiated a second request the caller doesn't know about. We should be
1955*6777b538SAndroid Build Coastguard Worker // able to authenticate this request because we should have authenticated
1956*6777b538SAndroid Build Coastguard Worker // this URL moments ago.
1957*6777b538SAndroid Build Coastguard Worker if (IsReadyToRestartForAuth()) {
1958*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST_COMPLETE);
1959*6777b538SAndroid Build Coastguard Worker // In theory we should check to see if there are new cookies, but there
1960*6777b538SAndroid Build Coastguard Worker // is no way to do that from here.
1961*6777b538SAndroid Build Coastguard Worker return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_);
1962*6777b538SAndroid Build Coastguard Worker }
1963*6777b538SAndroid Build Coastguard Worker
1964*6777b538SAndroid Build Coastguard Worker // We have to perform cleanup at this point so that at least the next
1965*6777b538SAndroid Build Coastguard Worker // request can succeed. We do not retry at this point, because data
1966*6777b538SAndroid Build Coastguard Worker // has been read and we have no way to gather credentials. We would
1967*6777b538SAndroid Build Coastguard Worker // fail again, and potentially loop. This can happen if the credentials
1968*6777b538SAndroid Build Coastguard Worker // expire while chrome is suspended.
1969*6777b538SAndroid Build Coastguard Worker if (entry_) {
1970*6777b538SAndroid Build Coastguard Worker DoomPartialEntry(false);
1971*6777b538SAndroid Build Coastguard Worker }
1972*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
1973*6777b538SAndroid Build Coastguard Worker partial_.reset();
1974*6777b538SAndroid Build Coastguard Worker ResetNetworkTransaction();
1975*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
1976*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_AUTH_FAILURE_AFTER_READ;
1977*6777b538SAndroid Build Coastguard Worker }
1978*6777b538SAndroid Build Coastguard Worker
1979*6777b538SAndroid Build Coastguard Worker new_response_ = new_response;
1980*6777b538SAndroid Build Coastguard Worker if (!ValidatePartialResponse() && !auth_response_.headers.get()) {
1981*6777b538SAndroid Build Coastguard Worker // Something went wrong with this request and we have to restart it.
1982*6777b538SAndroid Build Coastguard Worker // If we have an authentication response, we are exposed to weird things
1983*6777b538SAndroid Build Coastguard Worker // hapenning if the user cancels the authentication before we receive
1984*6777b538SAndroid Build Coastguard Worker // the new response.
1985*6777b538SAndroid Build Coastguard Worker net_log_.AddEvent(NetLogEventType::HTTP_CACHE_RE_SEND_PARTIAL_REQUEST);
1986*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
1987*6777b538SAndroid Build Coastguard Worker SetResponse(HttpResponseInfo());
1988*6777b538SAndroid Build Coastguard Worker ResetNetworkTransaction();
1989*6777b538SAndroid Build Coastguard Worker new_response_ = nullptr;
1990*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
1991*6777b538SAndroid Build Coastguard Worker return OK;
1992*6777b538SAndroid Build Coastguard Worker }
1993*6777b538SAndroid Build Coastguard Worker
1994*6777b538SAndroid Build Coastguard Worker if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
1995*6777b538SAndroid Build Coastguard Worker // We have stored the full entry, but it changed and the server is
1996*6777b538SAndroid Build Coastguard Worker // sending a range. We have to delete the old entry.
1997*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
1998*6777b538SAndroid Build Coastguard Worker DoneWithEntry(false);
1999*6777b538SAndroid Build Coastguard Worker }
2000*6777b538SAndroid Build Coastguard Worker
2001*6777b538SAndroid Build Coastguard Worker if (mode_ == WRITE &&
2002*6777b538SAndroid Build Coastguard Worker cache_entry_status_ != CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) {
2003*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_NOT_IN_CACHE);
2004*6777b538SAndroid Build Coastguard Worker }
2005*6777b538SAndroid Build Coastguard Worker
2006*6777b538SAndroid Build Coastguard Worker // Invalidate any cached GET with a successful PUT, DELETE, or PATCH.
2007*6777b538SAndroid Build Coastguard Worker if (mode_ == WRITE &&
2008*6777b538SAndroid Build Coastguard Worker (method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH")) {
2009*6777b538SAndroid Build Coastguard Worker if (NonErrorResponse(new_response_->headers->response_code()) &&
2010*6777b538SAndroid Build Coastguard Worker (entry_ && !entry_->IsDoomed())) {
2011*6777b538SAndroid Build Coastguard Worker int ret = cache_->DoomEntry(cache_key_, nullptr);
2012*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, ret);
2013*6777b538SAndroid Build Coastguard Worker }
2014*6777b538SAndroid Build Coastguard Worker // Do not invalidate the entry if the request failed.
2015*6777b538SAndroid Build Coastguard Worker DoneWithEntry(true);
2016*6777b538SAndroid Build Coastguard Worker }
2017*6777b538SAndroid Build Coastguard Worker
2018*6777b538SAndroid Build Coastguard Worker // Invalidate any cached GET with a successful POST. If the network isolation
2019*6777b538SAndroid Build Coastguard Worker // key isn't populated with the split cache active, there will be nothing to
2020*6777b538SAndroid Build Coastguard Worker // invalidate in the cache.
2021*6777b538SAndroid Build Coastguard Worker if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) && method_ == "POST" &&
2022*6777b538SAndroid Build Coastguard Worker NonErrorResponse(new_response_->headers->response_code()) &&
2023*6777b538SAndroid Build Coastguard Worker (!HttpCache::IsSplitCacheEnabled() ||
2024*6777b538SAndroid Build Coastguard Worker request_->network_isolation_key.IsFullyPopulated())) {
2025*6777b538SAndroid Build Coastguard Worker cache_->DoomMainEntryForUrl(request_->url, request_->network_isolation_key,
2026*6777b538SAndroid Build Coastguard Worker request_->is_subframe_document_resource);
2027*6777b538SAndroid Build Coastguard Worker }
2028*6777b538SAndroid Build Coastguard Worker
2029*6777b538SAndroid Build Coastguard Worker if (new_response_->headers->response_code() ==
2030*6777b538SAndroid Build Coastguard Worker net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE &&
2031*6777b538SAndroid Build Coastguard Worker (method_ == "GET" || method_ == "POST")) {
2032*6777b538SAndroid Build Coastguard Worker // If there is an active entry it may be destroyed with this transaction.
2033*6777b538SAndroid Build Coastguard Worker SetResponse(*new_response_);
2034*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
2035*6777b538SAndroid Build Coastguard Worker return OK;
2036*6777b538SAndroid Build Coastguard Worker }
2037*6777b538SAndroid Build Coastguard Worker
2038*6777b538SAndroid Build Coastguard Worker // Are we expecting a response to a conditional query?
2039*6777b538SAndroid Build Coastguard Worker if (mode_ == READ_WRITE || mode_ == UPDATE) {
2040*6777b538SAndroid Build Coastguard Worker if (new_response->headers->response_code() == net::HTTP_NOT_MODIFIED ||
2041*6777b538SAndroid Build Coastguard Worker handling_206_) {
2042*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
2043*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_UPDATE_CACHED_RESPONSE);
2044*6777b538SAndroid Build Coastguard Worker return OK;
2045*6777b538SAndroid Build Coastguard Worker }
2046*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
2047*6777b538SAndroid Build Coastguard Worker mode_ = WRITE;
2048*6777b538SAndroid Build Coastguard Worker }
2049*6777b538SAndroid Build Coastguard Worker
2050*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_OVERWRITE_CACHED_RESPONSE);
2051*6777b538SAndroid Build Coastguard Worker return OK;
2052*6777b538SAndroid Build Coastguard Worker }
2053*6777b538SAndroid Build Coastguard Worker
2054*6777b538SAndroid Build Coastguard Worker // We received 304 or 206 and we want to update the cached response headers.
DoUpdateCachedResponse()2055*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoUpdateCachedResponse() {
2056*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoUpdateCachedResponse",
2057*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
2058*6777b538SAndroid Build Coastguard Worker int rv = OK;
2059*6777b538SAndroid Build Coastguard Worker // Update the cached response based on the headers and properties of
2060*6777b538SAndroid Build Coastguard Worker // new_response_.
2061*6777b538SAndroid Build Coastguard Worker response_.headers->Update(*new_response_->headers.get());
2062*6777b538SAndroid Build Coastguard Worker response_.stale_revalidate_timeout = base::Time();
2063*6777b538SAndroid Build Coastguard Worker response_.response_time = new_response_->response_time;
2064*6777b538SAndroid Build Coastguard Worker response_.request_time = new_response_->request_time;
2065*6777b538SAndroid Build Coastguard Worker response_.network_accessed = new_response_->network_accessed;
2066*6777b538SAndroid Build Coastguard Worker response_.unused_since_prefetch = new_response_->unused_since_prefetch;
2067*6777b538SAndroid Build Coastguard Worker response_.restricted_prefetch = new_response_->restricted_prefetch;
2068*6777b538SAndroid Build Coastguard Worker response_.ssl_info = new_response_->ssl_info;
2069*6777b538SAndroid Build Coastguard Worker response_.dns_aliases = new_response_->dns_aliases;
2070*6777b538SAndroid Build Coastguard Worker
2071*6777b538SAndroid Build Coastguard Worker // If the new response didn't have a vary header, we continue to use the
2072*6777b538SAndroid Build Coastguard Worker // header from the stored response per the effect of headers->Update().
2073*6777b538SAndroid Build Coastguard Worker // Update the data with the new/updated request headers.
2074*6777b538SAndroid Build Coastguard Worker response_.vary_data.Init(*request_, *response_.headers);
2075*6777b538SAndroid Build Coastguard Worker
2076*6777b538SAndroid Build Coastguard Worker if (ShouldDisableCaching(*response_.headers)) {
2077*6777b538SAndroid Build Coastguard Worker if (!entry_->IsDoomed()) {
2078*6777b538SAndroid Build Coastguard Worker int ret = cache_->DoomEntry(cache_key_, nullptr);
2079*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, ret);
2080*6777b538SAndroid Build Coastguard Worker }
2081*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
2082*6777b538SAndroid Build Coastguard Worker } else {
2083*6777b538SAndroid Build Coastguard Worker // If we are already reading, we already updated the headers for this
2084*6777b538SAndroid Build Coastguard Worker // request; doing it again will change Content-Length.
2085*6777b538SAndroid Build Coastguard Worker if (!reading_) {
2086*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_WRITE_UPDATED_RESPONSE);
2087*6777b538SAndroid Build Coastguard Worker rv = OK;
2088*6777b538SAndroid Build Coastguard Worker } else {
2089*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
2090*6777b538SAndroid Build Coastguard Worker }
2091*6777b538SAndroid Build Coastguard Worker }
2092*6777b538SAndroid Build Coastguard Worker
2093*6777b538SAndroid Build Coastguard Worker return rv;
2094*6777b538SAndroid Build Coastguard Worker }
2095*6777b538SAndroid Build Coastguard Worker
DoCacheWriteUpdatedResponse()2096*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheWriteUpdatedResponse() {
2097*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net",
2098*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoCacheWriteUpdatedResponse",
2099*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
2100*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE);
2101*6777b538SAndroid Build Coastguard Worker return WriteResponseInfoToEntry(response_, false);
2102*6777b538SAndroid Build Coastguard Worker }
2103*6777b538SAndroid Build Coastguard Worker
DoCacheWriteUpdatedResponseComplete(int result)2104*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) {
2105*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
2106*6777b538SAndroid Build Coastguard Worker "net", "HttpCacheTransaction::DoCacheWriteUpdatedResponseComplete",
2107*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2108*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_UPDATE_CACHED_RESPONSE_COMPLETE);
2109*6777b538SAndroid Build Coastguard Worker return OnWriteResponseInfoToEntryComplete(result);
2110*6777b538SAndroid Build Coastguard Worker }
2111*6777b538SAndroid Build Coastguard Worker
DoUpdateCachedResponseComplete(int result)2112*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
2113*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net",
2114*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoUpdateCachedResponseComplete",
2115*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2116*6777b538SAndroid Build Coastguard Worker if (mode_ == UPDATE) {
2117*6777b538SAndroid Build Coastguard Worker DCHECK(!handling_206_);
2118*6777b538SAndroid Build Coastguard Worker // We got a "not modified" response and already updated the corresponding
2119*6777b538SAndroid Build Coastguard Worker // cache entry above.
2120*6777b538SAndroid Build Coastguard Worker //
2121*6777b538SAndroid Build Coastguard Worker // By stopping to write to the cache now, we make sure that the 304 rather
2122*6777b538SAndroid Build Coastguard Worker // than the cached 200 response, is what will be returned to the user.
2123*6777b538SAndroid Build Coastguard Worker UpdateSecurityHeadersBeforeForwarding();
2124*6777b538SAndroid Build Coastguard Worker DoneWithEntry(true);
2125*6777b538SAndroid Build Coastguard Worker } else if (entry_ && !handling_206_) {
2126*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(READ_WRITE, mode_);
2127*6777b538SAndroid Build Coastguard Worker if ((!partial_ && !entry_->IsWritingInProgress()) ||
2128*6777b538SAndroid Build Coastguard Worker (partial_ && partial_->IsLastRange())) {
2129*6777b538SAndroid Build Coastguard Worker mode_ = READ;
2130*6777b538SAndroid Build Coastguard Worker }
2131*6777b538SAndroid Build Coastguard Worker // We no longer need the network transaction, so destroy it.
2132*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
2133*6777b538SAndroid Build Coastguard Worker ResetNetworkTransaction();
2134*6777b538SAndroid Build Coastguard Worker }
2135*6777b538SAndroid Build Coastguard Worker } else if (entry_ && handling_206_ && truncated_ &&
2136*6777b538SAndroid Build Coastguard Worker partial_->initial_validation()) {
2137*6777b538SAndroid Build Coastguard Worker // We just finished the validation of a truncated entry, and the server
2138*6777b538SAndroid Build Coastguard Worker // is willing to resume the operation. Now we go back and start serving
2139*6777b538SAndroid Build Coastguard Worker // the first part to the user.
2140*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
2141*6777b538SAndroid Build Coastguard Worker ResetNetworkTransaction();
2142*6777b538SAndroid Build Coastguard Worker }
2143*6777b538SAndroid Build Coastguard Worker new_response_ = nullptr;
2144*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
2145*6777b538SAndroid Build Coastguard Worker partial_->SetRangeToStartDownload();
2146*6777b538SAndroid Build Coastguard Worker return OK;
2147*6777b538SAndroid Build Coastguard Worker }
2148*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_OVERWRITE_CACHED_RESPONSE);
2149*6777b538SAndroid Build Coastguard Worker return OK;
2150*6777b538SAndroid Build Coastguard Worker }
2151*6777b538SAndroid Build Coastguard Worker
DoOverwriteCachedResponse()2152*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoOverwriteCachedResponse() {
2153*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoOverwriteCachedResponse",
2154*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
2155*6777b538SAndroid Build Coastguard Worker if (mode_ & READ) {
2156*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
2157*6777b538SAndroid Build Coastguard Worker return OK;
2158*6777b538SAndroid Build Coastguard Worker }
2159*6777b538SAndroid Build Coastguard Worker
2160*6777b538SAndroid Build Coastguard Worker // We change the value of Content-Length for partial content.
2161*6777b538SAndroid Build Coastguard Worker if (handling_206_ && partial_) {
2162*6777b538SAndroid Build Coastguard Worker partial_->FixContentLength(new_response_->headers.get());
2163*6777b538SAndroid Build Coastguard Worker }
2164*6777b538SAndroid Build Coastguard Worker
2165*6777b538SAndroid Build Coastguard Worker SetResponse(*new_response_);
2166*6777b538SAndroid Build Coastguard Worker
2167*6777b538SAndroid Build Coastguard Worker if (method_ == "HEAD") {
2168*6777b538SAndroid Build Coastguard Worker // This response is replacing the cached one.
2169*6777b538SAndroid Build Coastguard Worker DoneWithEntry(false);
2170*6777b538SAndroid Build Coastguard Worker new_response_ = nullptr;
2171*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
2172*6777b538SAndroid Build Coastguard Worker return OK;
2173*6777b538SAndroid Build Coastguard Worker }
2174*6777b538SAndroid Build Coastguard Worker
2175*6777b538SAndroid Build Coastguard Worker if (handling_206_ && !CanResume(false)) {
2176*6777b538SAndroid Build Coastguard Worker // There is no point in storing this resource because it will never be used.
2177*6777b538SAndroid Build Coastguard Worker // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries.
2178*6777b538SAndroid Build Coastguard Worker DoneWithEntry(false);
2179*6777b538SAndroid Build Coastguard Worker if (partial_) {
2180*6777b538SAndroid Build Coastguard Worker partial_->FixResponseHeaders(response_.headers.get(), true);
2181*6777b538SAndroid Build Coastguard Worker }
2182*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
2183*6777b538SAndroid Build Coastguard Worker return OK;
2184*6777b538SAndroid Build Coastguard Worker }
2185*6777b538SAndroid Build Coastguard Worker // Mark the response with browser_run_id before it gets written.
2186*6777b538SAndroid Build Coastguard Worker if (initial_request_->browser_run_id.has_value()) {
2187*6777b538SAndroid Build Coastguard Worker response_.browser_run_id = initial_request_->browser_run_id;
2188*6777b538SAndroid Build Coastguard Worker }
2189*6777b538SAndroid Build Coastguard Worker
2190*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_WRITE_RESPONSE);
2191*6777b538SAndroid Build Coastguard Worker return OK;
2192*6777b538SAndroid Build Coastguard Worker }
2193*6777b538SAndroid Build Coastguard Worker
DoCacheWriteResponse()2194*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheWriteResponse() {
2195*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoCacheWriteResponse",
2196*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
2197*6777b538SAndroid Build Coastguard Worker DCHECK(response_.headers);
2198*6777b538SAndroid Build Coastguard Worker // Invalidate any current entry with a successful response if this transaction
2199*6777b538SAndroid Build Coastguard Worker // cannot write to this entry. This transaction then continues to read from
2200*6777b538SAndroid Build Coastguard Worker // the network without writing to the backend.
2201*6777b538SAndroid Build Coastguard Worker bool is_match = response_.headers->response_code() == net::HTTP_NOT_MODIFIED;
2202*6777b538SAndroid Build Coastguard Worker if (entry_ && !entry_->CanTransactionWriteResponseHeaders(
2203*6777b538SAndroid Build Coastguard Worker this, partial_ != nullptr, is_match)) {
2204*6777b538SAndroid Build Coastguard Worker done_headers_create_new_entry_ = true;
2205*6777b538SAndroid Build Coastguard Worker
2206*6777b538SAndroid Build Coastguard Worker // The transaction needs to overwrite this response. Doom the current entry,
2207*6777b538SAndroid Build Coastguard Worker // create a new one (by going to STATE_INIT_ENTRY), and then jump straight
2208*6777b538SAndroid Build Coastguard Worker // to writing out the response, bypassing the headers checks. The mode_ is
2209*6777b538SAndroid Build Coastguard Worker // set to WRITE in order to doom any other existing entries that might exist
2210*6777b538SAndroid Build Coastguard Worker // so that this transaction can go straight to writing a response.
2211*6777b538SAndroid Build Coastguard Worker mode_ = WRITE;
2212*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_INIT_ENTRY);
2213*6777b538SAndroid Build Coastguard Worker cache_->DoomEntryValidationNoMatch(std::move(entry_));
2214*6777b538SAndroid Build Coastguard Worker entry_.reset();
2215*6777b538SAndroid Build Coastguard Worker return OK;
2216*6777b538SAndroid Build Coastguard Worker }
2217*6777b538SAndroid Build Coastguard Worker
2218*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_WRITE_RESPONSE_COMPLETE);
2219*6777b538SAndroid Build Coastguard Worker return WriteResponseInfoToEntry(response_, truncated_);
2220*6777b538SAndroid Build Coastguard Worker }
2221*6777b538SAndroid Build Coastguard Worker
DoCacheWriteResponseComplete(int result)2222*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
2223*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net",
2224*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoCacheWriteResponseComplete",
2225*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2226*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_TRUNCATE_CACHED_DATA);
2227*6777b538SAndroid Build Coastguard Worker return OnWriteResponseInfoToEntryComplete(result);
2228*6777b538SAndroid Build Coastguard Worker }
2229*6777b538SAndroid Build Coastguard Worker
DoTruncateCachedData()2230*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoTruncateCachedData() {
2231*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoTruncateCachedData",
2232*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
2233*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_TRUNCATE_CACHED_DATA_COMPLETE);
2234*6777b538SAndroid Build Coastguard Worker if (!entry_) {
2235*6777b538SAndroid Build Coastguard Worker return OK;
2236*6777b538SAndroid Build Coastguard Worker }
2237*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
2238*6777b538SAndroid Build Coastguard Worker BeginDiskCacheAccessTimeCount();
2239*6777b538SAndroid Build Coastguard Worker // Truncate the stream.
2240*6777b538SAndroid Build Coastguard Worker return entry_->GetEntry()->WriteData(kResponseContentIndex, /*offset=*/0,
2241*6777b538SAndroid Build Coastguard Worker /*buf=*/nullptr, /*buf_len=*/0,
2242*6777b538SAndroid Build Coastguard Worker io_callback_, /*truncate=*/true);
2243*6777b538SAndroid Build Coastguard Worker }
2244*6777b538SAndroid Build Coastguard Worker
DoTruncateCachedDataComplete(int result)2245*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) {
2246*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net",
2247*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoTruncateCachedDataComplete",
2248*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2249*6777b538SAndroid Build Coastguard Worker EndDiskCacheAccessTimeCount(DiskCacheAccessType::kWrite);
2250*6777b538SAndroid Build Coastguard Worker if (entry_) {
2251*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
2252*6777b538SAndroid Build Coastguard Worker result);
2253*6777b538SAndroid Build Coastguard Worker }
2254*6777b538SAndroid Build Coastguard Worker
2255*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
2256*6777b538SAndroid Build Coastguard Worker return OK;
2257*6777b538SAndroid Build Coastguard Worker }
2258*6777b538SAndroid Build Coastguard Worker
DoPartialHeadersReceived()2259*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoPartialHeadersReceived() {
2260*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoPartialHeadersReceived",
2261*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
2262*6777b538SAndroid Build Coastguard Worker new_response_ = nullptr;
2263*6777b538SAndroid Build Coastguard Worker
2264*6777b538SAndroid Build Coastguard Worker if (partial_ && mode_ != NONE && !reading_) {
2265*6777b538SAndroid Build Coastguard Worker // We are about to return the headers for a byte-range request to the user,
2266*6777b538SAndroid Build Coastguard Worker // so let's fix them.
2267*6777b538SAndroid Build Coastguard Worker partial_->FixResponseHeaders(response_.headers.get(), true);
2268*6777b538SAndroid Build Coastguard Worker }
2269*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
2270*6777b538SAndroid Build Coastguard Worker return OK;
2271*6777b538SAndroid Build Coastguard Worker }
2272*6777b538SAndroid Build Coastguard Worker
DoHeadersPhaseCannotProceed(int result)2273*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoHeadersPhaseCannotProceed(int result) {
2274*6777b538SAndroid Build Coastguard Worker // If its the Start state machine and it cannot proceed due to a cache
2275*6777b538SAndroid Build Coastguard Worker // failure, restart this transaction.
2276*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
2277*6777b538SAndroid Build Coastguard Worker
2278*6777b538SAndroid Build Coastguard Worker // Reset before invoking SetRequest() which can reset the request info sent to
2279*6777b538SAndroid Build Coastguard Worker // network transaction.
2280*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
2281*6777b538SAndroid Build Coastguard Worker network_trans_.reset();
2282*6777b538SAndroid Build Coastguard Worker }
2283*6777b538SAndroid Build Coastguard Worker
2284*6777b538SAndroid Build Coastguard Worker new_response_ = nullptr;
2285*6777b538SAndroid Build Coastguard Worker
2286*6777b538SAndroid Build Coastguard Worker SetRequest(net_log_);
2287*6777b538SAndroid Build Coastguard Worker
2288*6777b538SAndroid Build Coastguard Worker entry_.reset();
2289*6777b538SAndroid Build Coastguard Worker new_entry_.reset();
2290*6777b538SAndroid Build Coastguard Worker last_disk_cache_access_start_time_ = TimeTicks();
2291*6777b538SAndroid Build Coastguard Worker
2292*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/1219402): This should probably clear `response_`,
2293*6777b538SAndroid Build Coastguard Worker // too, once things are fixed so it's safe to do so.
2294*6777b538SAndroid Build Coastguard Worker
2295*6777b538SAndroid Build Coastguard Worker // Bypass the cache for timeout scenario.
2296*6777b538SAndroid Build Coastguard Worker if (result == ERR_CACHE_LOCK_TIMEOUT) {
2297*6777b538SAndroid Build Coastguard Worker effective_load_flags_ |= LOAD_DISABLE_CACHE;
2298*6777b538SAndroid Build Coastguard Worker }
2299*6777b538SAndroid Build Coastguard Worker
2300*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_GET_BACKEND);
2301*6777b538SAndroid Build Coastguard Worker return OK;
2302*6777b538SAndroid Build Coastguard Worker }
2303*6777b538SAndroid Build Coastguard Worker
DoFinishHeaders(int result)2304*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoFinishHeaders(int result) {
2305*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoFinishHeaders",
2306*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2307*6777b538SAndroid Build Coastguard Worker if (!cache_.get() || !entry_ || result != OK) {
2308*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2309*6777b538SAndroid Build Coastguard Worker return result;
2310*6777b538SAndroid Build Coastguard Worker }
2311*6777b538SAndroid Build Coastguard Worker
2312*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS_COMPLETE);
2313*6777b538SAndroid Build Coastguard Worker
2314*6777b538SAndroid Build Coastguard Worker // If it was an auth failure, this transaction should continue to be
2315*6777b538SAndroid Build Coastguard Worker // headers_transaction till consumer takes an action, so no need to do
2316*6777b538SAndroid Build Coastguard Worker // anything now.
2317*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/740947). See the issue for a suggestion for cleaning the
2318*6777b538SAndroid Build Coastguard Worker // state machine to be able to remove this condition.
2319*6777b538SAndroid Build Coastguard Worker if (auth_response_.headers.get()) {
2320*6777b538SAndroid Build Coastguard Worker return OK;
2321*6777b538SAndroid Build Coastguard Worker }
2322*6777b538SAndroid Build Coastguard Worker
2323*6777b538SAndroid Build Coastguard Worker // If the transaction needs to wait because another transaction is still
2324*6777b538SAndroid Build Coastguard Worker // writing the response body, it will return ERR_IO_PENDING now and the
2325*6777b538SAndroid Build Coastguard Worker // cache_io_callback_ will be invoked when the wait is done.
2326*6777b538SAndroid Build Coastguard Worker int rv = cache_->DoneWithResponseHeaders(entry_, this, partial_ != nullptr);
2327*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_ || rv == OK) << "Expected OK, but got " << rv;
2328*6777b538SAndroid Build Coastguard Worker
2329*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
2330*6777b538SAndroid Build Coastguard Worker DCHECK(entry_lock_waiting_since_.is_null());
2331*6777b538SAndroid Build Coastguard Worker entry_lock_waiting_since_ = TimeTicks::Now();
2332*6777b538SAndroid Build Coastguard Worker AddCacheLockTimeoutHandler(entry_.get());
2333*6777b538SAndroid Build Coastguard Worker }
2334*6777b538SAndroid Build Coastguard Worker return rv;
2335*6777b538SAndroid Build Coastguard Worker }
2336*6777b538SAndroid Build Coastguard Worker
DoFinishHeadersComplete(int rv)2337*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoFinishHeadersComplete(int rv) {
2338*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoFinishHeadersComplete",
2339*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", rv);
2340*6777b538SAndroid Build Coastguard Worker entry_lock_waiting_since_ = TimeTicks();
2341*6777b538SAndroid Build Coastguard Worker if (rv == ERR_CACHE_RACE || rv == ERR_CACHE_LOCK_TIMEOUT) {
2342*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
2343*6777b538SAndroid Build Coastguard Worker return rv;
2344*6777b538SAndroid Build Coastguard Worker }
2345*6777b538SAndroid Build Coastguard Worker
2346*6777b538SAndroid Build Coastguard Worker if (network_trans_ && InWriters()) {
2347*6777b538SAndroid Build Coastguard Worker entry_->writers()->SetNetworkTransaction(this, std::move(network_trans_));
2348*6777b538SAndroid Build Coastguard Worker moved_network_transaction_to_writers_ = true;
2349*6777b538SAndroid Build Coastguard Worker }
2350*6777b538SAndroid Build Coastguard Worker
2351*6777b538SAndroid Build Coastguard Worker // If already reading, that means it is a partial request coming back to the
2352*6777b538SAndroid Build Coastguard Worker // headers phase, continue to the appropriate reading state.
2353*6777b538SAndroid Build Coastguard Worker if (reading_) {
2354*6777b538SAndroid Build Coastguard Worker int reading_state_rv = TransitionToReadingState();
2355*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, reading_state_rv);
2356*6777b538SAndroid Build Coastguard Worker return OK;
2357*6777b538SAndroid Build Coastguard Worker }
2358*6777b538SAndroid Build Coastguard Worker
2359*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2360*6777b538SAndroid Build Coastguard Worker return rv;
2361*6777b538SAndroid Build Coastguard Worker }
2362*6777b538SAndroid Build Coastguard Worker
DoNetworkReadCacheWrite()2363*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoNetworkReadCacheWrite() {
2364*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoNetworkReadCacheWrite",
2365*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "read_offset", read_offset_,
2366*6777b538SAndroid Build Coastguard Worker "read_buf_len", read_buf_len_);
2367*6777b538SAndroid Build Coastguard Worker DCHECK(InWriters());
2368*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NETWORK_READ_CACHE_WRITE_COMPLETE);
2369*6777b538SAndroid Build Coastguard Worker return entry_->writers()->Read(read_buf_, read_buf_len_, io_callback_, this);
2370*6777b538SAndroid Build Coastguard Worker }
2371*6777b538SAndroid Build Coastguard Worker
DoNetworkReadCacheWriteComplete(int result)2372*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoNetworkReadCacheWriteComplete(int result) {
2373*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net",
2374*6777b538SAndroid Build Coastguard Worker "HttpCacheTransaction::DoNetworkReadCacheWriteComplete",
2375*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2376*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
2377*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2378*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
2379*6777b538SAndroid Build Coastguard Worker }
2380*6777b538SAndroid Build Coastguard Worker // |result| will be error code in case of network read failure and |this|
2381*6777b538SAndroid Build Coastguard Worker // cannot proceed further, so set entry_ to null. |result| will not be error
2382*6777b538SAndroid Build Coastguard Worker // in case of cache write failure since |this| can continue to read from the
2383*6777b538SAndroid Build Coastguard Worker // network. If response is completed, then also set entry to null.
2384*6777b538SAndroid Build Coastguard Worker if (result < 0) {
2385*6777b538SAndroid Build Coastguard Worker // We should have discovered this error in WriterAboutToBeRemovedFromEntry
2386*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(result, shared_writing_error_);
2387*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(NONE, mode_);
2388*6777b538SAndroid Build Coastguard Worker DCHECK(!entry_);
2389*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2390*6777b538SAndroid Build Coastguard Worker return result;
2391*6777b538SAndroid Build Coastguard Worker }
2392*6777b538SAndroid Build Coastguard Worker
2393*6777b538SAndroid Build Coastguard Worker if (partial_) {
2394*6777b538SAndroid Build Coastguard Worker return DoPartialNetworkReadCompleted(result);
2395*6777b538SAndroid Build Coastguard Worker }
2396*6777b538SAndroid Build Coastguard Worker
2397*6777b538SAndroid Build Coastguard Worker if (result == 0) {
2398*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(NONE, mode_);
2399*6777b538SAndroid Build Coastguard Worker DCHECK(!entry_);
2400*6777b538SAndroid Build Coastguard Worker } else {
2401*6777b538SAndroid Build Coastguard Worker read_offset_ += result;
2402*6777b538SAndroid Build Coastguard Worker }
2403*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2404*6777b538SAndroid Build Coastguard Worker return result;
2405*6777b538SAndroid Build Coastguard Worker }
2406*6777b538SAndroid Build Coastguard Worker
DoPartialNetworkReadCompleted(int result)2407*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
2408*6777b538SAndroid Build Coastguard Worker DCHECK(partial_);
2409*6777b538SAndroid Build Coastguard Worker
2410*6777b538SAndroid Build Coastguard Worker // Go to the next range if nothing returned or return the result.
2411*6777b538SAndroid Build Coastguard Worker // TODO(shivanisha) Simplify this condition if possible. It was introduced
2412*6777b538SAndroid Build Coastguard Worker // in https://codereview.chromium.org/545101
2413*6777b538SAndroid Build Coastguard Worker if (result != 0 || truncated_ ||
2414*6777b538SAndroid Build Coastguard Worker !(partial_->IsLastRange() || mode_ == WRITE)) {
2415*6777b538SAndroid Build Coastguard Worker partial_->OnNetworkReadCompleted(result);
2416*6777b538SAndroid Build Coastguard Worker
2417*6777b538SAndroid Build Coastguard Worker if (result == 0) {
2418*6777b538SAndroid Build Coastguard Worker // We need to move on to the next range.
2419*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
2420*6777b538SAndroid Build Coastguard Worker ResetNetworkTransaction();
2421*6777b538SAndroid Build Coastguard Worker } else if (InWriters() && entry_->writers()->network_transaction()) {
2422*6777b538SAndroid Build Coastguard Worker SaveNetworkTransactionInfo(*(entry_->writers()->network_transaction()));
2423*6777b538SAndroid Build Coastguard Worker entry_->writers()->ResetNetworkTransaction();
2424*6777b538SAndroid Build Coastguard Worker }
2425*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
2426*6777b538SAndroid Build Coastguard Worker } else {
2427*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2428*6777b538SAndroid Build Coastguard Worker }
2429*6777b538SAndroid Build Coastguard Worker return result;
2430*6777b538SAndroid Build Coastguard Worker }
2431*6777b538SAndroid Build Coastguard Worker
2432*6777b538SAndroid Build Coastguard Worker // Request completed.
2433*6777b538SAndroid Build Coastguard Worker if (result == 0) {
2434*6777b538SAndroid Build Coastguard Worker DoneWithEntry(true);
2435*6777b538SAndroid Build Coastguard Worker }
2436*6777b538SAndroid Build Coastguard Worker
2437*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2438*6777b538SAndroid Build Coastguard Worker return result;
2439*6777b538SAndroid Build Coastguard Worker }
2440*6777b538SAndroid Build Coastguard Worker
DoNetworkRead()2441*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoNetworkRead() {
2442*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoNetworkRead",
2443*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "read_offset", read_offset_,
2444*6777b538SAndroid Build Coastguard Worker "read_buf_len", read_buf_len_);
2445*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NETWORK_READ_COMPLETE);
2446*6777b538SAndroid Build Coastguard Worker return network_trans_->Read(read_buf_.get(), read_buf_len_, io_callback_);
2447*6777b538SAndroid Build Coastguard Worker }
2448*6777b538SAndroid Build Coastguard Worker
DoNetworkReadComplete(int result)2449*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoNetworkReadComplete(int result) {
2450*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoNetworkReadComplete",
2451*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2452*6777b538SAndroid Build Coastguard Worker
2453*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
2454*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2455*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
2456*6777b538SAndroid Build Coastguard Worker }
2457*6777b538SAndroid Build Coastguard Worker
2458*6777b538SAndroid Build Coastguard Worker if (partial_) {
2459*6777b538SAndroid Build Coastguard Worker return DoPartialNetworkReadCompleted(result);
2460*6777b538SAndroid Build Coastguard Worker }
2461*6777b538SAndroid Build Coastguard Worker
2462*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2463*6777b538SAndroid Build Coastguard Worker return result;
2464*6777b538SAndroid Build Coastguard Worker }
2465*6777b538SAndroid Build Coastguard Worker
DoCacheReadData()2466*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheReadData() {
2467*6777b538SAndroid Build Coastguard Worker if (entry_) {
2468*6777b538SAndroid Build Coastguard Worker DCHECK(InWriters() || entry_->TransactionInReaders(this));
2469*6777b538SAndroid Build Coastguard Worker }
2470*6777b538SAndroid Build Coastguard Worker
2471*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoCacheReadData",
2472*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "read_offset", read_offset_,
2473*6777b538SAndroid Build Coastguard Worker "read_buf_len", read_buf_len_);
2474*6777b538SAndroid Build Coastguard Worker
2475*6777b538SAndroid Build Coastguard Worker if (method_ == "HEAD") {
2476*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2477*6777b538SAndroid Build Coastguard Worker return 0;
2478*6777b538SAndroid Build Coastguard Worker }
2479*6777b538SAndroid Build Coastguard Worker
2480*6777b538SAndroid Build Coastguard Worker DCHECK(entry_);
2481*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_READ_DATA_COMPLETE);
2482*6777b538SAndroid Build Coastguard Worker
2483*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA);
2484*6777b538SAndroid Build Coastguard Worker if (partial_) {
2485*6777b538SAndroid Build Coastguard Worker return partial_->CacheRead(entry_->GetEntry(), read_buf_.get(),
2486*6777b538SAndroid Build Coastguard Worker read_buf_len_, io_callback_);
2487*6777b538SAndroid Build Coastguard Worker }
2488*6777b538SAndroid Build Coastguard Worker
2489*6777b538SAndroid Build Coastguard Worker BeginDiskCacheAccessTimeCount();
2490*6777b538SAndroid Build Coastguard Worker return entry_->GetEntry()->ReadData(kResponseContentIndex, read_offset_,
2491*6777b538SAndroid Build Coastguard Worker read_buf_.get(), read_buf_len_,
2492*6777b538SAndroid Build Coastguard Worker io_callback_);
2493*6777b538SAndroid Build Coastguard Worker }
2494*6777b538SAndroid Build Coastguard Worker
DoCacheReadDataComplete(int result)2495*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
2496*6777b538SAndroid Build Coastguard Worker EndDiskCacheAccessTimeCount(DiskCacheAccessType::kRead);
2497*6777b538SAndroid Build Coastguard Worker if (entry_) {
2498*6777b538SAndroid Build Coastguard Worker DCHECK(InWriters() || entry_->TransactionInReaders(this));
2499*6777b538SAndroid Build Coastguard Worker }
2500*6777b538SAndroid Build Coastguard Worker
2501*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoCacheReadDataComplete",
2502*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
2503*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_DATA,
2504*6777b538SAndroid Build Coastguard Worker result);
2505*6777b538SAndroid Build Coastguard Worker
2506*6777b538SAndroid Build Coastguard Worker if (!cache_.get()) {
2507*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2508*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
2509*6777b538SAndroid Build Coastguard Worker }
2510*6777b538SAndroid Build Coastguard Worker
2511*6777b538SAndroid Build Coastguard Worker if (partial_) {
2512*6777b538SAndroid Build Coastguard Worker // Partial requests are confusing to report in histograms because they may
2513*6777b538SAndroid Build Coastguard Worker // have multiple underlying requests.
2514*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
2515*6777b538SAndroid Build Coastguard Worker return DoPartialCacheReadCompleted(result);
2516*6777b538SAndroid Build Coastguard Worker }
2517*6777b538SAndroid Build Coastguard Worker
2518*6777b538SAndroid Build Coastguard Worker if (result > 0) {
2519*6777b538SAndroid Build Coastguard Worker read_offset_ += result;
2520*6777b538SAndroid Build Coastguard Worker } else if (result == 0) { // End of file.
2521*6777b538SAndroid Build Coastguard Worker DoneWithEntry(true);
2522*6777b538SAndroid Build Coastguard Worker } else {
2523*6777b538SAndroid Build Coastguard Worker return OnCacheReadError(result, false);
2524*6777b538SAndroid Build Coastguard Worker }
2525*6777b538SAndroid Build Coastguard Worker
2526*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
2527*6777b538SAndroid Build Coastguard Worker return result;
2528*6777b538SAndroid Build Coastguard Worker }
2529*6777b538SAndroid Build Coastguard Worker
2530*6777b538SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2531*6777b538SAndroid Build Coastguard Worker
SetRequest(const NetLogWithSource & net_log)2532*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log) {
2533*6777b538SAndroid Build Coastguard Worker net_log_ = net_log;
2534*6777b538SAndroid Build Coastguard Worker
2535*6777b538SAndroid Build Coastguard Worker // Reset the variables that might get set in this function. This is done
2536*6777b538SAndroid Build Coastguard Worker // because this function can be invoked multiple times for a transaction.
2537*6777b538SAndroid Build Coastguard Worker cache_entry_status_ = CacheEntryStatus::ENTRY_UNDEFINED;
2538*6777b538SAndroid Build Coastguard Worker external_validation_.Reset();
2539*6777b538SAndroid Build Coastguard Worker range_requested_ = false;
2540*6777b538SAndroid Build Coastguard Worker partial_.reset();
2541*6777b538SAndroid Build Coastguard Worker
2542*6777b538SAndroid Build Coastguard Worker request_ = initial_request_;
2543*6777b538SAndroid Build Coastguard Worker custom_request_.reset();
2544*6777b538SAndroid Build Coastguard Worker
2545*6777b538SAndroid Build Coastguard Worker effective_load_flags_ = request_->load_flags;
2546*6777b538SAndroid Build Coastguard Worker method_ = request_->method;
2547*6777b538SAndroid Build Coastguard Worker
2548*6777b538SAndroid Build Coastguard Worker if (cache_->mode() == DISABLE) {
2549*6777b538SAndroid Build Coastguard Worker effective_load_flags_ |= LOAD_DISABLE_CACHE;
2550*6777b538SAndroid Build Coastguard Worker }
2551*6777b538SAndroid Build Coastguard Worker
2552*6777b538SAndroid Build Coastguard Worker // Some headers imply load flags. The order here is significant.
2553*6777b538SAndroid Build Coastguard Worker //
2554*6777b538SAndroid Build Coastguard Worker // LOAD_DISABLE_CACHE : no cache read or write
2555*6777b538SAndroid Build Coastguard Worker // LOAD_BYPASS_CACHE : no cache read
2556*6777b538SAndroid Build Coastguard Worker // LOAD_VALIDATE_CACHE : no cache read unless validation
2557*6777b538SAndroid Build Coastguard Worker //
2558*6777b538SAndroid Build Coastguard Worker // The former modes trump latter modes, so if we find a matching header we
2559*6777b538SAndroid Build Coastguard Worker // can stop iterating kSpecialHeaders.
2560*6777b538SAndroid Build Coastguard Worker //
2561*6777b538SAndroid Build Coastguard Worker static const struct {
2562*6777b538SAndroid Build Coastguard Worker // This field is not a raw_ptr<> because it was filtered by the rewriter
2563*6777b538SAndroid Build Coastguard Worker // for: #global-scope
2564*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION const HeaderNameAndValue* search;
2565*6777b538SAndroid Build Coastguard Worker int load_flag;
2566*6777b538SAndroid Build Coastguard Worker } kSpecialHeaders[] = {
2567*6777b538SAndroid Build Coastguard Worker {kPassThroughHeaders, LOAD_DISABLE_CACHE},
2568*6777b538SAndroid Build Coastguard Worker {kForceFetchHeaders, LOAD_BYPASS_CACHE},
2569*6777b538SAndroid Build Coastguard Worker {kForceValidateHeaders, LOAD_VALIDATE_CACHE},
2570*6777b538SAndroid Build Coastguard Worker };
2571*6777b538SAndroid Build Coastguard Worker
2572*6777b538SAndroid Build Coastguard Worker bool range_found = false;
2573*6777b538SAndroid Build Coastguard Worker bool external_validation_error = false;
2574*6777b538SAndroid Build Coastguard Worker bool special_headers = false;
2575*6777b538SAndroid Build Coastguard Worker
2576*6777b538SAndroid Build Coastguard Worker if (request_->extra_headers.HasHeader(HttpRequestHeaders::kRange)) {
2577*6777b538SAndroid Build Coastguard Worker range_found = true;
2578*6777b538SAndroid Build Coastguard Worker }
2579*6777b538SAndroid Build Coastguard Worker
2580*6777b538SAndroid Build Coastguard Worker for (const auto& special_header : kSpecialHeaders) {
2581*6777b538SAndroid Build Coastguard Worker if (HeaderMatches(request_->extra_headers, special_header.search)) {
2582*6777b538SAndroid Build Coastguard Worker effective_load_flags_ |= special_header.load_flag;
2583*6777b538SAndroid Build Coastguard Worker special_headers = true;
2584*6777b538SAndroid Build Coastguard Worker break;
2585*6777b538SAndroid Build Coastguard Worker }
2586*6777b538SAndroid Build Coastguard Worker }
2587*6777b538SAndroid Build Coastguard Worker
2588*6777b538SAndroid Build Coastguard Worker // Check for conditionalization headers which may correspond with a
2589*6777b538SAndroid Build Coastguard Worker // cache validation request.
2590*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(kValidationHeaders); ++i) {
2591*6777b538SAndroid Build Coastguard Worker const ValidationHeaderInfo& info = kValidationHeaders[i];
2592*6777b538SAndroid Build Coastguard Worker std::string validation_value;
2593*6777b538SAndroid Build Coastguard Worker if (request_->extra_headers.GetHeader(info.request_header_name,
2594*6777b538SAndroid Build Coastguard Worker &validation_value)) {
2595*6777b538SAndroid Build Coastguard Worker if (!external_validation_.values[i].empty() || validation_value.empty()) {
2596*6777b538SAndroid Build Coastguard Worker external_validation_error = true;
2597*6777b538SAndroid Build Coastguard Worker }
2598*6777b538SAndroid Build Coastguard Worker external_validation_.values[i] = validation_value;
2599*6777b538SAndroid Build Coastguard Worker external_validation_.initialized = true;
2600*6777b538SAndroid Build Coastguard Worker }
2601*6777b538SAndroid Build Coastguard Worker }
2602*6777b538SAndroid Build Coastguard Worker
2603*6777b538SAndroid Build Coastguard Worker if (range_found || special_headers || external_validation_.initialized) {
2604*6777b538SAndroid Build Coastguard Worker // Log the headers before request_ is modified.
2605*6777b538SAndroid Build Coastguard Worker std::string empty;
2606*6777b538SAndroid Build Coastguard Worker NetLogRequestHeaders(net_log_,
2607*6777b538SAndroid Build Coastguard Worker NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS,
2608*6777b538SAndroid Build Coastguard Worker empty, &request_->extra_headers);
2609*6777b538SAndroid Build Coastguard Worker }
2610*6777b538SAndroid Build Coastguard Worker
2611*6777b538SAndroid Build Coastguard Worker // We don't support ranges and validation headers.
2612*6777b538SAndroid Build Coastguard Worker if (range_found && external_validation_.initialized) {
2613*6777b538SAndroid Build Coastguard Worker LOG(WARNING) << "Byte ranges AND validation headers found.";
2614*6777b538SAndroid Build Coastguard Worker effective_load_flags_ |= LOAD_DISABLE_CACHE;
2615*6777b538SAndroid Build Coastguard Worker }
2616*6777b538SAndroid Build Coastguard Worker
2617*6777b538SAndroid Build Coastguard Worker // If there is more than one validation header, we can't treat this request as
2618*6777b538SAndroid Build Coastguard Worker // a cache validation, since we don't know for sure which header the server
2619*6777b538SAndroid Build Coastguard Worker // will give us a response for (and they could be contradictory).
2620*6777b538SAndroid Build Coastguard Worker if (external_validation_error) {
2621*6777b538SAndroid Build Coastguard Worker LOG(WARNING) << "Multiple or malformed validation headers found.";
2622*6777b538SAndroid Build Coastguard Worker effective_load_flags_ |= LOAD_DISABLE_CACHE;
2623*6777b538SAndroid Build Coastguard Worker }
2624*6777b538SAndroid Build Coastguard Worker
2625*6777b538SAndroid Build Coastguard Worker if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
2626*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
2627*6777b538SAndroid Build Coastguard Worker partial_ = std::make_unique<PartialData>();
2628*6777b538SAndroid Build Coastguard Worker if (method_ == "GET" && partial_->Init(request_->extra_headers)) {
2629*6777b538SAndroid Build Coastguard Worker // We will be modifying the actual range requested to the server, so
2630*6777b538SAndroid Build Coastguard Worker // let's remove the header here.
2631*6777b538SAndroid Build Coastguard Worker // Note that custom_request_ is a shallow copy so will keep the same
2632*6777b538SAndroid Build Coastguard Worker // pointer to upload data stream as in the original request.
2633*6777b538SAndroid Build Coastguard Worker custom_request_ = std::make_unique<HttpRequestInfo>(*request_);
2634*6777b538SAndroid Build Coastguard Worker custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
2635*6777b538SAndroid Build Coastguard Worker request_ = custom_request_.get();
2636*6777b538SAndroid Build Coastguard Worker partial_->SetHeaders(custom_request_->extra_headers);
2637*6777b538SAndroid Build Coastguard Worker } else {
2638*6777b538SAndroid Build Coastguard Worker // The range is invalid or we cannot handle it properly.
2639*6777b538SAndroid Build Coastguard Worker VLOG(1) << "Invalid byte range found.";
2640*6777b538SAndroid Build Coastguard Worker effective_load_flags_ |= LOAD_DISABLE_CACHE;
2641*6777b538SAndroid Build Coastguard Worker partial_.reset(nullptr);
2642*6777b538SAndroid Build Coastguard Worker }
2643*6777b538SAndroid Build Coastguard Worker }
2644*6777b538SAndroid Build Coastguard Worker }
2645*6777b538SAndroid Build Coastguard Worker
ShouldPassThrough()2646*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::ShouldPassThrough() {
2647*6777b538SAndroid Build Coastguard Worker bool cacheable = true;
2648*6777b538SAndroid Build Coastguard Worker
2649*6777b538SAndroid Build Coastguard Worker // We may have a null disk_cache if there is an error we cannot recover from,
2650*6777b538SAndroid Build Coastguard Worker // like not enough disk space, or sharing violations.
2651*6777b538SAndroid Build Coastguard Worker if (!cache_->disk_cache_.get()) {
2652*6777b538SAndroid Build Coastguard Worker cacheable = false;
2653*6777b538SAndroid Build Coastguard Worker } else if (effective_load_flags_ & LOAD_DISABLE_CACHE) {
2654*6777b538SAndroid Build Coastguard Worker cacheable = false;
2655*6777b538SAndroid Build Coastguard Worker }
2656*6777b538SAndroid Build Coastguard Worker // Prevent resources whose origin is opaque from being cached. Blink's memory
2657*6777b538SAndroid Build Coastguard Worker // cache should take care of reusing resources within the current page load,
2658*6777b538SAndroid Build Coastguard Worker // but otherwise a resource with an opaque top-frame origin won’t be used
2659*6777b538SAndroid Build Coastguard Worker // again. Also, if the request does not have a top frame origin, bypass the
2660*6777b538SAndroid Build Coastguard Worker // cache otherwise resources from different pages could share a cached entry
2661*6777b538SAndroid Build Coastguard Worker // in such cases.
2662*6777b538SAndroid Build Coastguard Worker else if (HttpCache::IsSplitCacheEnabled() &&
2663*6777b538SAndroid Build Coastguard Worker request_->network_isolation_key.IsTransient()) {
2664*6777b538SAndroid Build Coastguard Worker cacheable = false;
2665*6777b538SAndroid Build Coastguard Worker } else if (method_ == "GET" || method_ == "HEAD") {
2666*6777b538SAndroid Build Coastguard Worker } else if (method_ == "POST" && request_->upload_data_stream &&
2667*6777b538SAndroid Build Coastguard Worker request_->upload_data_stream->identifier()) {
2668*6777b538SAndroid Build Coastguard Worker } else if (method_ == "PUT" && request_->upload_data_stream) {
2669*6777b538SAndroid Build Coastguard Worker }
2670*6777b538SAndroid Build Coastguard Worker // DELETE and PATCH requests may result in invalidating the cache, so cannot
2671*6777b538SAndroid Build Coastguard Worker // just pass through.
2672*6777b538SAndroid Build Coastguard Worker else if (method_ == "DELETE" || method_ == "PATCH") {
2673*6777b538SAndroid Build Coastguard Worker } else {
2674*6777b538SAndroid Build Coastguard Worker cacheable = false;
2675*6777b538SAndroid Build Coastguard Worker }
2676*6777b538SAndroid Build Coastguard Worker
2677*6777b538SAndroid Build Coastguard Worker return !cacheable;
2678*6777b538SAndroid Build Coastguard Worker }
2679*6777b538SAndroid Build Coastguard Worker
BeginCacheRead()2680*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::BeginCacheRead() {
2681*6777b538SAndroid Build Coastguard Worker // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges.
2682*6777b538SAndroid Build Coastguard Worker // It's possible to trigger this from JavaScript using the Fetch API with
2683*6777b538SAndroid Build Coastguard Worker // `cache: 'only-if-cached'` so ideally we should support it.
2684*6777b538SAndroid Build Coastguard Worker // TODO(ricea): Correctly read from the cache in this case.
2685*6777b538SAndroid Build Coastguard Worker if (response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT ||
2686*6777b538SAndroid Build Coastguard Worker partial_) {
2687*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
2688*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_MISS;
2689*6777b538SAndroid Build Coastguard Worker }
2690*6777b538SAndroid Build Coastguard Worker
2691*6777b538SAndroid Build Coastguard Worker // We don't have the whole resource.
2692*6777b538SAndroid Build Coastguard Worker if (truncated_) {
2693*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
2694*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_MISS;
2695*6777b538SAndroid Build Coastguard Worker }
2696*6777b538SAndroid Build Coastguard Worker
2697*6777b538SAndroid Build Coastguard Worker if (RequiresValidation() != VALIDATION_NONE) {
2698*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
2699*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_MISS;
2700*6777b538SAndroid Build Coastguard Worker }
2701*6777b538SAndroid Build Coastguard Worker
2702*6777b538SAndroid Build Coastguard Worker if (method_ == "HEAD") {
2703*6777b538SAndroid Build Coastguard Worker FixHeadersForHead();
2704*6777b538SAndroid Build Coastguard Worker }
2705*6777b538SAndroid Build Coastguard Worker
2706*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
2707*6777b538SAndroid Build Coastguard Worker return OK;
2708*6777b538SAndroid Build Coastguard Worker }
2709*6777b538SAndroid Build Coastguard Worker
BeginCacheValidation()2710*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::BeginCacheValidation() {
2711*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(mode_, READ_WRITE);
2712*6777b538SAndroid Build Coastguard Worker
2713*6777b538SAndroid Build Coastguard Worker ValidationType required_validation = RequiresValidation();
2714*6777b538SAndroid Build Coastguard Worker
2715*6777b538SAndroid Build Coastguard Worker bool skip_validation = (required_validation == VALIDATION_NONE);
2716*6777b538SAndroid Build Coastguard Worker bool needs_stale_while_revalidate_cache_update = false;
2717*6777b538SAndroid Build Coastguard Worker
2718*6777b538SAndroid Build Coastguard Worker if ((effective_load_flags_ & LOAD_SUPPORT_ASYNC_REVALIDATION) &&
2719*6777b538SAndroid Build Coastguard Worker required_validation == VALIDATION_ASYNCHRONOUS) {
2720*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(request_->method, "GET");
2721*6777b538SAndroid Build Coastguard Worker skip_validation = true;
2722*6777b538SAndroid Build Coastguard Worker response_.async_revalidation_requested = true;
2723*6777b538SAndroid Build Coastguard Worker needs_stale_while_revalidate_cache_update =
2724*6777b538SAndroid Build Coastguard Worker response_.stale_revalidate_timeout.is_null();
2725*6777b538SAndroid Build Coastguard Worker }
2726*6777b538SAndroid Build Coastguard Worker
2727*6777b538SAndroid Build Coastguard Worker if (method_ == "HEAD" && (truncated_ || response_.headers->response_code() ==
2728*6777b538SAndroid Build Coastguard Worker net::HTTP_PARTIAL_CONTENT)) {
2729*6777b538SAndroid Build Coastguard Worker DCHECK(!partial_);
2730*6777b538SAndroid Build Coastguard Worker if (skip_validation) {
2731*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
2732*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CONNECTED_CALLBACK);
2733*6777b538SAndroid Build Coastguard Worker return OK;
2734*6777b538SAndroid Build Coastguard Worker }
2735*6777b538SAndroid Build Coastguard Worker
2736*6777b538SAndroid Build Coastguard Worker // Bail out!
2737*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
2738*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
2739*6777b538SAndroid Build Coastguard Worker return OK;
2740*6777b538SAndroid Build Coastguard Worker }
2741*6777b538SAndroid Build Coastguard Worker
2742*6777b538SAndroid Build Coastguard Worker if (truncated_) {
2743*6777b538SAndroid Build Coastguard Worker // Truncated entries can cause partial gets, so we shouldn't record this
2744*6777b538SAndroid Build Coastguard Worker // load in histograms.
2745*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
2746*6777b538SAndroid Build Coastguard Worker skip_validation = !partial_->initial_validation();
2747*6777b538SAndroid Build Coastguard Worker }
2748*6777b538SAndroid Build Coastguard Worker
2749*6777b538SAndroid Build Coastguard Worker // If this is the first request (!reading_) of a 206 entry (is_sparse_) that
2750*6777b538SAndroid Build Coastguard Worker // doesn't actually cover the entire file (which with !reading would require
2751*6777b538SAndroid Build Coastguard Worker // partial->IsLastRange()), and the user is requesting the whole thing
2752*6777b538SAndroid Build Coastguard Worker // (!partial_->range_requested()), make sure to validate the first chunk,
2753*6777b538SAndroid Build Coastguard Worker // since afterwards it will be too late if it's actually out-of-date (or the
2754*6777b538SAndroid Build Coastguard Worker // server bungles invalidation). This is limited to the whole-file request
2755*6777b538SAndroid Build Coastguard Worker // as a targeted fix for https://crbug.com/888742 while avoiding extra
2756*6777b538SAndroid Build Coastguard Worker // requests in other cases, but the problem can occur more generally as well;
2757*6777b538SAndroid Build Coastguard Worker // it's just a lot less likely with applications actively using ranges.
2758*6777b538SAndroid Build Coastguard Worker // See https://crbug.com/902724 for the more general case.
2759*6777b538SAndroid Build Coastguard Worker bool first_read_of_full_from_partial =
2760*6777b538SAndroid Build Coastguard Worker is_sparse_ && !reading_ &&
2761*6777b538SAndroid Build Coastguard Worker (partial_ && !partial_->range_requested() && !partial_->IsLastRange());
2762*6777b538SAndroid Build Coastguard Worker
2763*6777b538SAndroid Build Coastguard Worker if (partial_ && (is_sparse_ || truncated_) &&
2764*6777b538SAndroid Build Coastguard Worker (!partial_->IsCurrentRangeCached() || invalid_range_ ||
2765*6777b538SAndroid Build Coastguard Worker first_read_of_full_from_partial)) {
2766*6777b538SAndroid Build Coastguard Worker // Force revalidation for sparse or truncated entries. Note that we don't
2767*6777b538SAndroid Build Coastguard Worker // want to ignore the regular validation logic just because a byte range was
2768*6777b538SAndroid Build Coastguard Worker // part of the request.
2769*6777b538SAndroid Build Coastguard Worker skip_validation = false;
2770*6777b538SAndroid Build Coastguard Worker }
2771*6777b538SAndroid Build Coastguard Worker
2772*6777b538SAndroid Build Coastguard Worker if (skip_validation) {
2773*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
2774*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
2775*6777b538SAndroid Build Coastguard Worker TransitionToState(needs_stale_while_revalidate_cache_update
2776*6777b538SAndroid Build Coastguard Worker ? STATE_CACHE_UPDATE_STALE_WHILE_REVALIDATE_TIMEOUT
2777*6777b538SAndroid Build Coastguard Worker : STATE_CONNECTED_CALLBACK);
2778*6777b538SAndroid Build Coastguard Worker return OK;
2779*6777b538SAndroid Build Coastguard Worker } else {
2780*6777b538SAndroid Build Coastguard Worker // Make the network request conditional, to see if we may reuse our cached
2781*6777b538SAndroid Build Coastguard Worker // response. If we cannot do so, then we just resort to a normal fetch.
2782*6777b538SAndroid Build Coastguard Worker // Our mode remains READ_WRITE for a conditional request. Even if the
2783*6777b538SAndroid Build Coastguard Worker // conditionalization fails, we don't switch to WRITE mode until we
2784*6777b538SAndroid Build Coastguard Worker // know we won't be falling back to using the cache entry in the
2785*6777b538SAndroid Build Coastguard Worker // LOAD_FROM_CACHE_IF_OFFLINE case.
2786*6777b538SAndroid Build Coastguard Worker if (!ConditionalizeRequest()) {
2787*6777b538SAndroid Build Coastguard Worker couldnt_conditionalize_request_ = true;
2788*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
2789*6777b538SAndroid Build Coastguard Worker if (partial_) {
2790*6777b538SAndroid Build Coastguard Worker return DoRestartPartialRequest();
2791*6777b538SAndroid Build Coastguard Worker }
2792*6777b538SAndroid Build Coastguard Worker
2793*6777b538SAndroid Build Coastguard Worker DCHECK_NE(net::HTTP_PARTIAL_CONTENT, response_.headers->response_code());
2794*6777b538SAndroid Build Coastguard Worker }
2795*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
2796*6777b538SAndroid Build Coastguard Worker }
2797*6777b538SAndroid Build Coastguard Worker return OK;
2798*6777b538SAndroid Build Coastguard Worker }
2799*6777b538SAndroid Build Coastguard Worker
BeginPartialCacheValidation()2800*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::BeginPartialCacheValidation() {
2801*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(mode_, READ_WRITE);
2802*6777b538SAndroid Build Coastguard Worker
2803*6777b538SAndroid Build Coastguard Worker if (response_.headers->response_code() != net::HTTP_PARTIAL_CONTENT &&
2804*6777b538SAndroid Build Coastguard Worker !partial_ && !truncated_) {
2805*6777b538SAndroid Build Coastguard Worker return BeginCacheValidation();
2806*6777b538SAndroid Build Coastguard Worker }
2807*6777b538SAndroid Build Coastguard Worker
2808*6777b538SAndroid Build Coastguard Worker // Partial requests should not be recorded in histograms.
2809*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
2810*6777b538SAndroid Build Coastguard Worker if (method_ == "HEAD") {
2811*6777b538SAndroid Build Coastguard Worker return BeginCacheValidation();
2812*6777b538SAndroid Build Coastguard Worker }
2813*6777b538SAndroid Build Coastguard Worker
2814*6777b538SAndroid Build Coastguard Worker if (!range_requested_) {
2815*6777b538SAndroid Build Coastguard Worker // The request is not for a range, but we have stored just ranges.
2816*6777b538SAndroid Build Coastguard Worker
2817*6777b538SAndroid Build Coastguard Worker partial_ = std::make_unique<PartialData>();
2818*6777b538SAndroid Build Coastguard Worker partial_->SetHeaders(request_->extra_headers);
2819*6777b538SAndroid Build Coastguard Worker if (!custom_request_.get()) {
2820*6777b538SAndroid Build Coastguard Worker custom_request_ = std::make_unique<HttpRequestInfo>(*request_);
2821*6777b538SAndroid Build Coastguard Worker request_ = custom_request_.get();
2822*6777b538SAndroid Build Coastguard Worker }
2823*6777b538SAndroid Build Coastguard Worker }
2824*6777b538SAndroid Build Coastguard Worker
2825*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_QUERY_DATA);
2826*6777b538SAndroid Build Coastguard Worker return OK;
2827*6777b538SAndroid Build Coastguard Worker }
2828*6777b538SAndroid Build Coastguard Worker
2829*6777b538SAndroid Build Coastguard Worker // This should only be called once per request.
ValidateEntryHeadersAndContinue()2830*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::ValidateEntryHeadersAndContinue() {
2831*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(mode_, READ_WRITE);
2832*6777b538SAndroid Build Coastguard Worker
2833*6777b538SAndroid Build Coastguard Worker if (!partial_->UpdateFromStoredHeaders(response_.headers.get(),
2834*6777b538SAndroid Build Coastguard Worker entry_->GetEntry(), truncated_,
2835*6777b538SAndroid Build Coastguard Worker entry_->IsWritingInProgress())) {
2836*6777b538SAndroid Build Coastguard Worker return DoRestartPartialRequest();
2837*6777b538SAndroid Build Coastguard Worker }
2838*6777b538SAndroid Build Coastguard Worker
2839*6777b538SAndroid Build Coastguard Worker if (response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT) {
2840*6777b538SAndroid Build Coastguard Worker is_sparse_ = true;
2841*6777b538SAndroid Build Coastguard Worker }
2842*6777b538SAndroid Build Coastguard Worker
2843*6777b538SAndroid Build Coastguard Worker if (!partial_->IsRequestedRangeOK()) {
2844*6777b538SAndroid Build Coastguard Worker // The stored data is fine, but the request may be invalid.
2845*6777b538SAndroid Build Coastguard Worker invalid_range_ = true;
2846*6777b538SAndroid Build Coastguard Worker }
2847*6777b538SAndroid Build Coastguard Worker
2848*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
2849*6777b538SAndroid Build Coastguard Worker return OK;
2850*6777b538SAndroid Build Coastguard Worker }
2851*6777b538SAndroid Build Coastguard Worker
2852*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::
ExternallyConditionalizedValidationHeadersMatchEntry() const2853*6777b538SAndroid Build Coastguard Worker ExternallyConditionalizedValidationHeadersMatchEntry() const {
2854*6777b538SAndroid Build Coastguard Worker DCHECK(external_validation_.initialized);
2855*6777b538SAndroid Build Coastguard Worker
2856*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(kValidationHeaders); i++) {
2857*6777b538SAndroid Build Coastguard Worker if (external_validation_.values[i].empty()) {
2858*6777b538SAndroid Build Coastguard Worker continue;
2859*6777b538SAndroid Build Coastguard Worker }
2860*6777b538SAndroid Build Coastguard Worker
2861*6777b538SAndroid Build Coastguard Worker // Retrieve either the cached response's "etag" or "last-modified" header.
2862*6777b538SAndroid Build Coastguard Worker std::string validator;
2863*6777b538SAndroid Build Coastguard Worker response_.headers->EnumerateHeader(
2864*6777b538SAndroid Build Coastguard Worker nullptr, kValidationHeaders[i].related_response_header_name,
2865*6777b538SAndroid Build Coastguard Worker &validator);
2866*6777b538SAndroid Build Coastguard Worker
2867*6777b538SAndroid Build Coastguard Worker if (validator != external_validation_.values[i]) {
2868*6777b538SAndroid Build Coastguard Worker return false;
2869*6777b538SAndroid Build Coastguard Worker }
2870*6777b538SAndroid Build Coastguard Worker }
2871*6777b538SAndroid Build Coastguard Worker
2872*6777b538SAndroid Build Coastguard Worker return true;
2873*6777b538SAndroid Build Coastguard Worker }
2874*6777b538SAndroid Build Coastguard Worker
BeginExternallyConditionalizedRequest()2875*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
2876*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(UPDATE, mode_);
2877*6777b538SAndroid Build Coastguard Worker
2878*6777b538SAndroid Build Coastguard Worker if (response_.headers->response_code() != net::HTTP_OK || truncated_ ||
2879*6777b538SAndroid Build Coastguard Worker !ExternallyConditionalizedValidationHeadersMatchEntry()) {
2880*6777b538SAndroid Build Coastguard Worker // The externally conditionalized request is not a validation request
2881*6777b538SAndroid Build Coastguard Worker // for our existing cache entry. Proceed with caching disabled.
2882*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
2883*6777b538SAndroid Build Coastguard Worker DoneWithEntry(true);
2884*6777b538SAndroid Build Coastguard Worker }
2885*6777b538SAndroid Build Coastguard Worker
2886*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SEND_REQUEST);
2887*6777b538SAndroid Build Coastguard Worker return OK;
2888*6777b538SAndroid Build Coastguard Worker }
2889*6777b538SAndroid Build Coastguard Worker
RestartNetworkRequest()2890*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::RestartNetworkRequest() {
2891*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ & WRITE || mode_ == NONE);
2892*6777b538SAndroid Build Coastguard Worker DCHECK(network_trans_.get());
2893*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
2894*6777b538SAndroid Build Coastguard Worker
2895*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_SEND_REQUEST_COMPLETE;
2896*6777b538SAndroid Build Coastguard Worker int rv = network_trans_->RestartIgnoringLastError(io_callback_);
2897*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING) {
2898*6777b538SAndroid Build Coastguard Worker return DoLoop(rv);
2899*6777b538SAndroid Build Coastguard Worker }
2900*6777b538SAndroid Build Coastguard Worker return rv;
2901*6777b538SAndroid Build Coastguard Worker }
2902*6777b538SAndroid Build Coastguard Worker
RestartNetworkRequestWithCertificate(scoped_refptr<X509Certificate> client_cert,scoped_refptr<SSLPrivateKey> client_private_key)2903*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::RestartNetworkRequestWithCertificate(
2904*6777b538SAndroid Build Coastguard Worker scoped_refptr<X509Certificate> client_cert,
2905*6777b538SAndroid Build Coastguard Worker scoped_refptr<SSLPrivateKey> client_private_key) {
2906*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ & WRITE || mode_ == NONE);
2907*6777b538SAndroid Build Coastguard Worker DCHECK(network_trans_.get());
2908*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
2909*6777b538SAndroid Build Coastguard Worker
2910*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_SEND_REQUEST_COMPLETE;
2911*6777b538SAndroid Build Coastguard Worker int rv = network_trans_->RestartWithCertificate(
2912*6777b538SAndroid Build Coastguard Worker std::move(client_cert), std::move(client_private_key), io_callback_);
2913*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING) {
2914*6777b538SAndroid Build Coastguard Worker return DoLoop(rv);
2915*6777b538SAndroid Build Coastguard Worker }
2916*6777b538SAndroid Build Coastguard Worker return rv;
2917*6777b538SAndroid Build Coastguard Worker }
2918*6777b538SAndroid Build Coastguard Worker
RestartNetworkRequestWithAuth(const AuthCredentials & credentials)2919*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::RestartNetworkRequestWithAuth(
2920*6777b538SAndroid Build Coastguard Worker const AuthCredentials& credentials) {
2921*6777b538SAndroid Build Coastguard Worker DCHECK(mode_ & WRITE || mode_ == NONE);
2922*6777b538SAndroid Build Coastguard Worker DCHECK(network_trans_.get());
2923*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_NONE, next_state_);
2924*6777b538SAndroid Build Coastguard Worker
2925*6777b538SAndroid Build Coastguard Worker next_state_ = STATE_SEND_REQUEST_COMPLETE;
2926*6777b538SAndroid Build Coastguard Worker int rv = network_trans_->RestartWithAuth(credentials, io_callback_);
2927*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING) {
2928*6777b538SAndroid Build Coastguard Worker return DoLoop(rv);
2929*6777b538SAndroid Build Coastguard Worker }
2930*6777b538SAndroid Build Coastguard Worker return rv;
2931*6777b538SAndroid Build Coastguard Worker }
2932*6777b538SAndroid Build Coastguard Worker
RequiresValidation()2933*6777b538SAndroid Build Coastguard Worker ValidationType HttpCache::Transaction::RequiresValidation() {
2934*6777b538SAndroid Build Coastguard Worker // TODO(darin): need to do more work here:
2935*6777b538SAndroid Build Coastguard Worker // - make sure we have a matching request method
2936*6777b538SAndroid Build Coastguard Worker // - watch out for cached responses that depend on authentication
2937*6777b538SAndroid Build Coastguard Worker
2938*6777b538SAndroid Build Coastguard Worker if (!(effective_load_flags_ & LOAD_SKIP_VARY_CHECK) &&
2939*6777b538SAndroid Build Coastguard Worker response_.vary_data.is_valid() &&
2940*6777b538SAndroid Build Coastguard Worker !response_.vary_data.MatchesRequest(*request_,
2941*6777b538SAndroid Build Coastguard Worker *response_.headers.get())) {
2942*6777b538SAndroid Build Coastguard Worker vary_mismatch_ = true;
2943*6777b538SAndroid Build Coastguard Worker validation_cause_ = VALIDATION_CAUSE_VARY_MISMATCH;
2944*6777b538SAndroid Build Coastguard Worker return VALIDATION_SYNCHRONOUS;
2945*6777b538SAndroid Build Coastguard Worker }
2946*6777b538SAndroid Build Coastguard Worker
2947*6777b538SAndroid Build Coastguard Worker if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION) {
2948*6777b538SAndroid Build Coastguard Worker return VALIDATION_NONE;
2949*6777b538SAndroid Build Coastguard Worker }
2950*6777b538SAndroid Build Coastguard Worker
2951*6777b538SAndroid Build Coastguard Worker if (method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH") {
2952*6777b538SAndroid Build Coastguard Worker return VALIDATION_SYNCHRONOUS;
2953*6777b538SAndroid Build Coastguard Worker }
2954*6777b538SAndroid Build Coastguard Worker
2955*6777b538SAndroid Build Coastguard Worker bool validate_flag = effective_load_flags_ & LOAD_VALIDATE_CACHE;
2956*6777b538SAndroid Build Coastguard Worker
2957*6777b538SAndroid Build Coastguard Worker ValidationType validation_required_by_headers =
2958*6777b538SAndroid Build Coastguard Worker validate_flag ? VALIDATION_SYNCHRONOUS
2959*6777b538SAndroid Build Coastguard Worker : response_.headers->RequiresValidation(
2960*6777b538SAndroid Build Coastguard Worker response_.request_time, response_.response_time,
2961*6777b538SAndroid Build Coastguard Worker cache_->clock_->Now());
2962*6777b538SAndroid Build Coastguard Worker
2963*6777b538SAndroid Build Coastguard Worker base::TimeDelta response_time_in_cache =
2964*6777b538SAndroid Build Coastguard Worker cache_->clock_->Now() - response_.response_time;
2965*6777b538SAndroid Build Coastguard Worker
2966*6777b538SAndroid Build Coastguard Worker if (!base::FeatureList::IsEnabled(
2967*6777b538SAndroid Build Coastguard Worker features::kPrefetchFollowsNormalCacheSemantics) &&
2968*6777b538SAndroid Build Coastguard Worker !(effective_load_flags_ & LOAD_PREFETCH) &&
2969*6777b538SAndroid Build Coastguard Worker (response_time_in_cache >= base::TimeDelta())) {
2970*6777b538SAndroid Build Coastguard Worker bool reused_within_time_window =
2971*6777b538SAndroid Build Coastguard Worker response_time_in_cache < base::Minutes(kPrefetchReuseMins);
2972*6777b538SAndroid Build Coastguard Worker bool first_reuse = response_.unused_since_prefetch;
2973*6777b538SAndroid Build Coastguard Worker
2974*6777b538SAndroid Build Coastguard Worker // The first use of a resource after prefetch within a short window skips
2975*6777b538SAndroid Build Coastguard Worker // validation.
2976*6777b538SAndroid Build Coastguard Worker if (first_reuse && reused_within_time_window) {
2977*6777b538SAndroid Build Coastguard Worker return VALIDATION_NONE;
2978*6777b538SAndroid Build Coastguard Worker }
2979*6777b538SAndroid Build Coastguard Worker }
2980*6777b538SAndroid Build Coastguard Worker
2981*6777b538SAndroid Build Coastguard Worker if (validate_flag) {
2982*6777b538SAndroid Build Coastguard Worker validation_cause_ = VALIDATION_CAUSE_VALIDATE_FLAG;
2983*6777b538SAndroid Build Coastguard Worker return VALIDATION_SYNCHRONOUS;
2984*6777b538SAndroid Build Coastguard Worker }
2985*6777b538SAndroid Build Coastguard Worker
2986*6777b538SAndroid Build Coastguard Worker if (validation_required_by_headers != VALIDATION_NONE) {
2987*6777b538SAndroid Build Coastguard Worker HttpResponseHeaders::FreshnessLifetimes lifetimes =
2988*6777b538SAndroid Build Coastguard Worker response_.headers->GetFreshnessLifetimes(response_.response_time);
2989*6777b538SAndroid Build Coastguard Worker if (lifetimes.freshness == base::TimeDelta()) {
2990*6777b538SAndroid Build Coastguard Worker validation_cause_ = VALIDATION_CAUSE_ZERO_FRESHNESS;
2991*6777b538SAndroid Build Coastguard Worker } else {
2992*6777b538SAndroid Build Coastguard Worker validation_cause_ = VALIDATION_CAUSE_STALE;
2993*6777b538SAndroid Build Coastguard Worker }
2994*6777b538SAndroid Build Coastguard Worker }
2995*6777b538SAndroid Build Coastguard Worker
2996*6777b538SAndroid Build Coastguard Worker if (validation_required_by_headers == VALIDATION_ASYNCHRONOUS) {
2997*6777b538SAndroid Build Coastguard Worker // Asynchronous revalidation is only supported for GET methods.
2998*6777b538SAndroid Build Coastguard Worker if (request_->method != "GET") {
2999*6777b538SAndroid Build Coastguard Worker return VALIDATION_SYNCHRONOUS;
3000*6777b538SAndroid Build Coastguard Worker }
3001*6777b538SAndroid Build Coastguard Worker
3002*6777b538SAndroid Build Coastguard Worker // If the timeout on the staleness revalidation is set don't hand out
3003*6777b538SAndroid Build Coastguard Worker // a resource that hasn't been async validated.
3004*6777b538SAndroid Build Coastguard Worker if (!response_.stale_revalidate_timeout.is_null() &&
3005*6777b538SAndroid Build Coastguard Worker response_.stale_revalidate_timeout < cache_->clock_->Now()) {
3006*6777b538SAndroid Build Coastguard Worker return VALIDATION_SYNCHRONOUS;
3007*6777b538SAndroid Build Coastguard Worker }
3008*6777b538SAndroid Build Coastguard Worker }
3009*6777b538SAndroid Build Coastguard Worker
3010*6777b538SAndroid Build Coastguard Worker return validation_required_by_headers;
3011*6777b538SAndroid Build Coastguard Worker }
3012*6777b538SAndroid Build Coastguard Worker
IsResponseConditionalizable(std::string * etag_value,std::string * last_modified_value) const3013*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::IsResponseConditionalizable(
3014*6777b538SAndroid Build Coastguard Worker std::string* etag_value,
3015*6777b538SAndroid Build Coastguard Worker std::string* last_modified_value) const {
3016*6777b538SAndroid Build Coastguard Worker DCHECK(response_.headers.get());
3017*6777b538SAndroid Build Coastguard Worker
3018*6777b538SAndroid Build Coastguard Worker // This only makes sense for cached 200 or 206 responses.
3019*6777b538SAndroid Build Coastguard Worker if (response_.headers->response_code() != net::HTTP_OK &&
3020*6777b538SAndroid Build Coastguard Worker response_.headers->response_code() != net::HTTP_PARTIAL_CONTENT) {
3021*6777b538SAndroid Build Coastguard Worker return false;
3022*6777b538SAndroid Build Coastguard Worker }
3023*6777b538SAndroid Build Coastguard Worker
3024*6777b538SAndroid Build Coastguard Worker // Just use the first available ETag and/or Last-Modified header value.
3025*6777b538SAndroid Build Coastguard Worker // TODO(darin): Or should we use the last?
3026*6777b538SAndroid Build Coastguard Worker
3027*6777b538SAndroid Build Coastguard Worker if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) {
3028*6777b538SAndroid Build Coastguard Worker response_.headers->EnumerateHeader(nullptr, "etag", etag_value);
3029*6777b538SAndroid Build Coastguard Worker }
3030*6777b538SAndroid Build Coastguard Worker
3031*6777b538SAndroid Build Coastguard Worker response_.headers->EnumerateHeader(nullptr, "last-modified",
3032*6777b538SAndroid Build Coastguard Worker last_modified_value);
3033*6777b538SAndroid Build Coastguard Worker
3034*6777b538SAndroid Build Coastguard Worker if (etag_value->empty() && last_modified_value->empty()) {
3035*6777b538SAndroid Build Coastguard Worker return false;
3036*6777b538SAndroid Build Coastguard Worker }
3037*6777b538SAndroid Build Coastguard Worker
3038*6777b538SAndroid Build Coastguard Worker return true;
3039*6777b538SAndroid Build Coastguard Worker }
3040*6777b538SAndroid Build Coastguard Worker
ShouldOpenOnlyMethods() const3041*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::ShouldOpenOnlyMethods() const {
3042*6777b538SAndroid Build Coastguard Worker // These methods indicate that we should only try to open an entry and not
3043*6777b538SAndroid Build Coastguard Worker // fallback to create.
3044*6777b538SAndroid Build Coastguard Worker return method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH" ||
3045*6777b538SAndroid Build Coastguard Worker (method_ == "HEAD" && mode_ == READ_WRITE);
3046*6777b538SAndroid Build Coastguard Worker }
3047*6777b538SAndroid Build Coastguard Worker
ConditionalizeRequest()3048*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::ConditionalizeRequest() {
3049*6777b538SAndroid Build Coastguard Worker DCHECK(response_.headers.get());
3050*6777b538SAndroid Build Coastguard Worker
3051*6777b538SAndroid Build Coastguard Worker if (method_ == "PUT" || method_ == "DELETE" || method_ == "PATCH") {
3052*6777b538SAndroid Build Coastguard Worker return false;
3053*6777b538SAndroid Build Coastguard Worker }
3054*6777b538SAndroid Build Coastguard Worker
3055*6777b538SAndroid Build Coastguard Worker if (fail_conditionalization_for_test_) {
3056*6777b538SAndroid Build Coastguard Worker return false;
3057*6777b538SAndroid Build Coastguard Worker }
3058*6777b538SAndroid Build Coastguard Worker
3059*6777b538SAndroid Build Coastguard Worker std::string etag_value;
3060*6777b538SAndroid Build Coastguard Worker std::string last_modified_value;
3061*6777b538SAndroid Build Coastguard Worker if (!IsResponseConditionalizable(&etag_value, &last_modified_value)) {
3062*6777b538SAndroid Build Coastguard Worker return false;
3063*6777b538SAndroid Build Coastguard Worker }
3064*6777b538SAndroid Build Coastguard Worker
3065*6777b538SAndroid Build Coastguard Worker DCHECK(response_.headers->response_code() != net::HTTP_PARTIAL_CONTENT ||
3066*6777b538SAndroid Build Coastguard Worker response_.headers->HasStrongValidators());
3067*6777b538SAndroid Build Coastguard Worker
3068*6777b538SAndroid Build Coastguard Worker if (vary_mismatch_) {
3069*6777b538SAndroid Build Coastguard Worker // Can't rely on last-modified if vary is different.
3070*6777b538SAndroid Build Coastguard Worker last_modified_value.clear();
3071*6777b538SAndroid Build Coastguard Worker if (etag_value.empty()) {
3072*6777b538SAndroid Build Coastguard Worker return false;
3073*6777b538SAndroid Build Coastguard Worker }
3074*6777b538SAndroid Build Coastguard Worker }
3075*6777b538SAndroid Build Coastguard Worker
3076*6777b538SAndroid Build Coastguard Worker if (!partial_) {
3077*6777b538SAndroid Build Coastguard Worker // Need to customize the request, so this forces us to allocate :(
3078*6777b538SAndroid Build Coastguard Worker custom_request_ = std::make_unique<HttpRequestInfo>(*request_);
3079*6777b538SAndroid Build Coastguard Worker request_ = custom_request_.get();
3080*6777b538SAndroid Build Coastguard Worker }
3081*6777b538SAndroid Build Coastguard Worker DCHECK(custom_request_.get());
3082*6777b538SAndroid Build Coastguard Worker
3083*6777b538SAndroid Build Coastguard Worker bool use_if_range =
3084*6777b538SAndroid Build Coastguard Worker partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_;
3085*6777b538SAndroid Build Coastguard Worker
3086*6777b538SAndroid Build Coastguard Worker if (!etag_value.empty()) {
3087*6777b538SAndroid Build Coastguard Worker if (use_if_range) {
3088*6777b538SAndroid Build Coastguard Worker // We don't want to switch to WRITE mode if we don't have this block of a
3089*6777b538SAndroid Build Coastguard Worker // byte-range request because we may have other parts cached.
3090*6777b538SAndroid Build Coastguard Worker custom_request_->extra_headers.SetHeader(HttpRequestHeaders::kIfRange,
3091*6777b538SAndroid Build Coastguard Worker etag_value);
3092*6777b538SAndroid Build Coastguard Worker } else {
3093*6777b538SAndroid Build Coastguard Worker custom_request_->extra_headers.SetHeader(HttpRequestHeaders::kIfNoneMatch,
3094*6777b538SAndroid Build Coastguard Worker etag_value);
3095*6777b538SAndroid Build Coastguard Worker }
3096*6777b538SAndroid Build Coastguard Worker // For byte-range requests, make sure that we use only one way to validate
3097*6777b538SAndroid Build Coastguard Worker // the request.
3098*6777b538SAndroid Build Coastguard Worker if (partial_ && !partial_->IsCurrentRangeCached()) {
3099*6777b538SAndroid Build Coastguard Worker return true;
3100*6777b538SAndroid Build Coastguard Worker }
3101*6777b538SAndroid Build Coastguard Worker }
3102*6777b538SAndroid Build Coastguard Worker
3103*6777b538SAndroid Build Coastguard Worker if (!last_modified_value.empty()) {
3104*6777b538SAndroid Build Coastguard Worker if (use_if_range) {
3105*6777b538SAndroid Build Coastguard Worker custom_request_->extra_headers.SetHeader(HttpRequestHeaders::kIfRange,
3106*6777b538SAndroid Build Coastguard Worker last_modified_value);
3107*6777b538SAndroid Build Coastguard Worker } else {
3108*6777b538SAndroid Build Coastguard Worker custom_request_->extra_headers.SetHeader(
3109*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::kIfModifiedSince, last_modified_value);
3110*6777b538SAndroid Build Coastguard Worker }
3111*6777b538SAndroid Build Coastguard Worker }
3112*6777b538SAndroid Build Coastguard Worker
3113*6777b538SAndroid Build Coastguard Worker return true;
3114*6777b538SAndroid Build Coastguard Worker }
3115*6777b538SAndroid Build Coastguard Worker
MaybeRejectBasedOnEntryInMemoryData(uint8_t in_memory_info)3116*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::MaybeRejectBasedOnEntryInMemoryData(
3117*6777b538SAndroid Build Coastguard Worker uint8_t in_memory_info) {
3118*6777b538SAndroid Build Coastguard Worker // Not going to be clever with those...
3119*6777b538SAndroid Build Coastguard Worker if (partial_) {
3120*6777b538SAndroid Build Coastguard Worker return false;
3121*6777b538SAndroid Build Coastguard Worker }
3122*6777b538SAndroid Build Coastguard Worker
3123*6777b538SAndroid Build Coastguard Worker // Avoiding open based on in-memory hints requires us to be permitted to
3124*6777b538SAndroid Build Coastguard Worker // modify the cache, including deleting an old entry. Only the READ_WRITE
3125*6777b538SAndroid Build Coastguard Worker // and WRITE modes permit that... and WRITE never tries to open entries in the
3126*6777b538SAndroid Build Coastguard Worker // first place, so we shouldn't see it here.
3127*6777b538SAndroid Build Coastguard Worker DCHECK_NE(mode_, WRITE);
3128*6777b538SAndroid Build Coastguard Worker if (mode_ != READ_WRITE) {
3129*6777b538SAndroid Build Coastguard Worker return false;
3130*6777b538SAndroid Build Coastguard Worker }
3131*6777b538SAndroid Build Coastguard Worker
3132*6777b538SAndroid Build Coastguard Worker // If we are loading ignoring cache validity (aka back button), obviously
3133*6777b538SAndroid Build Coastguard Worker // can't reject things based on it. Also if LOAD_ONLY_FROM_CACHE there is no
3134*6777b538SAndroid Build Coastguard Worker // hope of network offering anything better.
3135*6777b538SAndroid Build Coastguard Worker if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION ||
3136*6777b538SAndroid Build Coastguard Worker effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
3137*6777b538SAndroid Build Coastguard Worker return false;
3138*6777b538SAndroid Build Coastguard Worker }
3139*6777b538SAndroid Build Coastguard Worker
3140*6777b538SAndroid Build Coastguard Worker return (in_memory_info & HINT_UNUSABLE_PER_CACHING_HEADERS) ==
3141*6777b538SAndroid Build Coastguard Worker HINT_UNUSABLE_PER_CACHING_HEADERS;
3142*6777b538SAndroid Build Coastguard Worker }
3143*6777b538SAndroid Build Coastguard Worker
ComputeUnusablePerCachingHeaders()3144*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::ComputeUnusablePerCachingHeaders() {
3145*6777b538SAndroid Build Coastguard Worker // unused_since_prefetch overrides some caching headers, so it may be useful
3146*6777b538SAndroid Build Coastguard Worker // regardless of what they say.
3147*6777b538SAndroid Build Coastguard Worker if (response_.unused_since_prefetch) {
3148*6777b538SAndroid Build Coastguard Worker return false;
3149*6777b538SAndroid Build Coastguard Worker }
3150*6777b538SAndroid Build Coastguard Worker
3151*6777b538SAndroid Build Coastguard Worker // Has an e-tag or last-modified: we can probably send a conditional request,
3152*6777b538SAndroid Build Coastguard Worker // so it's potentially useful.
3153*6777b538SAndroid Build Coastguard Worker std::string etag_ignored, last_modified_ignored;
3154*6777b538SAndroid Build Coastguard Worker if (IsResponseConditionalizable(&etag_ignored, &last_modified_ignored)) {
3155*6777b538SAndroid Build Coastguard Worker return false;
3156*6777b538SAndroid Build Coastguard Worker }
3157*6777b538SAndroid Build Coastguard Worker
3158*6777b538SAndroid Build Coastguard Worker // If none of the above is true and the entry has zero freshness, then it
3159*6777b538SAndroid Build Coastguard Worker // won't be usable absent load flag override.
3160*6777b538SAndroid Build Coastguard Worker return response_.headers->GetFreshnessLifetimes(response_.response_time)
3161*6777b538SAndroid Build Coastguard Worker .freshness.is_zero();
3162*6777b538SAndroid Build Coastguard Worker }
3163*6777b538SAndroid Build Coastguard Worker
3164*6777b538SAndroid Build Coastguard Worker // We just received some headers from the server. We may have asked for a range,
3165*6777b538SAndroid Build Coastguard Worker // in which case partial_ has an object. This could be the first network request
3166*6777b538SAndroid Build Coastguard Worker // we make to fulfill the original request, or we may be already reading (from
3167*6777b538SAndroid Build Coastguard Worker // the net and / or the cache). If we are not expecting a certain response, we
3168*6777b538SAndroid Build Coastguard Worker // just bypass the cache for this request (but again, maybe we are reading), and
3169*6777b538SAndroid Build Coastguard Worker // delete partial_ (so we are not able to "fix" the headers that we return to
3170*6777b538SAndroid Build Coastguard Worker // the user). This results in either a weird response for the caller (we don't
3171*6777b538SAndroid Build Coastguard Worker // expect it after all), or maybe a range that was not exactly what it was asked
3172*6777b538SAndroid Build Coastguard Worker // for.
3173*6777b538SAndroid Build Coastguard Worker //
3174*6777b538SAndroid Build Coastguard Worker // If the server is simply telling us that the resource has changed, we delete
3175*6777b538SAndroid Build Coastguard Worker // the cached entry and restart the request as the caller intended (by returning
3176*6777b538SAndroid Build Coastguard Worker // false from this method). However, we may not be able to do that at any point,
3177*6777b538SAndroid Build Coastguard Worker // for instance if we already returned the headers to the user.
3178*6777b538SAndroid Build Coastguard Worker //
3179*6777b538SAndroid Build Coastguard Worker // WARNING: Whenever this code returns false, it has to make sure that the next
3180*6777b538SAndroid Build Coastguard Worker // time it is called it will return true so that we don't keep retrying the
3181*6777b538SAndroid Build Coastguard Worker // request.
ValidatePartialResponse()3182*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::ValidatePartialResponse() {
3183*6777b538SAndroid Build Coastguard Worker const HttpResponseHeaders* headers = new_response_->headers.get();
3184*6777b538SAndroid Build Coastguard Worker int response_code = headers->response_code();
3185*6777b538SAndroid Build Coastguard Worker bool partial_response = (response_code == net::HTTP_PARTIAL_CONTENT);
3186*6777b538SAndroid Build Coastguard Worker handling_206_ = false;
3187*6777b538SAndroid Build Coastguard Worker
3188*6777b538SAndroid Build Coastguard Worker if (!entry_ || method_ != "GET") {
3189*6777b538SAndroid Build Coastguard Worker return true;
3190*6777b538SAndroid Build Coastguard Worker }
3191*6777b538SAndroid Build Coastguard Worker
3192*6777b538SAndroid Build Coastguard Worker if (invalid_range_) {
3193*6777b538SAndroid Build Coastguard Worker // We gave up trying to match this request with the stored data. If the
3194*6777b538SAndroid Build Coastguard Worker // server is ok with the request, delete the entry, otherwise just ignore
3195*6777b538SAndroid Build Coastguard Worker // this request
3196*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
3197*6777b538SAndroid Build Coastguard Worker if (partial_response || response_code == net::HTTP_OK) {
3198*6777b538SAndroid Build Coastguard Worker DoomPartialEntry(true);
3199*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
3200*6777b538SAndroid Build Coastguard Worker } else {
3201*6777b538SAndroid Build Coastguard Worker if (response_code == net::HTTP_NOT_MODIFIED) {
3202*6777b538SAndroid Build Coastguard Worker // Change the response code of the request to be 416 (Requested range
3203*6777b538SAndroid Build Coastguard Worker // not satisfiable).
3204*6777b538SAndroid Build Coastguard Worker SetResponse(*new_response_);
3205*6777b538SAndroid Build Coastguard Worker partial_->FixResponseHeaders(response_.headers.get(), false);
3206*6777b538SAndroid Build Coastguard Worker }
3207*6777b538SAndroid Build Coastguard Worker IgnoreRangeRequest();
3208*6777b538SAndroid Build Coastguard Worker }
3209*6777b538SAndroid Build Coastguard Worker return true;
3210*6777b538SAndroid Build Coastguard Worker }
3211*6777b538SAndroid Build Coastguard Worker
3212*6777b538SAndroid Build Coastguard Worker if (!partial_) {
3213*6777b538SAndroid Build Coastguard Worker // We are not expecting 206 but we may have one.
3214*6777b538SAndroid Build Coastguard Worker if (partial_response) {
3215*6777b538SAndroid Build Coastguard Worker IgnoreRangeRequest();
3216*6777b538SAndroid Build Coastguard Worker }
3217*6777b538SAndroid Build Coastguard Worker
3218*6777b538SAndroid Build Coastguard Worker return true;
3219*6777b538SAndroid Build Coastguard Worker }
3220*6777b538SAndroid Build Coastguard Worker
3221*6777b538SAndroid Build Coastguard Worker // TODO(rvargas): Do we need to consider other results here?.
3222*6777b538SAndroid Build Coastguard Worker bool failure = response_code == net::HTTP_OK ||
3223*6777b538SAndroid Build Coastguard Worker response_code == net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE;
3224*6777b538SAndroid Build Coastguard Worker
3225*6777b538SAndroid Build Coastguard Worker if (partial_->IsCurrentRangeCached()) {
3226*6777b538SAndroid Build Coastguard Worker // We asked for "If-None-Match: " so a 206 means a new object.
3227*6777b538SAndroid Build Coastguard Worker if (partial_response) {
3228*6777b538SAndroid Build Coastguard Worker failure = true;
3229*6777b538SAndroid Build Coastguard Worker }
3230*6777b538SAndroid Build Coastguard Worker
3231*6777b538SAndroid Build Coastguard Worker if (response_code == net::HTTP_NOT_MODIFIED &&
3232*6777b538SAndroid Build Coastguard Worker partial_->ResponseHeadersOK(headers)) {
3233*6777b538SAndroid Build Coastguard Worker return true;
3234*6777b538SAndroid Build Coastguard Worker }
3235*6777b538SAndroid Build Coastguard Worker } else {
3236*6777b538SAndroid Build Coastguard Worker // We asked for "If-Range: " so a 206 means just another range.
3237*6777b538SAndroid Build Coastguard Worker if (partial_response) {
3238*6777b538SAndroid Build Coastguard Worker if (partial_->ResponseHeadersOK(headers)) {
3239*6777b538SAndroid Build Coastguard Worker handling_206_ = true;
3240*6777b538SAndroid Build Coastguard Worker return true;
3241*6777b538SAndroid Build Coastguard Worker } else {
3242*6777b538SAndroid Build Coastguard Worker failure = true;
3243*6777b538SAndroid Build Coastguard Worker }
3244*6777b538SAndroid Build Coastguard Worker }
3245*6777b538SAndroid Build Coastguard Worker
3246*6777b538SAndroid Build Coastguard Worker if (!reading_ && !is_sparse_ && !partial_response) {
3247*6777b538SAndroid Build Coastguard Worker // See if we can ignore the fact that we issued a byte range request.
3248*6777b538SAndroid Build Coastguard Worker // If the server sends 200, just store it. If it sends an error, redirect
3249*6777b538SAndroid Build Coastguard Worker // or something else, we may store the response as long as we didn't have
3250*6777b538SAndroid Build Coastguard Worker // anything already stored.
3251*6777b538SAndroid Build Coastguard Worker if (response_code == net::HTTP_OK ||
3252*6777b538SAndroid Build Coastguard Worker (!truncated_ && response_code != net::HTTP_NOT_MODIFIED &&
3253*6777b538SAndroid Build Coastguard Worker response_code != net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE)) {
3254*6777b538SAndroid Build Coastguard Worker // The server is sending something else, and we can save it.
3255*6777b538SAndroid Build Coastguard Worker DCHECK((truncated_ && !partial_->IsLastRange()) || range_requested_);
3256*6777b538SAndroid Build Coastguard Worker partial_.reset();
3257*6777b538SAndroid Build Coastguard Worker truncated_ = false;
3258*6777b538SAndroid Build Coastguard Worker return true;
3259*6777b538SAndroid Build Coastguard Worker }
3260*6777b538SAndroid Build Coastguard Worker }
3261*6777b538SAndroid Build Coastguard Worker
3262*6777b538SAndroid Build Coastguard Worker // 304 is not expected here, but we'll spare the entry (unless it was
3263*6777b538SAndroid Build Coastguard Worker // truncated).
3264*6777b538SAndroid Build Coastguard Worker if (truncated_) {
3265*6777b538SAndroid Build Coastguard Worker failure = true;
3266*6777b538SAndroid Build Coastguard Worker }
3267*6777b538SAndroid Build Coastguard Worker }
3268*6777b538SAndroid Build Coastguard Worker
3269*6777b538SAndroid Build Coastguard Worker if (failure) {
3270*6777b538SAndroid Build Coastguard Worker // We cannot truncate this entry, it has to be deleted.
3271*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
3272*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
3273*6777b538SAndroid Build Coastguard Worker if (is_sparse_ || truncated_) {
3274*6777b538SAndroid Build Coastguard Worker // There was something cached to start with, either sparsed data (206), or
3275*6777b538SAndroid Build Coastguard Worker // a truncated 200, which means that we probably modified the request,
3276*6777b538SAndroid Build Coastguard Worker // adding a byte range or modifying the range requested by the caller.
3277*6777b538SAndroid Build Coastguard Worker if (!reading_ && !partial_->IsLastRange()) {
3278*6777b538SAndroid Build Coastguard Worker // We have not returned anything to the caller yet so it should be safe
3279*6777b538SAndroid Build Coastguard Worker // to issue another network request, this time without us messing up the
3280*6777b538SAndroid Build Coastguard Worker // headers.
3281*6777b538SAndroid Build Coastguard Worker ResetPartialState(true);
3282*6777b538SAndroid Build Coastguard Worker return false;
3283*6777b538SAndroid Build Coastguard Worker }
3284*6777b538SAndroid Build Coastguard Worker LOG(WARNING) << "Failed to revalidate partial entry";
3285*6777b538SAndroid Build Coastguard Worker }
3286*6777b538SAndroid Build Coastguard Worker DoomPartialEntry(true);
3287*6777b538SAndroid Build Coastguard Worker return true;
3288*6777b538SAndroid Build Coastguard Worker }
3289*6777b538SAndroid Build Coastguard Worker
3290*6777b538SAndroid Build Coastguard Worker IgnoreRangeRequest();
3291*6777b538SAndroid Build Coastguard Worker return true;
3292*6777b538SAndroid Build Coastguard Worker }
3293*6777b538SAndroid Build Coastguard Worker
IgnoreRangeRequest()3294*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::IgnoreRangeRequest() {
3295*6777b538SAndroid Build Coastguard Worker // We have a problem. We may or may not be reading already (in which case we
3296*6777b538SAndroid Build Coastguard Worker // returned the headers), but we'll just pretend that this request is not
3297*6777b538SAndroid Build Coastguard Worker // using the cache and see what happens. Most likely this is the first
3298*6777b538SAndroid Build Coastguard Worker // response from the server (it's not changing its mind midway, right?).
3299*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
3300*6777b538SAndroid Build Coastguard Worker DoneWithEntry(mode_ != WRITE);
3301*6777b538SAndroid Build Coastguard Worker partial_.reset(nullptr);
3302*6777b538SAndroid Build Coastguard Worker }
3303*6777b538SAndroid Build Coastguard Worker
3304*6777b538SAndroid Build Coastguard Worker // Called to signal to the consumer that we are about to read headers from a
3305*6777b538SAndroid Build Coastguard Worker // cached entry originally read from a given IP endpoint.
DoConnectedCallback()3306*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoConnectedCallback() {
3307*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CONNECTED_CALLBACK_COMPLETE);
3308*6777b538SAndroid Build Coastguard Worker if (connected_callback_.is_null()) {
3309*6777b538SAndroid Build Coastguard Worker return OK;
3310*6777b538SAndroid Build Coastguard Worker }
3311*6777b538SAndroid Build Coastguard Worker
3312*6777b538SAndroid Build Coastguard Worker auto type = response_.was_fetched_via_proxy ? TransportType::kCachedFromProxy
3313*6777b538SAndroid Build Coastguard Worker : TransportType::kCached;
3314*6777b538SAndroid Build Coastguard Worker return connected_callback_.Run(
3315*6777b538SAndroid Build Coastguard Worker TransportInfo(type, response_.remote_endpoint, /*accept_ch_frame_arg=*/"",
3316*6777b538SAndroid Build Coastguard Worker /*cert_is_issued_by_known_root=*/false, kProtoUnknown),
3317*6777b538SAndroid Build Coastguard Worker io_callback_);
3318*6777b538SAndroid Build Coastguard Worker }
3319*6777b538SAndroid Build Coastguard Worker
DoConnectedCallbackComplete(int result)3320*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoConnectedCallbackComplete(int result) {
3321*6777b538SAndroid Build Coastguard Worker if (result != OK) {
3322*6777b538SAndroid Build Coastguard Worker if (result ==
3323*6777b538SAndroid Build Coastguard Worker ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY) {
3324*6777b538SAndroid Build Coastguard Worker DoomInconsistentEntry();
3325*6777b538SAndroid Build Coastguard Worker UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
3326*6777b538SAndroid Build Coastguard Worker TransitionToState(reading_ ? STATE_SEND_REQUEST
3327*6777b538SAndroid Build Coastguard Worker : STATE_HEADERS_PHASE_CANNOT_PROCEED);
3328*6777b538SAndroid Build Coastguard Worker return OK;
3329*6777b538SAndroid Build Coastguard Worker }
3330*6777b538SAndroid Build Coastguard Worker
3331*6777b538SAndroid Build Coastguard Worker if (result == ERR_INCONSISTENT_IP_ADDRESS_SPACE) {
3332*6777b538SAndroid Build Coastguard Worker DoomInconsistentEntry();
3333*6777b538SAndroid Build Coastguard Worker } else {
3334*6777b538SAndroid Build Coastguard Worker // Release the entry for further use - we are done using it.
3335*6777b538SAndroid Build Coastguard Worker DoneWithEntry(/*entry_is_complete=*/true);
3336*6777b538SAndroid Build Coastguard Worker }
3337*6777b538SAndroid Build Coastguard Worker
3338*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
3339*6777b538SAndroid Build Coastguard Worker return result;
3340*6777b538SAndroid Build Coastguard Worker }
3341*6777b538SAndroid Build Coastguard Worker
3342*6777b538SAndroid Build Coastguard Worker if (reading_) {
3343*6777b538SAndroid Build Coastguard Worker // We can only get here if we're reading a partial range of bytes from the
3344*6777b538SAndroid Build Coastguard Worker // cache. In that case, proceed to read the bytes themselves.
3345*6777b538SAndroid Build Coastguard Worker DCHECK(partial_);
3346*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CACHE_READ_DATA);
3347*6777b538SAndroid Build Coastguard Worker } else {
3348*6777b538SAndroid Build Coastguard Worker // Otherwise, we have just read headers from the cache.
3349*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_SETUP_ENTRY_FOR_READ);
3350*6777b538SAndroid Build Coastguard Worker }
3351*6777b538SAndroid Build Coastguard Worker return OK;
3352*6777b538SAndroid Build Coastguard Worker }
3353*6777b538SAndroid Build Coastguard Worker
DoomInconsistentEntry()3354*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::DoomInconsistentEntry() {
3355*6777b538SAndroid Build Coastguard Worker // Explicitly call `DoomActiveEntry()` ourselves before calling
3356*6777b538SAndroid Build Coastguard Worker // `DoneWithEntry()` because we cannot rely on the latter doing it for us.
3357*6777b538SAndroid Build Coastguard Worker // Indeed, `DoneWithEntry(false)` does not call `DoomActiveEntry()` if either
3358*6777b538SAndroid Build Coastguard Worker // of the following conditions hold:
3359*6777b538SAndroid Build Coastguard Worker //
3360*6777b538SAndroid Build Coastguard Worker // - the transaction uses the cache in read-only mode
3361*6777b538SAndroid Build Coastguard Worker // - the transaction has passed the headers phase and is reading
3362*6777b538SAndroid Build Coastguard Worker //
3363*6777b538SAndroid Build Coastguard Worker // Inconsistent cache entries can cause deterministic failures even in
3364*6777b538SAndroid Build Coastguard Worker // read-only mode, so they should be doomed anyway. They can also be detected
3365*6777b538SAndroid Build Coastguard Worker // during the reading phase in the case of split range requests, since those
3366*6777b538SAndroid Build Coastguard Worker // requests can result in multiple connections being obtained to different
3367*6777b538SAndroid Build Coastguard Worker // remote endpoints.
3368*6777b538SAndroid Build Coastguard Worker cache_->DoomActiveEntry(cache_key_);
3369*6777b538SAndroid Build Coastguard Worker DoneWithEntry(/*entry_is_complete=*/false);
3370*6777b538SAndroid Build Coastguard Worker }
3371*6777b538SAndroid Build Coastguard Worker
FixHeadersForHead()3372*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::FixHeadersForHead() {
3373*6777b538SAndroid Build Coastguard Worker if (response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT) {
3374*6777b538SAndroid Build Coastguard Worker response_.headers->RemoveHeader("Content-Range");
3375*6777b538SAndroid Build Coastguard Worker response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK");
3376*6777b538SAndroid Build Coastguard Worker }
3377*6777b538SAndroid Build Coastguard Worker }
3378*6777b538SAndroid Build Coastguard Worker
DoSetupEntryForRead()3379*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoSetupEntryForRead() {
3380*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoSetupEntryForRead",
3381*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_));
3382*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
3383*6777b538SAndroid Build Coastguard Worker ResetNetworkTransaction();
3384*6777b538SAndroid Build Coastguard Worker }
3385*6777b538SAndroid Build Coastguard Worker
3386*6777b538SAndroid Build Coastguard Worker if (!entry_) {
3387*6777b538SAndroid Build Coastguard Worker // Entry got destroyed when twiddling SWR bits.
3388*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
3389*6777b538SAndroid Build Coastguard Worker return OK;
3390*6777b538SAndroid Build Coastguard Worker }
3391*6777b538SAndroid Build Coastguard Worker
3392*6777b538SAndroid Build Coastguard Worker if (partial_) {
3393*6777b538SAndroid Build Coastguard Worker if (truncated_ || is_sparse_ ||
3394*6777b538SAndroid Build Coastguard Worker (!invalid_range_ &&
3395*6777b538SAndroid Build Coastguard Worker (response_.headers->response_code() == net::HTTP_OK ||
3396*6777b538SAndroid Build Coastguard Worker response_.headers->response_code() == net::HTTP_PARTIAL_CONTENT))) {
3397*6777b538SAndroid Build Coastguard Worker // We are going to return the saved response headers to the caller, so
3398*6777b538SAndroid Build Coastguard Worker // we may need to adjust them first. In cases we are handling a range
3399*6777b538SAndroid Build Coastguard Worker // request to a regular entry, we want the response to be a 200 or 206,
3400*6777b538SAndroid Build Coastguard Worker // since others can't really be turned into a 206.
3401*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_PARTIAL_HEADERS_RECEIVED);
3402*6777b538SAndroid Build Coastguard Worker return OK;
3403*6777b538SAndroid Build Coastguard Worker } else {
3404*6777b538SAndroid Build Coastguard Worker partial_.reset();
3405*6777b538SAndroid Build Coastguard Worker }
3406*6777b538SAndroid Build Coastguard Worker }
3407*6777b538SAndroid Build Coastguard Worker
3408*6777b538SAndroid Build Coastguard Worker if (!entry_->IsWritingInProgress()) {
3409*6777b538SAndroid Build Coastguard Worker mode_ = READ;
3410*6777b538SAndroid Build Coastguard Worker }
3411*6777b538SAndroid Build Coastguard Worker
3412*6777b538SAndroid Build Coastguard Worker if (method_ == "HEAD") {
3413*6777b538SAndroid Build Coastguard Worker FixHeadersForHead();
3414*6777b538SAndroid Build Coastguard Worker }
3415*6777b538SAndroid Build Coastguard Worker
3416*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_FINISH_HEADERS);
3417*6777b538SAndroid Build Coastguard Worker return OK;
3418*6777b538SAndroid Build Coastguard Worker }
3419*6777b538SAndroid Build Coastguard Worker
WriteResponseInfoToEntry(const HttpResponseInfo & response,bool truncated)3420*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::WriteResponseInfoToEntry(
3421*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo& response,
3422*6777b538SAndroid Build Coastguard Worker bool truncated) {
3423*6777b538SAndroid Build Coastguard Worker DCHECK(response.headers);
3424*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::WriteResponseInfoToEntry",
3425*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "truncated", truncated);
3426*6777b538SAndroid Build Coastguard Worker
3427*6777b538SAndroid Build Coastguard Worker if (!entry_) {
3428*6777b538SAndroid Build Coastguard Worker return OK;
3429*6777b538SAndroid Build Coastguard Worker }
3430*6777b538SAndroid Build Coastguard Worker
3431*6777b538SAndroid Build Coastguard Worker net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO);
3432*6777b538SAndroid Build Coastguard Worker
3433*6777b538SAndroid Build Coastguard Worker // Do not cache content with cert errors. This is to prevent not reporting net
3434*6777b538SAndroid Build Coastguard Worker // errors when loading a resource from the cache. When we load a page over
3435*6777b538SAndroid Build Coastguard Worker // HTTPS with a cert error we show an SSL blocking page. If the user clicks
3436*6777b538SAndroid Build Coastguard Worker // proceed we reload the resource ignoring the errors. The loaded resource is
3437*6777b538SAndroid Build Coastguard Worker // then cached. If that resource is subsequently loaded from the cache, no
3438*6777b538SAndroid Build Coastguard Worker // net error is reported (even though the cert status contains the actual
3439*6777b538SAndroid Build Coastguard Worker // errors) and no SSL blocking page is shown. An alternative would be to
3440*6777b538SAndroid Build Coastguard Worker // reverse-map the cert status to a net error and replay the net error.
3441*6777b538SAndroid Build Coastguard Worker if (IsCertStatusError(response.ssl_info.cert_status) ||
3442*6777b538SAndroid Build Coastguard Worker ShouldDisableCaching(*response.headers)) {
3443*6777b538SAndroid Build Coastguard Worker if (partial_) {
3444*6777b538SAndroid Build Coastguard Worker partial_->FixResponseHeaders(response_.headers.get(), true);
3445*6777b538SAndroid Build Coastguard Worker }
3446*6777b538SAndroid Build Coastguard Worker
3447*6777b538SAndroid Build Coastguard Worker bool stopped = StopCachingImpl(false);
3448*6777b538SAndroid Build Coastguard Worker DCHECK(stopped);
3449*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
3450*6777b538SAndroid Build Coastguard Worker OK);
3451*6777b538SAndroid Build Coastguard Worker return OK;
3452*6777b538SAndroid Build Coastguard Worker }
3453*6777b538SAndroid Build Coastguard Worker
3454*6777b538SAndroid Build Coastguard Worker if (truncated) {
3455*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(net::HTTP_OK, response.headers->response_code());
3456*6777b538SAndroid Build Coastguard Worker }
3457*6777b538SAndroid Build Coastguard Worker
3458*6777b538SAndroid Build Coastguard Worker // When writing headers, we normally only write the non-transient headers.
3459*6777b538SAndroid Build Coastguard Worker bool skip_transient_headers = true;
3460*6777b538SAndroid Build Coastguard Worker auto data = base::MakeRefCounted<PickledIOBuffer>();
3461*6777b538SAndroid Build Coastguard Worker response.Persist(data->pickle(), skip_transient_headers, truncated);
3462*6777b538SAndroid Build Coastguard Worker data->Done();
3463*6777b538SAndroid Build Coastguard Worker
3464*6777b538SAndroid Build Coastguard Worker io_buf_len_ = data->pickle()->size();
3465*6777b538SAndroid Build Coastguard Worker
3466*6777b538SAndroid Build Coastguard Worker // Summarize some info on cacheability in memory. Don't do it if doomed
3467*6777b538SAndroid Build Coastguard Worker // since then |entry_| isn't definitive for |cache_key_|.
3468*6777b538SAndroid Build Coastguard Worker if (!entry_->IsDoomed()) {
3469*6777b538SAndroid Build Coastguard Worker cache_->GetCurrentBackend()->SetEntryInMemoryData(
3470*6777b538SAndroid Build Coastguard Worker cache_key_, ComputeUnusablePerCachingHeaders()
3471*6777b538SAndroid Build Coastguard Worker ? HINT_UNUSABLE_PER_CACHING_HEADERS
3472*6777b538SAndroid Build Coastguard Worker : 0);
3473*6777b538SAndroid Build Coastguard Worker }
3474*6777b538SAndroid Build Coastguard Worker
3475*6777b538SAndroid Build Coastguard Worker BeginDiskCacheAccessTimeCount();
3476*6777b538SAndroid Build Coastguard Worker return entry_->GetEntry()->WriteData(kResponseInfoIndex, 0, data.get(),
3477*6777b538SAndroid Build Coastguard Worker io_buf_len_, io_callback_, true);
3478*6777b538SAndroid Build Coastguard Worker }
3479*6777b538SAndroid Build Coastguard Worker
OnWriteResponseInfoToEntryComplete(int result)3480*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
3481*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT(
3482*6777b538SAndroid Build Coastguard Worker "net", "HttpCacheTransaction::OnWriteResponseInfoToEntryComplete",
3483*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "result", result);
3484*6777b538SAndroid Build Coastguard Worker EndDiskCacheAccessTimeCount(DiskCacheAccessType::kWrite);
3485*6777b538SAndroid Build Coastguard Worker if (!entry_) {
3486*6777b538SAndroid Build Coastguard Worker return OK;
3487*6777b538SAndroid Build Coastguard Worker }
3488*6777b538SAndroid Build Coastguard Worker net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
3489*6777b538SAndroid Build Coastguard Worker result);
3490*6777b538SAndroid Build Coastguard Worker
3491*6777b538SAndroid Build Coastguard Worker if (result != io_buf_len_) {
3492*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "failed to write response info to cache";
3493*6777b538SAndroid Build Coastguard Worker DoneWithEntry(false);
3494*6777b538SAndroid Build Coastguard Worker }
3495*6777b538SAndroid Build Coastguard Worker return OK;
3496*6777b538SAndroid Build Coastguard Worker }
3497*6777b538SAndroid Build Coastguard Worker
StopCachingImpl(bool success)3498*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::StopCachingImpl(bool success) {
3499*6777b538SAndroid Build Coastguard Worker bool stopped = false;
3500*6777b538SAndroid Build Coastguard Worker // Let writers know so that it doesn't attempt to write to the cache.
3501*6777b538SAndroid Build Coastguard Worker if (InWriters()) {
3502*6777b538SAndroid Build Coastguard Worker stopped = entry_->writers()->StopCaching(success /* keep_entry */);
3503*6777b538SAndroid Build Coastguard Worker if (stopped) {
3504*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
3505*6777b538SAndroid Build Coastguard Worker }
3506*6777b538SAndroid Build Coastguard Worker } else if (entry_) {
3507*6777b538SAndroid Build Coastguard Worker stopped = true;
3508*6777b538SAndroid Build Coastguard Worker DoneWithEntry(success /* entry_is_complete */);
3509*6777b538SAndroid Build Coastguard Worker }
3510*6777b538SAndroid Build Coastguard Worker return stopped;
3511*6777b538SAndroid Build Coastguard Worker }
3512*6777b538SAndroid Build Coastguard Worker
DoneWithEntry(bool entry_is_complete)3513*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::DoneWithEntry(bool entry_is_complete) {
3514*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_INSTANT("net", "HttpCacheTransaction::DoneWithEntry",
3515*6777b538SAndroid Build Coastguard Worker perfetto::Track(trace_id_), "entry_is_complete",
3516*6777b538SAndroid Build Coastguard Worker entry_is_complete);
3517*6777b538SAndroid Build Coastguard Worker if (!entry_) {
3518*6777b538SAndroid Build Coastguard Worker return;
3519*6777b538SAndroid Build Coastguard Worker }
3520*6777b538SAndroid Build Coastguard Worker
3521*6777b538SAndroid Build Coastguard Worker // Our `entry_` member must be valid throughout this call since
3522*6777b538SAndroid Build Coastguard Worker // `DoneWithEntry` calls into
3523*6777b538SAndroid Build Coastguard Worker // `HttpCache::Transaction::WriterAboutToBeRemovedFromEntry` which accesses
3524*6777b538SAndroid Build Coastguard Worker // `this`'s `entry_` member.
3525*6777b538SAndroid Build Coastguard Worker cache_->DoneWithEntry(entry_, this, entry_is_complete, partial_ != nullptr);
3526*6777b538SAndroid Build Coastguard Worker entry_.reset();
3527*6777b538SAndroid Build Coastguard Worker mode_ = NONE; // switch to 'pass through' mode
3528*6777b538SAndroid Build Coastguard Worker }
3529*6777b538SAndroid Build Coastguard Worker
OnCacheReadError(int result,bool restart)3530*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
3531*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "ReadData failed: " << result;
3532*6777b538SAndroid Build Coastguard Worker
3533*6777b538SAndroid Build Coastguard Worker // Avoid using this entry in the future.
3534*6777b538SAndroid Build Coastguard Worker if (cache_.get()) {
3535*6777b538SAndroid Build Coastguard Worker cache_->DoomActiveEntry(cache_key_);
3536*6777b538SAndroid Build Coastguard Worker }
3537*6777b538SAndroid Build Coastguard Worker
3538*6777b538SAndroid Build Coastguard Worker if (restart) {
3539*6777b538SAndroid Build Coastguard Worker DCHECK(!reading_);
3540*6777b538SAndroid Build Coastguard Worker DCHECK(!network_trans_.get());
3541*6777b538SAndroid Build Coastguard Worker
3542*6777b538SAndroid Build Coastguard Worker // Since we are going to add this to a new entry, not recording histograms
3543*6777b538SAndroid Build Coastguard Worker // or setting mode to NONE at this point by invoking the wrapper
3544*6777b538SAndroid Build Coastguard Worker // DoneWithEntry.
3545*6777b538SAndroid Build Coastguard Worker //
3546*6777b538SAndroid Build Coastguard Worker // Our `entry_` member must be valid throughout this call since
3547*6777b538SAndroid Build Coastguard Worker // `DoneWithEntry` calls into
3548*6777b538SAndroid Build Coastguard Worker // `HttpCache::Transaction::WriterAboutToBeRemovedFromEntry` which accesses
3549*6777b538SAndroid Build Coastguard Worker // `this`'s `entry_` member.
3550*6777b538SAndroid Build Coastguard Worker cache_->DoneWithEntry(entry_, this, true /* entry_is_complete */,
3551*6777b538SAndroid Build Coastguard Worker partial_ != nullptr);
3552*6777b538SAndroid Build Coastguard Worker entry_.reset();
3553*6777b538SAndroid Build Coastguard Worker is_sparse_ = false;
3554*6777b538SAndroid Build Coastguard Worker // It's OK to use PartialData::RestoreHeaders here as |restart| is only set
3555*6777b538SAndroid Build Coastguard Worker // when the HttpResponseInfo couldn't even be read, at which point it's
3556*6777b538SAndroid Build Coastguard Worker // too early for range info in |partial_| to have changed.
3557*6777b538SAndroid Build Coastguard Worker if (partial_) {
3558*6777b538SAndroid Build Coastguard Worker partial_->RestoreHeaders(&custom_request_->extra_headers);
3559*6777b538SAndroid Build Coastguard Worker }
3560*6777b538SAndroid Build Coastguard Worker partial_.reset();
3561*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_GET_BACKEND);
3562*6777b538SAndroid Build Coastguard Worker return OK;
3563*6777b538SAndroid Build Coastguard Worker }
3564*6777b538SAndroid Build Coastguard Worker
3565*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
3566*6777b538SAndroid Build Coastguard Worker return ERR_CACHE_READ_FAILURE;
3567*6777b538SAndroid Build Coastguard Worker }
3568*6777b538SAndroid Build Coastguard Worker
OnCacheLockTimeout(base::TimeTicks start_time)3569*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::OnCacheLockTimeout(base::TimeTicks start_time) {
3570*6777b538SAndroid Build Coastguard Worker if (entry_lock_waiting_since_ != start_time) {
3571*6777b538SAndroid Build Coastguard Worker return;
3572*6777b538SAndroid Build Coastguard Worker }
3573*6777b538SAndroid Build Coastguard Worker
3574*6777b538SAndroid Build Coastguard Worker DCHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
3575*6777b538SAndroid Build Coastguard Worker next_state_ == STATE_FINISH_HEADERS_COMPLETE || waiting_for_cache_io_);
3576*6777b538SAndroid Build Coastguard Worker
3577*6777b538SAndroid Build Coastguard Worker if (!cache_) {
3578*6777b538SAndroid Build Coastguard Worker return;
3579*6777b538SAndroid Build Coastguard Worker }
3580*6777b538SAndroid Build Coastguard Worker
3581*6777b538SAndroid Build Coastguard Worker if (next_state_ == STATE_ADD_TO_ENTRY_COMPLETE || waiting_for_cache_io_) {
3582*6777b538SAndroid Build Coastguard Worker cache_->RemovePendingTransaction(this);
3583*6777b538SAndroid Build Coastguard Worker } else {
3584*6777b538SAndroid Build Coastguard Worker DoneWithEntry(false /* entry_is_complete */);
3585*6777b538SAndroid Build Coastguard Worker }
3586*6777b538SAndroid Build Coastguard Worker OnCacheIOComplete(ERR_CACHE_LOCK_TIMEOUT);
3587*6777b538SAndroid Build Coastguard Worker }
3588*6777b538SAndroid Build Coastguard Worker
DoomPartialEntry(bool delete_object)3589*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
3590*6777b538SAndroid Build Coastguard Worker DVLOG(2) << "DoomPartialEntry";
3591*6777b538SAndroid Build Coastguard Worker if (entry_ && !entry_->IsDoomed()) {
3592*6777b538SAndroid Build Coastguard Worker int rv = cache_->DoomEntry(cache_key_, nullptr);
3593*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
3594*6777b538SAndroid Build Coastguard Worker }
3595*6777b538SAndroid Build Coastguard Worker
3596*6777b538SAndroid Build Coastguard Worker // Our `entry_` member must be valid throughout this call since
3597*6777b538SAndroid Build Coastguard Worker // `DoneWithEntry` calls into
3598*6777b538SAndroid Build Coastguard Worker // `HttpCache::Transaction::WriterAboutToBeRemovedFromEntry` which accesses
3599*6777b538SAndroid Build Coastguard Worker // `this`'s `entry_` member.
3600*6777b538SAndroid Build Coastguard Worker cache_->DoneWithEntry(entry_, this, false /* entry_is_complete */,
3601*6777b538SAndroid Build Coastguard Worker partial_ != nullptr);
3602*6777b538SAndroid Build Coastguard Worker entry_.reset();
3603*6777b538SAndroid Build Coastguard Worker is_sparse_ = false;
3604*6777b538SAndroid Build Coastguard Worker truncated_ = false;
3605*6777b538SAndroid Build Coastguard Worker if (delete_object) {
3606*6777b538SAndroid Build Coastguard Worker partial_.reset(nullptr);
3607*6777b538SAndroid Build Coastguard Worker }
3608*6777b538SAndroid Build Coastguard Worker }
3609*6777b538SAndroid Build Coastguard Worker
DoPartialCacheReadCompleted(int result)3610*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
3611*6777b538SAndroid Build Coastguard Worker partial_->OnCacheReadCompleted(result);
3612*6777b538SAndroid Build Coastguard Worker
3613*6777b538SAndroid Build Coastguard Worker if (result == 0 && mode_ == READ_WRITE) {
3614*6777b538SAndroid Build Coastguard Worker // We need to move on to the next range.
3615*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_START_PARTIAL_CACHE_VALIDATION);
3616*6777b538SAndroid Build Coastguard Worker } else if (result < 0) {
3617*6777b538SAndroid Build Coastguard Worker return OnCacheReadError(result, false);
3618*6777b538SAndroid Build Coastguard Worker } else {
3619*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_NONE);
3620*6777b538SAndroid Build Coastguard Worker }
3621*6777b538SAndroid Build Coastguard Worker return result;
3622*6777b538SAndroid Build Coastguard Worker }
3623*6777b538SAndroid Build Coastguard Worker
DoRestartPartialRequest()3624*6777b538SAndroid Build Coastguard Worker int HttpCache::Transaction::DoRestartPartialRequest() {
3625*6777b538SAndroid Build Coastguard Worker // The stored data cannot be used. Get rid of it and restart this request.
3626*6777b538SAndroid Build Coastguard Worker net_log_.AddEvent(NetLogEventType::HTTP_CACHE_RESTART_PARTIAL_REQUEST);
3627*6777b538SAndroid Build Coastguard Worker
3628*6777b538SAndroid Build Coastguard Worker // WRITE + Doom + STATE_INIT_ENTRY == STATE_CREATE_ENTRY (without an attempt
3629*6777b538SAndroid Build Coastguard Worker // to Doom the entry again).
3630*6777b538SAndroid Build Coastguard Worker ResetPartialState(!range_requested_);
3631*6777b538SAndroid Build Coastguard Worker
3632*6777b538SAndroid Build Coastguard Worker // Change mode to WRITE after ResetPartialState as that may have changed the
3633*6777b538SAndroid Build Coastguard Worker // mode to NONE.
3634*6777b538SAndroid Build Coastguard Worker mode_ = WRITE;
3635*6777b538SAndroid Build Coastguard Worker TransitionToState(STATE_CREATE_ENTRY);
3636*6777b538SAndroid Build Coastguard Worker return OK;
3637*6777b538SAndroid Build Coastguard Worker }
3638*6777b538SAndroid Build Coastguard Worker
ResetPartialState(bool delete_object)3639*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::ResetPartialState(bool delete_object) {
3640*6777b538SAndroid Build Coastguard Worker partial_->RestoreHeaders(&custom_request_->extra_headers);
3641*6777b538SAndroid Build Coastguard Worker DoomPartialEntry(delete_object);
3642*6777b538SAndroid Build Coastguard Worker
3643*6777b538SAndroid Build Coastguard Worker if (!delete_object) {
3644*6777b538SAndroid Build Coastguard Worker // The simplest way to re-initialize partial_ is to create a new object.
3645*6777b538SAndroid Build Coastguard Worker partial_ = std::make_unique<PartialData>();
3646*6777b538SAndroid Build Coastguard Worker
3647*6777b538SAndroid Build Coastguard Worker // Reset the range header to the original value (http://crbug.com/820599).
3648*6777b538SAndroid Build Coastguard Worker custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
3649*6777b538SAndroid Build Coastguard Worker if (partial_->Init(initial_request_->extra_headers)) {
3650*6777b538SAndroid Build Coastguard Worker partial_->SetHeaders(custom_request_->extra_headers);
3651*6777b538SAndroid Build Coastguard Worker } else {
3652*6777b538SAndroid Build Coastguard Worker partial_.reset();
3653*6777b538SAndroid Build Coastguard Worker }
3654*6777b538SAndroid Build Coastguard Worker }
3655*6777b538SAndroid Build Coastguard Worker }
3656*6777b538SAndroid Build Coastguard Worker
ResetNetworkTransaction()3657*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::ResetNetworkTransaction() {
3658*6777b538SAndroid Build Coastguard Worker SaveNetworkTransactionInfo(*network_trans_);
3659*6777b538SAndroid Build Coastguard Worker network_trans_.reset();
3660*6777b538SAndroid Build Coastguard Worker }
3661*6777b538SAndroid Build Coastguard Worker
network_transaction() const3662*6777b538SAndroid Build Coastguard Worker const HttpTransaction* HttpCache::Transaction::network_transaction() const {
3663*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
3664*6777b538SAndroid Build Coastguard Worker return network_trans_.get();
3665*6777b538SAndroid Build Coastguard Worker }
3666*6777b538SAndroid Build Coastguard Worker if (InWriters()) {
3667*6777b538SAndroid Build Coastguard Worker return entry_->writers()->network_transaction();
3668*6777b538SAndroid Build Coastguard Worker }
3669*6777b538SAndroid Build Coastguard Worker return nullptr;
3670*6777b538SAndroid Build Coastguard Worker }
3671*6777b538SAndroid Build Coastguard Worker
3672*6777b538SAndroid Build Coastguard Worker const HttpTransaction*
GetOwnedOrMovedNetworkTransaction() const3673*6777b538SAndroid Build Coastguard Worker HttpCache::Transaction::GetOwnedOrMovedNetworkTransaction() const {
3674*6777b538SAndroid Build Coastguard Worker if (network_trans_) {
3675*6777b538SAndroid Build Coastguard Worker return network_trans_.get();
3676*6777b538SAndroid Build Coastguard Worker }
3677*6777b538SAndroid Build Coastguard Worker if (InWriters() && moved_network_transaction_to_writers_) {
3678*6777b538SAndroid Build Coastguard Worker return entry_->writers()->network_transaction();
3679*6777b538SAndroid Build Coastguard Worker }
3680*6777b538SAndroid Build Coastguard Worker return nullptr;
3681*6777b538SAndroid Build Coastguard Worker }
3682*6777b538SAndroid Build Coastguard Worker
network_transaction()3683*6777b538SAndroid Build Coastguard Worker HttpTransaction* HttpCache::Transaction::network_transaction() {
3684*6777b538SAndroid Build Coastguard Worker return const_cast<HttpTransaction*>(
3685*6777b538SAndroid Build Coastguard Worker static_cast<const Transaction*>(this)->network_transaction());
3686*6777b538SAndroid Build Coastguard Worker }
3687*6777b538SAndroid Build Coastguard Worker
3688*6777b538SAndroid Build Coastguard Worker // Histogram data from the end of 2010 show the following distribution of
3689*6777b538SAndroid Build Coastguard Worker // response headers:
3690*6777b538SAndroid Build Coastguard Worker //
3691*6777b538SAndroid Build Coastguard Worker // Content-Length............... 87%
3692*6777b538SAndroid Build Coastguard Worker // Date......................... 98%
3693*6777b538SAndroid Build Coastguard Worker // Last-Modified................ 49%
3694*6777b538SAndroid Build Coastguard Worker // Etag......................... 19%
3695*6777b538SAndroid Build Coastguard Worker // Accept-Ranges: bytes......... 25%
3696*6777b538SAndroid Build Coastguard Worker // Accept-Ranges: none.......... 0.4%
3697*6777b538SAndroid Build Coastguard Worker // Strong Validator............. 50%
3698*6777b538SAndroid Build Coastguard Worker // Strong Validator + ranges.... 24%
3699*6777b538SAndroid Build Coastguard Worker // Strong Validator + CL........ 49%
3700*6777b538SAndroid Build Coastguard Worker //
CanResume(bool has_data)3701*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::CanResume(bool has_data) {
3702*6777b538SAndroid Build Coastguard Worker // Double check that there is something worth keeping.
3703*6777b538SAndroid Build Coastguard Worker if (has_data && !entry_->GetEntry()->GetDataSize(kResponseContentIndex)) {
3704*6777b538SAndroid Build Coastguard Worker return false;
3705*6777b538SAndroid Build Coastguard Worker }
3706*6777b538SAndroid Build Coastguard Worker
3707*6777b538SAndroid Build Coastguard Worker if (method_ != "GET") {
3708*6777b538SAndroid Build Coastguard Worker return false;
3709*6777b538SAndroid Build Coastguard Worker }
3710*6777b538SAndroid Build Coastguard Worker
3711*6777b538SAndroid Build Coastguard Worker // Note that if this is a 206, content-length was already fixed after calling
3712*6777b538SAndroid Build Coastguard Worker // PartialData::ResponseHeadersOK().
3713*6777b538SAndroid Build Coastguard Worker if (response_.headers->GetContentLength() <= 0 ||
3714*6777b538SAndroid Build Coastguard Worker response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
3715*6777b538SAndroid Build Coastguard Worker !response_.headers->HasStrongValidators()) {
3716*6777b538SAndroid Build Coastguard Worker return false;
3717*6777b538SAndroid Build Coastguard Worker }
3718*6777b538SAndroid Build Coastguard Worker
3719*6777b538SAndroid Build Coastguard Worker return true;
3720*6777b538SAndroid Build Coastguard Worker }
3721*6777b538SAndroid Build Coastguard Worker
SetResponse(const HttpResponseInfo & response)3722*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) {
3723*6777b538SAndroid Build Coastguard Worker response_ = response;
3724*6777b538SAndroid Build Coastguard Worker
3725*6777b538SAndroid Build Coastguard Worker if (response_.headers) {
3726*6777b538SAndroid Build Coastguard Worker DCHECK(request_);
3727*6777b538SAndroid Build Coastguard Worker response_.vary_data.Init(*request_, *response_.headers);
3728*6777b538SAndroid Build Coastguard Worker }
3729*6777b538SAndroid Build Coastguard Worker
3730*6777b538SAndroid Build Coastguard Worker SyncCacheEntryStatusToResponse();
3731*6777b538SAndroid Build Coastguard Worker }
3732*6777b538SAndroid Build Coastguard Worker
SetAuthResponse(const HttpResponseInfo & auth_response)3733*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SetAuthResponse(
3734*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo& auth_response) {
3735*6777b538SAndroid Build Coastguard Worker auth_response_ = auth_response;
3736*6777b538SAndroid Build Coastguard Worker SyncCacheEntryStatusToResponse();
3737*6777b538SAndroid Build Coastguard Worker }
3738*6777b538SAndroid Build Coastguard Worker
UpdateCacheEntryStatus(CacheEntryStatus new_cache_entry_status)3739*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::UpdateCacheEntryStatus(
3740*6777b538SAndroid Build Coastguard Worker CacheEntryStatus new_cache_entry_status) {
3741*6777b538SAndroid Build Coastguard Worker DCHECK_NE(CacheEntryStatus::ENTRY_UNDEFINED, new_cache_entry_status);
3742*6777b538SAndroid Build Coastguard Worker if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) {
3743*6777b538SAndroid Build Coastguard Worker return;
3744*6777b538SAndroid Build Coastguard Worker }
3745*6777b538SAndroid Build Coastguard Worker DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED ||
3746*6777b538SAndroid Build Coastguard Worker new_cache_entry_status == CacheEntryStatus::ENTRY_OTHER);
3747*6777b538SAndroid Build Coastguard Worker cache_entry_status_ = new_cache_entry_status;
3748*6777b538SAndroid Build Coastguard Worker SyncCacheEntryStatusToResponse();
3749*6777b538SAndroid Build Coastguard Worker }
3750*6777b538SAndroid Build Coastguard Worker
SyncCacheEntryStatusToResponse()3751*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SyncCacheEntryStatusToResponse() {
3752*6777b538SAndroid Build Coastguard Worker if (cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED) {
3753*6777b538SAndroid Build Coastguard Worker return;
3754*6777b538SAndroid Build Coastguard Worker }
3755*6777b538SAndroid Build Coastguard Worker response_.cache_entry_status = cache_entry_status_;
3756*6777b538SAndroid Build Coastguard Worker if (auth_response_.headers.get()) {
3757*6777b538SAndroid Build Coastguard Worker auth_response_.cache_entry_status = cache_entry_status_;
3758*6777b538SAndroid Build Coastguard Worker }
3759*6777b538SAndroid Build Coastguard Worker }
3760*6777b538SAndroid Build Coastguard Worker
RecordHistograms()3761*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::RecordHistograms() {
3762*6777b538SAndroid Build Coastguard Worker DCHECK(!recorded_histograms_);
3763*6777b538SAndroid Build Coastguard Worker recorded_histograms_ = true;
3764*6777b538SAndroid Build Coastguard Worker
3765*6777b538SAndroid Build Coastguard Worker if (CacheEntryStatus::ENTRY_UNDEFINED == cache_entry_status_) {
3766*6777b538SAndroid Build Coastguard Worker return;
3767*6777b538SAndroid Build Coastguard Worker }
3768*6777b538SAndroid Build Coastguard Worker
3769*6777b538SAndroid Build Coastguard Worker if (!cache_.get() || !cache_->GetCurrentBackend() ||
3770*6777b538SAndroid Build Coastguard Worker cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE ||
3771*6777b538SAndroid Build Coastguard Worker cache_->mode() != NORMAL || method_ != "GET") {
3772*6777b538SAndroid Build Coastguard Worker return;
3773*6777b538SAndroid Build Coastguard Worker }
3774*6777b538SAndroid Build Coastguard Worker
3775*6777b538SAndroid Build Coastguard Worker bool is_third_party = false;
3776*6777b538SAndroid Build Coastguard Worker
3777*6777b538SAndroid Build Coastguard Worker // Given that cache_entry_status_ is not ENTRY_UNDEFINED, the request must
3778*6777b538SAndroid Build Coastguard Worker // have started and so request_ should exist.
3779*6777b538SAndroid Build Coastguard Worker DCHECK(request_);
3780*6777b538SAndroid Build Coastguard Worker if (request_->possibly_top_frame_origin) {
3781*6777b538SAndroid Build Coastguard Worker is_third_party =
3782*6777b538SAndroid Build Coastguard Worker !request_->possibly_top_frame_origin->IsSameOriginWith(request_->url);
3783*6777b538SAndroid Build Coastguard Worker }
3784*6777b538SAndroid Build Coastguard Worker
3785*6777b538SAndroid Build Coastguard Worker std::string mime_type;
3786*6777b538SAndroid Build Coastguard Worker HttpResponseHeaders* response_headers = GetResponseInfo()->headers.get();
3787*6777b538SAndroid Build Coastguard Worker const bool is_no_store = response_headers && response_headers->HasHeaderValue(
3788*6777b538SAndroid Build Coastguard Worker "cache-control", "no-store");
3789*6777b538SAndroid Build Coastguard Worker if (response_headers && response_headers->GetMimeType(&mime_type)) {
3790*6777b538SAndroid Build Coastguard Worker // Record the cache pattern by resource type. The type is inferred by
3791*6777b538SAndroid Build Coastguard Worker // response header mime type, which could be incorrect, so this is just an
3792*6777b538SAndroid Build Coastguard Worker // estimate.
3793*6777b538SAndroid Build Coastguard Worker if (mime_type == "text/html" &&
3794*6777b538SAndroid Build Coastguard Worker (effective_load_flags_ & LOAD_MAIN_FRAME_DEPRECATED)) {
3795*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".MainFrameHTML");
3796*6777b538SAndroid Build Coastguard Worker IS_NO_STORE_HISTOGRAMS(".MainFrameHTML", is_no_store);
3797*6777b538SAndroid Build Coastguard Worker } else if (mime_type == "text/html") {
3798*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".NonMainFrameHTML");
3799*6777b538SAndroid Build Coastguard Worker } else if (mime_type == "text/css") {
3800*6777b538SAndroid Build Coastguard Worker if (is_third_party) {
3801*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".CSSThirdParty");
3802*6777b538SAndroid Build Coastguard Worker }
3803*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".CSS");
3804*6777b538SAndroid Build Coastguard Worker } else if (mime_type.starts_with("image/")) {
3805*6777b538SAndroid Build Coastguard Worker int64_t content_length = response_headers->GetContentLength();
3806*6777b538SAndroid Build Coastguard Worker if (content_length >= 0 && content_length < 100) {
3807*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".TinyImage");
3808*6777b538SAndroid Build Coastguard Worker } else if (content_length >= 100) {
3809*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".NonTinyImage");
3810*6777b538SAndroid Build Coastguard Worker }
3811*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".Image");
3812*6777b538SAndroid Build Coastguard Worker } else if (mime_type.ends_with("javascript") ||
3813*6777b538SAndroid Build Coastguard Worker mime_type.ends_with("ecmascript")) {
3814*6777b538SAndroid Build Coastguard Worker if (is_third_party) {
3815*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".JavaScriptThirdParty");
3816*6777b538SAndroid Build Coastguard Worker }
3817*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".JavaScript");
3818*6777b538SAndroid Build Coastguard Worker } else if (mime_type.find("font") != std::string::npos) {
3819*6777b538SAndroid Build Coastguard Worker if (is_third_party) {
3820*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".FontThirdParty");
3821*6777b538SAndroid Build Coastguard Worker }
3822*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".Font");
3823*6777b538SAndroid Build Coastguard Worker } else if (mime_type.starts_with("audio/")) {
3824*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".Audio");
3825*6777b538SAndroid Build Coastguard Worker } else if (mime_type.starts_with("video/")) {
3826*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS(".Video");
3827*6777b538SAndroid Build Coastguard Worker }
3828*6777b538SAndroid Build Coastguard Worker }
3829*6777b538SAndroid Build Coastguard Worker
3830*6777b538SAndroid Build Coastguard Worker CACHE_STATUS_HISTOGRAMS("");
3831*6777b538SAndroid Build Coastguard Worker IS_NO_STORE_HISTOGRAMS("", is_no_store);
3832*6777b538SAndroid Build Coastguard Worker
3833*6777b538SAndroid Build Coastguard Worker if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) {
3834*6777b538SAndroid Build Coastguard Worker return;
3835*6777b538SAndroid Build Coastguard Worker }
3836*6777b538SAndroid Build Coastguard Worker
3837*6777b538SAndroid Build Coastguard Worker DCHECK(!range_requested_) << "Cache entry status " << cache_entry_status_;
3838*6777b538SAndroid Build Coastguard Worker DCHECK(!first_cache_access_since_.is_null());
3839*6777b538SAndroid Build Coastguard Worker
3840*6777b538SAndroid Build Coastguard Worker base::TimeTicks now = base::TimeTicks::Now();
3841*6777b538SAndroid Build Coastguard Worker base::TimeDelta total_time = now - first_cache_access_since_;
3842*6777b538SAndroid Build Coastguard Worker
3843*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_CUSTOM_TIMES("HttpCache.AccessToDone2", total_time,
3844*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1), base::Seconds(30), 100);
3845*6777b538SAndroid Build Coastguard Worker
3846*6777b538SAndroid Build Coastguard Worker bool did_send_request = !send_request_since_.is_null();
3847*6777b538SAndroid Build Coastguard Worker
3848*6777b538SAndroid Build Coastguard Worker // It's not clear why `did_send_request` can be true when status is
3849*6777b538SAndroid Build Coastguard Worker // ENTRY_USED. See https://crbug.com/1409150.
3850*6777b538SAndroid Build Coastguard Worker // TODO(ricea): Maybe remove ENTRY_USED from the `did_send_request` true
3851*6777b538SAndroid Build Coastguard Worker // branch once that issue is resolved.
3852*6777b538SAndroid Build Coastguard Worker DCHECK(
3853*6777b538SAndroid Build Coastguard Worker (did_send_request &&
3854*6777b538SAndroid Build Coastguard Worker (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
3855*6777b538SAndroid Build Coastguard Worker cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
3856*6777b538SAndroid Build Coastguard Worker cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
3857*6777b538SAndroid Build Coastguard Worker cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
3858*6777b538SAndroid Build Coastguard Worker cache_entry_status_ == CacheEntryStatus::ENTRY_USED)) ||
3859*6777b538SAndroid Build Coastguard Worker (!did_send_request &&
3860*6777b538SAndroid Build Coastguard Worker (cache_entry_status_ == CacheEntryStatus::ENTRY_USED ||
3861*6777b538SAndroid Build Coastguard Worker cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)));
3862*6777b538SAndroid Build Coastguard Worker
3863*6777b538SAndroid Build Coastguard Worker if (!did_send_request) {
3864*6777b538SAndroid Build Coastguard Worker if (cache_entry_status_ == CacheEntryStatus::ENTRY_USED) {
3865*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_CUSTOM_TIMES("HttpCache.AccessToDone2.Used", total_time,
3866*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1), base::Seconds(3), 100);
3867*6777b538SAndroid Build Coastguard Worker }
3868*6777b538SAndroid Build Coastguard Worker return;
3869*6777b538SAndroid Build Coastguard Worker }
3870*6777b538SAndroid Build Coastguard Worker
3871*6777b538SAndroid Build Coastguard Worker base::TimeDelta before_send_time =
3872*6777b538SAndroid Build Coastguard Worker send_request_since_ - first_cache_access_since_;
3873*6777b538SAndroid Build Coastguard Worker
3874*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_CUSTOM_TIMES("HttpCache.AccessToDone2.SentRequest", total_time,
3875*6777b538SAndroid Build Coastguard Worker base::Milliseconds(1), base::Seconds(30), 100);
3876*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
3877*6777b538SAndroid Build Coastguard Worker
3878*6777b538SAndroid Build Coastguard Worker // TODO(gavinp): Remove or minimize these histograms, particularly the ones
3879*6777b538SAndroid Build Coastguard Worker // below this comment after we have received initial data.
3880*6777b538SAndroid Build Coastguard Worker switch (cache_entry_status_) {
3881*6777b538SAndroid Build Coastguard Worker case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: {
3882*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize",
3883*6777b538SAndroid Build Coastguard Worker before_send_time);
3884*6777b538SAndroid Build Coastguard Worker break;
3885*6777b538SAndroid Build Coastguard Worker }
3886*6777b538SAndroid Build Coastguard Worker case CacheEntryStatus::ENTRY_NOT_IN_CACHE: {
3887*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
3888*6777b538SAndroid Build Coastguard Worker break;
3889*6777b538SAndroid Build Coastguard Worker }
3890*6777b538SAndroid Build Coastguard Worker case CacheEntryStatus::ENTRY_VALIDATED: {
3891*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
3892*6777b538SAndroid Build Coastguard Worker break;
3893*6777b538SAndroid Build Coastguard Worker }
3894*6777b538SAndroid Build Coastguard Worker case CacheEntryStatus::ENTRY_UPDATED: {
3895*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
3896*6777b538SAndroid Build Coastguard Worker break;
3897*6777b538SAndroid Build Coastguard Worker }
3898*6777b538SAndroid Build Coastguard Worker default:
3899*6777b538SAndroid Build Coastguard Worker // STATUS_UNDEFINED and STATUS_OTHER are explicitly handled earlier in
3900*6777b538SAndroid Build Coastguard Worker // the function so shouldn't reach here. STATUS_MAX should never be set.
3901*6777b538SAndroid Build Coastguard Worker // Originally it was asserted that STATUS_USED couldn't happen here, but
3902*6777b538SAndroid Build Coastguard Worker // it turns out that it can. We don't have histograms for it, so just
3903*6777b538SAndroid Build Coastguard Worker // ignore it.
3904*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(cache_entry_status_, CacheEntryStatus::ENTRY_USED);
3905*6777b538SAndroid Build Coastguard Worker break;
3906*6777b538SAndroid Build Coastguard Worker }
3907*6777b538SAndroid Build Coastguard Worker
3908*6777b538SAndroid Build Coastguard Worker if (!total_disk_cache_read_time_.is_zero()) {
3909*6777b538SAndroid Build Coastguard Worker base::UmaHistogramTimes("HttpCache.TotalDiskCacheTimePerTransaction.Read",
3910*6777b538SAndroid Build Coastguard Worker total_disk_cache_read_time_);
3911*6777b538SAndroid Build Coastguard Worker }
3912*6777b538SAndroid Build Coastguard Worker if (!total_disk_cache_write_time_.is_zero()) {
3913*6777b538SAndroid Build Coastguard Worker base::UmaHistogramTimes("HttpCache.TotalDiskCacheTimePerTransaction.Write",
3914*6777b538SAndroid Build Coastguard Worker total_disk_cache_write_time_);
3915*6777b538SAndroid Build Coastguard Worker }
3916*6777b538SAndroid Build Coastguard Worker }
3917*6777b538SAndroid Build Coastguard Worker
InWriters() const3918*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::InWriters() const {
3919*6777b538SAndroid Build Coastguard Worker return entry_ && entry_->HasWriters() &&
3920*6777b538SAndroid Build Coastguard Worker entry_->writers()->HasTransaction(this);
3921*6777b538SAndroid Build Coastguard Worker }
3922*6777b538SAndroid Build Coastguard Worker
3923*6777b538SAndroid Build Coastguard Worker HttpCache::Transaction::NetworkTransactionInfo::NetworkTransactionInfo() =
3924*6777b538SAndroid Build Coastguard Worker default;
3925*6777b538SAndroid Build Coastguard Worker HttpCache::Transaction::NetworkTransactionInfo::~NetworkTransactionInfo() =
3926*6777b538SAndroid Build Coastguard Worker default;
3927*6777b538SAndroid Build Coastguard Worker
SaveNetworkTransactionInfo(const HttpTransaction & transaction)3928*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::SaveNetworkTransactionInfo(
3929*6777b538SAndroid Build Coastguard Worker const HttpTransaction& transaction) {
3930*6777b538SAndroid Build Coastguard Worker DCHECK(!network_transaction_info_.old_network_trans_load_timing);
3931*6777b538SAndroid Build Coastguard Worker LoadTimingInfo load_timing;
3932*6777b538SAndroid Build Coastguard Worker if (transaction.GetLoadTimingInfo(&load_timing)) {
3933*6777b538SAndroid Build Coastguard Worker network_transaction_info_.old_network_trans_load_timing =
3934*6777b538SAndroid Build Coastguard Worker std::make_unique<LoadTimingInfo>(load_timing);
3935*6777b538SAndroid Build Coastguard Worker }
3936*6777b538SAndroid Build Coastguard Worker
3937*6777b538SAndroid Build Coastguard Worker network_transaction_info_.total_received_bytes +=
3938*6777b538SAndroid Build Coastguard Worker transaction.GetTotalReceivedBytes();
3939*6777b538SAndroid Build Coastguard Worker network_transaction_info_.total_sent_bytes += transaction.GetTotalSentBytes();
3940*6777b538SAndroid Build Coastguard Worker
3941*6777b538SAndroid Build Coastguard Worker ConnectionAttempts attempts = transaction.GetConnectionAttempts();
3942*6777b538SAndroid Build Coastguard Worker for (const auto& attempt : attempts) {
3943*6777b538SAndroid Build Coastguard Worker network_transaction_info_.old_connection_attempts.push_back(attempt);
3944*6777b538SAndroid Build Coastguard Worker }
3945*6777b538SAndroid Build Coastguard Worker network_transaction_info_.old_remote_endpoint = IPEndPoint();
3946*6777b538SAndroid Build Coastguard Worker transaction.GetRemoteEndpoint(&network_transaction_info_.old_remote_endpoint);
3947*6777b538SAndroid Build Coastguard Worker
3948*6777b538SAndroid Build Coastguard Worker if (transaction.IsMdlMatchForMetrics()) {
3949*6777b538SAndroid Build Coastguard Worker network_transaction_info_.previous_mdl_match_for_metrics = true;
3950*6777b538SAndroid Build Coastguard Worker }
3951*6777b538SAndroid Build Coastguard Worker }
3952*6777b538SAndroid Build Coastguard Worker
OnIOComplete(int result)3953*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::OnIOComplete(int result) {
3954*6777b538SAndroid Build Coastguard Worker if (waiting_for_cache_io_) {
3955*6777b538SAndroid Build Coastguard Worker CHECK_NE(result, ERR_CACHE_RACE);
3956*6777b538SAndroid Build Coastguard Worker // If the HttpCache IO hasn't completed yet, queue the IO result
3957*6777b538SAndroid Build Coastguard Worker // to be processed when the HttpCache IO completes (or times out).
3958*6777b538SAndroid Build Coastguard Worker pending_io_result_ = result;
3959*6777b538SAndroid Build Coastguard Worker } else {
3960*6777b538SAndroid Build Coastguard Worker DoLoop(result);
3961*6777b538SAndroid Build Coastguard Worker }
3962*6777b538SAndroid Build Coastguard Worker }
3963*6777b538SAndroid Build Coastguard Worker
OnCacheIOComplete(int result)3964*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::OnCacheIOComplete(int result) {
3965*6777b538SAndroid Build Coastguard Worker if (waiting_for_cache_io_) {
3966*6777b538SAndroid Build Coastguard Worker // Handle the case of parallel HttpCache transactions being run against
3967*6777b538SAndroid Build Coastguard Worker // network IO.
3968*6777b538SAndroid Build Coastguard Worker waiting_for_cache_io_ = false;
3969*6777b538SAndroid Build Coastguard Worker cache_pending_ = false;
3970*6777b538SAndroid Build Coastguard Worker entry_lock_waiting_since_ = TimeTicks();
3971*6777b538SAndroid Build Coastguard Worker
3972*6777b538SAndroid Build Coastguard Worker if (result == OK) {
3973*6777b538SAndroid Build Coastguard Worker entry_ = std::move(new_entry_);
3974*6777b538SAndroid Build Coastguard Worker if (!entry_->IsWritingInProgress()) {
3975*6777b538SAndroid Build Coastguard Worker open_entry_last_used_ = entry_->GetEntry()->GetLastUsed();
3976*6777b538SAndroid Build Coastguard Worker }
3977*6777b538SAndroid Build Coastguard Worker } else {
3978*6777b538SAndroid Build Coastguard Worker // The HttpCache transaction failed or timed out. Bypass the cache in
3979*6777b538SAndroid Build Coastguard Worker // this case independent of the state of the network IO callback.
3980*6777b538SAndroid Build Coastguard Worker mode_ = NONE;
3981*6777b538SAndroid Build Coastguard Worker }
3982*6777b538SAndroid Build Coastguard Worker new_entry_.reset();
3983*6777b538SAndroid Build Coastguard Worker
3984*6777b538SAndroid Build Coastguard Worker // See if there is a pending IO result that completed while the HttpCache
3985*6777b538SAndroid Build Coastguard Worker // transaction was being processed that now needs to be processed.
3986*6777b538SAndroid Build Coastguard Worker if (pending_io_result_) {
3987*6777b538SAndroid Build Coastguard Worker int stored_result = pending_io_result_.value();
3988*6777b538SAndroid Build Coastguard Worker pending_io_result_ = std::nullopt;
3989*6777b538SAndroid Build Coastguard Worker OnIOComplete(stored_result);
3990*6777b538SAndroid Build Coastguard Worker }
3991*6777b538SAndroid Build Coastguard Worker } else {
3992*6777b538SAndroid Build Coastguard Worker DoLoop(result);
3993*6777b538SAndroid Build Coastguard Worker }
3994*6777b538SAndroid Build Coastguard Worker }
3995*6777b538SAndroid Build Coastguard Worker
TransitionToState(State state)3996*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::TransitionToState(State state) {
3997*6777b538SAndroid Build Coastguard Worker // Ensure that the state is only set once per Do* state.
3998*6777b538SAndroid Build Coastguard Worker DCHECK(in_do_loop_);
3999*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state;
4000*6777b538SAndroid Build Coastguard Worker next_state_ = state;
4001*6777b538SAndroid Build Coastguard Worker }
4002*6777b538SAndroid Build Coastguard Worker
ShouldDisableCaching(const HttpResponseHeaders & headers) const4003*6777b538SAndroid Build Coastguard Worker bool HttpCache::Transaction::ShouldDisableCaching(
4004*6777b538SAndroid Build Coastguard Worker const HttpResponseHeaders& headers) const {
4005*6777b538SAndroid Build Coastguard Worker // Do not cache no-store content.
4006*6777b538SAndroid Build Coastguard Worker if (headers.HasHeaderValue("cache-control", "no-store")) {
4007*6777b538SAndroid Build Coastguard Worker return true;
4008*6777b538SAndroid Build Coastguard Worker }
4009*6777b538SAndroid Build Coastguard Worker
4010*6777b538SAndroid Build Coastguard Worker bool disable_caching = false;
4011*6777b538SAndroid Build Coastguard Worker if (base::FeatureList::IsEnabled(
4012*6777b538SAndroid Build Coastguard Worker features::kTurnOffStreamingMediaCachingAlways) ||
4013*6777b538SAndroid Build Coastguard Worker (base::FeatureList::IsEnabled(
4014*6777b538SAndroid Build Coastguard Worker features::kTurnOffStreamingMediaCachingOnBattery) &&
4015*6777b538SAndroid Build Coastguard Worker IsOnBatteryPower())) {
4016*6777b538SAndroid Build Coastguard Worker // If the feature is always enabled or enabled while we're running on
4017*6777b538SAndroid Build Coastguard Worker // battery, and the acquired content is 'large' and not already cached, and
4018*6777b538SAndroid Build Coastguard Worker // we have a MIME type of audio or video, then disable the cache for this
4019*6777b538SAndroid Build Coastguard Worker // response. We based our initial definition of 'large' on the disk cache
4020*6777b538SAndroid Build Coastguard Worker // maximum block size of 16K, which we observed captures the majority of
4021*6777b538SAndroid Build Coastguard Worker // responses from various MSE implementations.
4022*6777b538SAndroid Build Coastguard Worker static constexpr int kMaxContentSize = 4096 * 4;
4023*6777b538SAndroid Build Coastguard Worker std::string mime_type;
4024*6777b538SAndroid Build Coastguard Worker base::CompareCase insensitive_ascii = base::CompareCase::INSENSITIVE_ASCII;
4025*6777b538SAndroid Build Coastguard Worker if (headers.GetContentLength() > kMaxContentSize &&
4026*6777b538SAndroid Build Coastguard Worker headers.response_code() != net::HTTP_NOT_MODIFIED &&
4027*6777b538SAndroid Build Coastguard Worker headers.GetMimeType(&mime_type) &&
4028*6777b538SAndroid Build Coastguard Worker (base::StartsWith(mime_type, "video", insensitive_ascii) ||
4029*6777b538SAndroid Build Coastguard Worker base::StartsWith(mime_type, "audio", insensitive_ascii))) {
4030*6777b538SAndroid Build Coastguard Worker disable_caching = true;
4031*6777b538SAndroid Build Coastguard Worker }
4032*6777b538SAndroid Build Coastguard Worker }
4033*6777b538SAndroid Build Coastguard Worker return disable_caching;
4034*6777b538SAndroid Build Coastguard Worker }
4035*6777b538SAndroid Build Coastguard Worker
UpdateSecurityHeadersBeforeForwarding()4036*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::UpdateSecurityHeadersBeforeForwarding() {
4037*6777b538SAndroid Build Coastguard Worker // Because of COEP, we need to add CORP to the 304 of resources that set it
4038*6777b538SAndroid Build Coastguard Worker // previously. It will be blocked in the network service otherwise.
4039*6777b538SAndroid Build Coastguard Worker std::string stored_corp_header;
4040*6777b538SAndroid Build Coastguard Worker response_.headers->GetNormalizedHeader("Cross-Origin-Resource-Policy",
4041*6777b538SAndroid Build Coastguard Worker &stored_corp_header);
4042*6777b538SAndroid Build Coastguard Worker if (!stored_corp_header.empty()) {
4043*6777b538SAndroid Build Coastguard Worker new_response_->headers->SetHeader("Cross-Origin-Resource-Policy",
4044*6777b538SAndroid Build Coastguard Worker stored_corp_header);
4045*6777b538SAndroid Build Coastguard Worker }
4046*6777b538SAndroid Build Coastguard Worker return;
4047*6777b538SAndroid Build Coastguard Worker }
4048*6777b538SAndroid Build Coastguard Worker
BeginDiskCacheAccessTimeCount()4049*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::BeginDiskCacheAccessTimeCount() {
4050*6777b538SAndroid Build Coastguard Worker DCHECK(last_disk_cache_access_start_time_.is_null());
4051*6777b538SAndroid Build Coastguard Worker if (partial_) {
4052*6777b538SAndroid Build Coastguard Worker return;
4053*6777b538SAndroid Build Coastguard Worker }
4054*6777b538SAndroid Build Coastguard Worker last_disk_cache_access_start_time_ = TimeTicks::Now();
4055*6777b538SAndroid Build Coastguard Worker }
4056*6777b538SAndroid Build Coastguard Worker
EndDiskCacheAccessTimeCount(DiskCacheAccessType type)4057*6777b538SAndroid Build Coastguard Worker void HttpCache::Transaction::EndDiskCacheAccessTimeCount(
4058*6777b538SAndroid Build Coastguard Worker DiskCacheAccessType type) {
4059*6777b538SAndroid Build Coastguard Worker // We may call this function without actual disk cache access as a result of
4060*6777b538SAndroid Build Coastguard Worker // state change.
4061*6777b538SAndroid Build Coastguard Worker if (last_disk_cache_access_start_time_.is_null()) {
4062*6777b538SAndroid Build Coastguard Worker return;
4063*6777b538SAndroid Build Coastguard Worker }
4064*6777b538SAndroid Build Coastguard Worker base::TimeDelta elapsed =
4065*6777b538SAndroid Build Coastguard Worker TimeTicks::Now() - last_disk_cache_access_start_time_;
4066*6777b538SAndroid Build Coastguard Worker switch (type) {
4067*6777b538SAndroid Build Coastguard Worker case DiskCacheAccessType::kRead:
4068*6777b538SAndroid Build Coastguard Worker total_disk_cache_read_time_ += elapsed;
4069*6777b538SAndroid Build Coastguard Worker break;
4070*6777b538SAndroid Build Coastguard Worker case DiskCacheAccessType::kWrite:
4071*6777b538SAndroid Build Coastguard Worker total_disk_cache_write_time_ += elapsed;
4072*6777b538SAndroid Build Coastguard Worker break;
4073*6777b538SAndroid Build Coastguard Worker }
4074*6777b538SAndroid Build Coastguard Worker last_disk_cache_access_start_time_ = TimeTicks();
4075*6777b538SAndroid Build Coastguard Worker }
4076*6777b538SAndroid Build Coastguard Worker
4077*6777b538SAndroid Build Coastguard Worker } // namespace net
4078