1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 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_writers.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <algorithm>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/disk_cache/disk_cache.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/http/http_cache_transaction.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_info.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/http/http_status_code.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/http/partial_data.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace net {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker namespace {
24*6777b538SAndroid Build Coastguard Worker
IsValidResponseForWriter(bool is_partial,const HttpResponseInfo * response_info)25*6777b538SAndroid Build Coastguard Worker bool IsValidResponseForWriter(bool is_partial,
26*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo* response_info) {
27*6777b538SAndroid Build Coastguard Worker if (!response_info->headers.get()) {
28*6777b538SAndroid Build Coastguard Worker return false;
29*6777b538SAndroid Build Coastguard Worker }
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker // Return false if the response code sent by the server is garbled.
32*6777b538SAndroid Build Coastguard Worker // Both 200 and 304 are valid since concurrent writing is supported.
33*6777b538SAndroid Build Coastguard Worker if (!is_partial &&
34*6777b538SAndroid Build Coastguard Worker (response_info->headers->response_code() != net::HTTP_OK &&
35*6777b538SAndroid Build Coastguard Worker response_info->headers->response_code() != net::HTTP_NOT_MODIFIED)) {
36*6777b538SAndroid Build Coastguard Worker return false;
37*6777b538SAndroid Build Coastguard Worker }
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker return true;
40*6777b538SAndroid Build Coastguard Worker }
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker } // namespace
43*6777b538SAndroid Build Coastguard Worker
TransactionInfo(PartialData * partial_data,const bool is_truncated,HttpResponseInfo info)44*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::TransactionInfo::TransactionInfo(PartialData* partial_data,
45*6777b538SAndroid Build Coastguard Worker const bool is_truncated,
46*6777b538SAndroid Build Coastguard Worker HttpResponseInfo info)
47*6777b538SAndroid Build Coastguard Worker : partial(partial_data), truncated(is_truncated), response_info(info) {}
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::TransactionInfo::~TransactionInfo() = default;
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::TransactionInfo::TransactionInfo(const TransactionInfo&) =
52*6777b538SAndroid Build Coastguard Worker default;
53*6777b538SAndroid Build Coastguard Worker
Writers(HttpCache * cache,scoped_refptr<HttpCache::ActiveEntry> entry)54*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::Writers(HttpCache* cache,
55*6777b538SAndroid Build Coastguard Worker scoped_refptr<HttpCache::ActiveEntry> entry)
56*6777b538SAndroid Build Coastguard Worker : cache_(cache), entry_(entry) {
57*6777b538SAndroid Build Coastguard Worker DCHECK(cache_);
58*6777b538SAndroid Build Coastguard Worker DCHECK(entry_);
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::~Writers() = default;
62*6777b538SAndroid Build Coastguard Worker
Read(scoped_refptr<IOBuffer> buf,int buf_len,CompletionOnceCallback callback,Transaction * transaction)63*6777b538SAndroid Build Coastguard Worker int HttpCache::Writers::Read(scoped_refptr<IOBuffer> buf,
64*6777b538SAndroid Build Coastguard Worker int buf_len,
65*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback,
66*6777b538SAndroid Build Coastguard Worker Transaction* transaction) {
67*6777b538SAndroid Build Coastguard Worker DCHECK(buf);
68*6777b538SAndroid Build Coastguard Worker DCHECK_GT(buf_len, 0);
69*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
70*6777b538SAndroid Build Coastguard Worker DCHECK(transaction);
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker // If another transaction invoked a Read which is currently ongoing, then
73*6777b538SAndroid Build Coastguard Worker // this transaction waits for the read to complete and gets its buffer filled
74*6777b538SAndroid Build Coastguard Worker // with the data returned from that read.
75*6777b538SAndroid Build Coastguard Worker if (next_state_ != State::NONE) {
76*6777b538SAndroid Build Coastguard Worker WaitingForRead read_info(buf, buf_len, std::move(callback));
77*6777b538SAndroid Build Coastguard Worker waiting_for_read_.emplace(transaction, std::move(read_info));
78*6777b538SAndroid Build Coastguard Worker return ERR_IO_PENDING;
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(next_state_, State::NONE);
82*6777b538SAndroid Build Coastguard Worker DCHECK(callback_.is_null());
83*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(nullptr, active_transaction_);
84*6777b538SAndroid Build Coastguard Worker DCHECK(HasTransaction(transaction));
85*6777b538SAndroid Build Coastguard Worker active_transaction_ = transaction;
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker read_buf_ = std::move(buf);
88*6777b538SAndroid Build Coastguard Worker io_buf_len_ = buf_len;
89*6777b538SAndroid Build Coastguard Worker next_state_ = State::NETWORK_READ;
90*6777b538SAndroid Build Coastguard Worker
91*6777b538SAndroid Build Coastguard Worker int rv = DoLoop(OK);
92*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
93*6777b538SAndroid Build Coastguard Worker callback_ = std::move(callback);
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker return rv;
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker
StopCaching(bool keep_entry)99*6777b538SAndroid Build Coastguard Worker bool HttpCache::Writers::StopCaching(bool keep_entry) {
100*6777b538SAndroid Build Coastguard Worker // If this is the only transaction in Writers, then stopping will be
101*6777b538SAndroid Build Coastguard Worker // successful. If not, then we will not stop caching since there are
102*6777b538SAndroid Build Coastguard Worker // other consumers waiting to read from the cache.
103*6777b538SAndroid Build Coastguard Worker if (all_writers_.size() != 1) {
104*6777b538SAndroid Build Coastguard Worker return false;
105*6777b538SAndroid Build Coastguard Worker }
106*6777b538SAndroid Build Coastguard Worker
107*6777b538SAndroid Build Coastguard Worker network_read_only_ = true;
108*6777b538SAndroid Build Coastguard Worker if (!keep_entry) {
109*6777b538SAndroid Build Coastguard Worker should_keep_entry_ = false;
110*6777b538SAndroid Build Coastguard Worker cache_->WritersDoomEntryRestartTransactions(entry_.get());
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker return true;
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker
AddTransaction(Transaction * transaction,ParallelWritingPattern initial_writing_pattern,RequestPriority priority,const TransactionInfo & info)116*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::AddTransaction(
117*6777b538SAndroid Build Coastguard Worker Transaction* transaction,
118*6777b538SAndroid Build Coastguard Worker ParallelWritingPattern initial_writing_pattern,
119*6777b538SAndroid Build Coastguard Worker RequestPriority priority,
120*6777b538SAndroid Build Coastguard Worker const TransactionInfo& info) {
121*6777b538SAndroid Build Coastguard Worker DCHECK(transaction);
122*6777b538SAndroid Build Coastguard Worker ParallelWritingPattern writers_pattern;
123*6777b538SAndroid Build Coastguard Worker DCHECK(CanAddWriters(&writers_pattern));
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(0u, all_writers_.count(transaction));
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker // Set truncation related information.
128*6777b538SAndroid Build Coastguard Worker response_info_truncation_ = info.response_info;
129*6777b538SAndroid Build Coastguard Worker should_keep_entry_ =
130*6777b538SAndroid Build Coastguard Worker IsValidResponseForWriter(info.partial != nullptr, &(info.response_info));
131*6777b538SAndroid Build Coastguard Worker
132*6777b538SAndroid Build Coastguard Worker if (all_writers_.empty()) {
133*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(PARALLEL_WRITING_NONE, parallel_writing_pattern_);
134*6777b538SAndroid Build Coastguard Worker parallel_writing_pattern_ = initial_writing_pattern;
135*6777b538SAndroid Build Coastguard Worker if (parallel_writing_pattern_ != PARALLEL_WRITING_JOIN) {
136*6777b538SAndroid Build Coastguard Worker is_exclusive_ = true;
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker } else {
139*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(PARALLEL_WRITING_JOIN, parallel_writing_pattern_);
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker if (info.partial && !info.truncated) {
143*6777b538SAndroid Build Coastguard Worker DCHECK(!partial_do_not_truncate_);
144*6777b538SAndroid Build Coastguard Worker partial_do_not_truncate_ = true;
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker
147*6777b538SAndroid Build Coastguard Worker std::pair<Transaction*, TransactionInfo> writer(transaction, info);
148*6777b538SAndroid Build Coastguard Worker all_writers_.insert(writer);
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker priority_ = std::max(priority, priority_);
151*6777b538SAndroid Build Coastguard Worker if (network_transaction_) {
152*6777b538SAndroid Build Coastguard Worker network_transaction_->SetPriority(priority_);
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
SetNetworkTransaction(Transaction * transaction,std::unique_ptr<HttpTransaction> network_transaction)156*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::SetNetworkTransaction(
157*6777b538SAndroid Build Coastguard Worker Transaction* transaction,
158*6777b538SAndroid Build Coastguard Worker std::unique_ptr<HttpTransaction> network_transaction) {
159*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(1u, all_writers_.count(transaction));
160*6777b538SAndroid Build Coastguard Worker DCHECK(network_transaction);
161*6777b538SAndroid Build Coastguard Worker DCHECK(!network_transaction_);
162*6777b538SAndroid Build Coastguard Worker network_transaction_ = std::move(network_transaction);
163*6777b538SAndroid Build Coastguard Worker network_transaction_->SetPriority(priority_);
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker
ResetNetworkTransaction()166*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::ResetNetworkTransaction() {
167*6777b538SAndroid Build Coastguard Worker DCHECK(is_exclusive_);
168*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(1u, all_writers_.size());
169*6777b538SAndroid Build Coastguard Worker DCHECK(all_writers_.begin()->second.partial);
170*6777b538SAndroid Build Coastguard Worker network_transaction_.reset();
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker
RemoveTransaction(Transaction * transaction,bool success)173*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::RemoveTransaction(Transaction* transaction,
174*6777b538SAndroid Build Coastguard Worker bool success) {
175*6777b538SAndroid Build Coastguard Worker EraseTransaction(transaction, OK);
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Worker if (!all_writers_.empty()) {
178*6777b538SAndroid Build Coastguard Worker return;
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker if (!success && ShouldTruncate()) {
182*6777b538SAndroid Build Coastguard Worker TruncateEntry();
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker // Destroys `this`.
186*6777b538SAndroid Build Coastguard Worker cache_->WritersDoneWritingToEntry(entry_, success, should_keep_entry_,
187*6777b538SAndroid Build Coastguard Worker TransactionSet());
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker
EraseTransaction(Transaction * transaction,int result)190*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::EraseTransaction(Transaction* transaction,
191*6777b538SAndroid Build Coastguard Worker int result) {
192*6777b538SAndroid Build Coastguard Worker // The transaction should be part of all_writers.
193*6777b538SAndroid Build Coastguard Worker auto it = all_writers_.find(transaction);
194*6777b538SAndroid Build Coastguard Worker DCHECK(it != all_writers_.end());
195*6777b538SAndroid Build Coastguard Worker EraseTransaction(it, result);
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker
198*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::TransactionMap::iterator
EraseTransaction(TransactionMap::iterator it,int result)199*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::EraseTransaction(TransactionMap::iterator it, int result) {
200*6777b538SAndroid Build Coastguard Worker Transaction* transaction = it->first;
201*6777b538SAndroid Build Coastguard Worker transaction->WriterAboutToBeRemovedFromEntry(result);
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker auto return_it = all_writers_.erase(it);
204*6777b538SAndroid Build Coastguard Worker
205*6777b538SAndroid Build Coastguard Worker if (all_writers_.empty() && next_state_ == State::NONE) {
206*6777b538SAndroid Build Coastguard Worker // This needs to be called to handle the edge case where even before Read is
207*6777b538SAndroid Build Coastguard Worker // invoked all transactions are removed. In that case the
208*6777b538SAndroid Build Coastguard Worker // network_transaction_ will still have a valid request info and so it
209*6777b538SAndroid Build Coastguard Worker // should be destroyed before its consumer is destroyed (request info
210*6777b538SAndroid Build Coastguard Worker // is a raw pointer owned by its consumer).
211*6777b538SAndroid Build Coastguard Worker network_transaction_.reset();
212*6777b538SAndroid Build Coastguard Worker } else {
213*6777b538SAndroid Build Coastguard Worker UpdatePriority();
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker
216*6777b538SAndroid Build Coastguard Worker if (active_transaction_ == transaction) {
217*6777b538SAndroid Build Coastguard Worker active_transaction_ = nullptr;
218*6777b538SAndroid Build Coastguard Worker } else {
219*6777b538SAndroid Build Coastguard Worker // If waiting for read, remove it from the map.
220*6777b538SAndroid Build Coastguard Worker waiting_for_read_.erase(transaction);
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker return return_it;
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker
UpdatePriority()225*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::UpdatePriority() {
226*6777b538SAndroid Build Coastguard Worker // Get the current highest priority.
227*6777b538SAndroid Build Coastguard Worker RequestPriority current_highest = MINIMUM_PRIORITY;
228*6777b538SAndroid Build Coastguard Worker for (auto& writer : all_writers_) {
229*6777b538SAndroid Build Coastguard Worker Transaction* transaction = writer.first;
230*6777b538SAndroid Build Coastguard Worker current_highest = std::max(transaction->priority(), current_highest);
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker
233*6777b538SAndroid Build Coastguard Worker if (priority_ != current_highest) {
234*6777b538SAndroid Build Coastguard Worker if (network_transaction_) {
235*6777b538SAndroid Build Coastguard Worker network_transaction_->SetPriority(current_highest);
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker priority_ = current_highest;
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker }
240*6777b538SAndroid Build Coastguard Worker
CloseConnectionOnDestruction()241*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::CloseConnectionOnDestruction() {
242*6777b538SAndroid Build Coastguard Worker if (network_transaction_) {
243*6777b538SAndroid Build Coastguard Worker network_transaction_->CloseConnectionOnDestruction();
244*6777b538SAndroid Build Coastguard Worker }
245*6777b538SAndroid Build Coastguard Worker }
246*6777b538SAndroid Build Coastguard Worker
ContainsOnlyIdleWriters() const247*6777b538SAndroid Build Coastguard Worker bool HttpCache::Writers::ContainsOnlyIdleWriters() const {
248*6777b538SAndroid Build Coastguard Worker return waiting_for_read_.empty() && !active_transaction_;
249*6777b538SAndroid Build Coastguard Worker }
250*6777b538SAndroid Build Coastguard Worker
CanAddWriters(ParallelWritingPattern * reason)251*6777b538SAndroid Build Coastguard Worker bool HttpCache::Writers::CanAddWriters(ParallelWritingPattern* reason) {
252*6777b538SAndroid Build Coastguard Worker *reason = parallel_writing_pattern_;
253*6777b538SAndroid Build Coastguard Worker
254*6777b538SAndroid Build Coastguard Worker if (all_writers_.empty()) {
255*6777b538SAndroid Build Coastguard Worker return true;
256*6777b538SAndroid Build Coastguard Worker }
257*6777b538SAndroid Build Coastguard Worker
258*6777b538SAndroid Build Coastguard Worker return !is_exclusive_ && !network_read_only_;
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker
ProcessFailure(int error)261*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::ProcessFailure(int error) {
262*6777b538SAndroid Build Coastguard Worker // Notify waiting_for_read_ of the failure. Tasks will be posted for all the
263*6777b538SAndroid Build Coastguard Worker // transactions.
264*6777b538SAndroid Build Coastguard Worker CompleteWaitingForReadTransactions(error);
265*6777b538SAndroid Build Coastguard Worker
266*6777b538SAndroid Build Coastguard Worker // Idle readers should fail when Read is invoked on them.
267*6777b538SAndroid Build Coastguard Worker RemoveIdleWriters(error);
268*6777b538SAndroid Build Coastguard Worker }
269*6777b538SAndroid Build Coastguard Worker
TruncateEntry()270*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::TruncateEntry() {
271*6777b538SAndroid Build Coastguard Worker DCHECK(ShouldTruncate());
272*6777b538SAndroid Build Coastguard Worker auto data = base::MakeRefCounted<PickledIOBuffer>();
273*6777b538SAndroid Build Coastguard Worker response_info_truncation_.Persist(data->pickle(),
274*6777b538SAndroid Build Coastguard Worker true /* skip_transient_headers*/,
275*6777b538SAndroid Build Coastguard Worker true /* response_truncated */);
276*6777b538SAndroid Build Coastguard Worker data->Done();
277*6777b538SAndroid Build Coastguard Worker io_buf_len_ = data->pickle()->size();
278*6777b538SAndroid Build Coastguard Worker entry_->GetEntry()->WriteData(kResponseInfoIndex, 0, data.get(), io_buf_len_,
279*6777b538SAndroid Build Coastguard Worker base::DoNothing(), true);
280*6777b538SAndroid Build Coastguard Worker }
281*6777b538SAndroid Build Coastguard Worker
ShouldTruncate()282*6777b538SAndroid Build Coastguard Worker bool HttpCache::Writers::ShouldTruncate() {
283*6777b538SAndroid Build Coastguard Worker // Don't set the flag for sparse entries or for entries that cannot be
284*6777b538SAndroid Build Coastguard Worker // resumed.
285*6777b538SAndroid Build Coastguard Worker if (!should_keep_entry_ || partial_do_not_truncate_) {
286*6777b538SAndroid Build Coastguard Worker return false;
287*6777b538SAndroid Build Coastguard Worker }
288*6777b538SAndroid Build Coastguard Worker
289*6777b538SAndroid Build Coastguard Worker // Check the response headers for strong validators.
290*6777b538SAndroid Build Coastguard Worker // Note that if this is a 206, content-length was already fixed after calling
291*6777b538SAndroid Build Coastguard Worker // PartialData::ResponseHeadersOK().
292*6777b538SAndroid Build Coastguard Worker if (response_info_truncation_.headers->GetContentLength() <= 0 ||
293*6777b538SAndroid Build Coastguard Worker response_info_truncation_.headers->HasHeaderValue("Accept-Ranges",
294*6777b538SAndroid Build Coastguard Worker "none") ||
295*6777b538SAndroid Build Coastguard Worker !response_info_truncation_.headers->HasStrongValidators()) {
296*6777b538SAndroid Build Coastguard Worker should_keep_entry_ = false;
297*6777b538SAndroid Build Coastguard Worker return false;
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker // Double check that there is something worth keeping.
301*6777b538SAndroid Build Coastguard Worker int current_size = entry_->GetEntry()->GetDataSize(kResponseContentIndex);
302*6777b538SAndroid Build Coastguard Worker if (!current_size) {
303*6777b538SAndroid Build Coastguard Worker should_keep_entry_ = false;
304*6777b538SAndroid Build Coastguard Worker return false;
305*6777b538SAndroid Build Coastguard Worker }
306*6777b538SAndroid Build Coastguard Worker
307*6777b538SAndroid Build Coastguard Worker if (response_info_truncation_.headers->HasHeader("Content-Encoding")) {
308*6777b538SAndroid Build Coastguard Worker should_keep_entry_ = false;
309*6777b538SAndroid Build Coastguard Worker return false;
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker int64_t content_length =
313*6777b538SAndroid Build Coastguard Worker response_info_truncation_.headers->GetContentLength();
314*6777b538SAndroid Build Coastguard Worker if (content_length >= 0 && content_length <= current_size) {
315*6777b538SAndroid Build Coastguard Worker return false;
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker
318*6777b538SAndroid Build Coastguard Worker return true;
319*6777b538SAndroid Build Coastguard Worker }
320*6777b538SAndroid Build Coastguard Worker
GetLoadState() const321*6777b538SAndroid Build Coastguard Worker LoadState HttpCache::Writers::GetLoadState() const {
322*6777b538SAndroid Build Coastguard Worker if (network_transaction_) {
323*6777b538SAndroid Build Coastguard Worker return network_transaction_->GetLoadState();
324*6777b538SAndroid Build Coastguard Worker }
325*6777b538SAndroid Build Coastguard Worker return LOAD_STATE_IDLE;
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker
WaitingForRead(scoped_refptr<IOBuffer> buf,int len,CompletionOnceCallback consumer_callback)328*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::WaitingForRead::WaitingForRead(
329*6777b538SAndroid Build Coastguard Worker scoped_refptr<IOBuffer> buf,
330*6777b538SAndroid Build Coastguard Worker int len,
331*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback consumer_callback)
332*6777b538SAndroid Build Coastguard Worker : read_buf(std::move(buf)),
333*6777b538SAndroid Build Coastguard Worker read_buf_len(len),
334*6777b538SAndroid Build Coastguard Worker callback(std::move(consumer_callback)) {
335*6777b538SAndroid Build Coastguard Worker DCHECK(read_buf);
336*6777b538SAndroid Build Coastguard Worker DCHECK_GT(len, 0);
337*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
338*6777b538SAndroid Build Coastguard Worker }
339*6777b538SAndroid Build Coastguard Worker
340*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::WaitingForRead::~WaitingForRead() = default;
341*6777b538SAndroid Build Coastguard Worker HttpCache::Writers::WaitingForRead::WaitingForRead(WaitingForRead&&) = default;
342*6777b538SAndroid Build Coastguard Worker
DoLoop(int result)343*6777b538SAndroid Build Coastguard Worker int HttpCache::Writers::DoLoop(int result) {
344*6777b538SAndroid Build Coastguard Worker DCHECK_NE(State::UNSET, next_state_);
345*6777b538SAndroid Build Coastguard Worker DCHECK_NE(State::NONE, next_state_);
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker int rv = result;
348*6777b538SAndroid Build Coastguard Worker do {
349*6777b538SAndroid Build Coastguard Worker State state = next_state_;
350*6777b538SAndroid Build Coastguard Worker next_state_ = State::UNSET;
351*6777b538SAndroid Build Coastguard Worker switch (state) {
352*6777b538SAndroid Build Coastguard Worker case State::NETWORK_READ:
353*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
354*6777b538SAndroid Build Coastguard Worker rv = DoNetworkRead();
355*6777b538SAndroid Build Coastguard Worker break;
356*6777b538SAndroid Build Coastguard Worker case State::NETWORK_READ_COMPLETE:
357*6777b538SAndroid Build Coastguard Worker rv = DoNetworkReadComplete(rv);
358*6777b538SAndroid Build Coastguard Worker break;
359*6777b538SAndroid Build Coastguard Worker case State::CACHE_WRITE_DATA:
360*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteData(rv);
361*6777b538SAndroid Build Coastguard Worker break;
362*6777b538SAndroid Build Coastguard Worker case State::CACHE_WRITE_DATA_COMPLETE:
363*6777b538SAndroid Build Coastguard Worker rv = DoCacheWriteDataComplete(rv);
364*6777b538SAndroid Build Coastguard Worker break;
365*6777b538SAndroid Build Coastguard Worker case State::UNSET:
366*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "bad state";
367*6777b538SAndroid Build Coastguard Worker rv = ERR_FAILED;
368*6777b538SAndroid Build Coastguard Worker break;
369*6777b538SAndroid Build Coastguard Worker case State::NONE:
370*6777b538SAndroid Build Coastguard Worker // Do Nothing.
371*6777b538SAndroid Build Coastguard Worker break;
372*6777b538SAndroid Build Coastguard Worker }
373*6777b538SAndroid Build Coastguard Worker } while (next_state_ != State::NONE && rv != ERR_IO_PENDING);
374*6777b538SAndroid Build Coastguard Worker
375*6777b538SAndroid Build Coastguard Worker if (next_state_ != State::NONE) {
376*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING && !callback_.is_null()) {
377*6777b538SAndroid Build Coastguard Worker std::move(callback_).Run(rv);
378*6777b538SAndroid Build Coastguard Worker }
379*6777b538SAndroid Build Coastguard Worker return rv;
380*6777b538SAndroid Build Coastguard Worker }
381*6777b538SAndroid Build Coastguard Worker
382*6777b538SAndroid Build Coastguard Worker // Save the callback as |this| may be destroyed when |cache_callback_| is run.
383*6777b538SAndroid Build Coastguard Worker // Note that |callback_| is intentionally reset even if it is not run.
384*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback = std::move(callback_);
385*6777b538SAndroid Build Coastguard Worker read_buf_ = nullptr;
386*6777b538SAndroid Build Coastguard Worker DCHECK(!all_writers_.empty() || cache_callback_);
387*6777b538SAndroid Build Coastguard Worker if (cache_callback_) {
388*6777b538SAndroid Build Coastguard Worker std::move(cache_callback_).Run();
389*6777b538SAndroid Build Coastguard Worker }
390*6777b538SAndroid Build Coastguard Worker // |this| may have been destroyed in the |cache_callback_|.
391*6777b538SAndroid Build Coastguard Worker if (rv != ERR_IO_PENDING && !callback.is_null()) {
392*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(rv);
393*6777b538SAndroid Build Coastguard Worker }
394*6777b538SAndroid Build Coastguard Worker return rv;
395*6777b538SAndroid Build Coastguard Worker }
396*6777b538SAndroid Build Coastguard Worker
DoNetworkRead()397*6777b538SAndroid Build Coastguard Worker int HttpCache::Writers::DoNetworkRead() {
398*6777b538SAndroid Build Coastguard Worker DCHECK(network_transaction_);
399*6777b538SAndroid Build Coastguard Worker next_state_ = State::NETWORK_READ_COMPLETE;
400*6777b538SAndroid Build Coastguard Worker
401*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/778641): This is a partial mitigation. When
402*6777b538SAndroid Build Coastguard Worker // reading from the network, a valid HttpNetworkTransaction must be always
403*6777b538SAndroid Build Coastguard Worker // available.
404*6777b538SAndroid Build Coastguard Worker if (!network_transaction_) {
405*6777b538SAndroid Build Coastguard Worker return ERR_FAILED;
406*6777b538SAndroid Build Coastguard Worker }
407*6777b538SAndroid Build Coastguard Worker
408*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback io_callback = base::BindOnce(
409*6777b538SAndroid Build Coastguard Worker &HttpCache::Writers::OnIOComplete, weak_factory_.GetWeakPtr());
410*6777b538SAndroid Build Coastguard Worker return network_transaction_->Read(read_buf_.get(), io_buf_len_,
411*6777b538SAndroid Build Coastguard Worker std::move(io_callback));
412*6777b538SAndroid Build Coastguard Worker }
413*6777b538SAndroid Build Coastguard Worker
DoNetworkReadComplete(int result)414*6777b538SAndroid Build Coastguard Worker int HttpCache::Writers::DoNetworkReadComplete(int result) {
415*6777b538SAndroid Build Coastguard Worker if (result < 0) {
416*6777b538SAndroid Build Coastguard Worker next_state_ = State::NONE;
417*6777b538SAndroid Build Coastguard Worker OnNetworkReadFailure(result);
418*6777b538SAndroid Build Coastguard Worker return result;
419*6777b538SAndroid Build Coastguard Worker }
420*6777b538SAndroid Build Coastguard Worker
421*6777b538SAndroid Build Coastguard Worker next_state_ = State::CACHE_WRITE_DATA;
422*6777b538SAndroid Build Coastguard Worker return result;
423*6777b538SAndroid Build Coastguard Worker }
424*6777b538SAndroid Build Coastguard Worker
OnNetworkReadFailure(int result)425*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::OnNetworkReadFailure(int result) {
426*6777b538SAndroid Build Coastguard Worker ProcessFailure(result);
427*6777b538SAndroid Build Coastguard Worker
428*6777b538SAndroid Build Coastguard Worker if (active_transaction_) {
429*6777b538SAndroid Build Coastguard Worker EraseTransaction(active_transaction_, result);
430*6777b538SAndroid Build Coastguard Worker }
431*6777b538SAndroid Build Coastguard Worker active_transaction_ = nullptr;
432*6777b538SAndroid Build Coastguard Worker
433*6777b538SAndroid Build Coastguard Worker if (ShouldTruncate()) {
434*6777b538SAndroid Build Coastguard Worker TruncateEntry();
435*6777b538SAndroid Build Coastguard Worker }
436*6777b538SAndroid Build Coastguard Worker
437*6777b538SAndroid Build Coastguard Worker SetCacheCallback(false, TransactionSet());
438*6777b538SAndroid Build Coastguard Worker }
439*6777b538SAndroid Build Coastguard Worker
DoCacheWriteData(int num_bytes)440*6777b538SAndroid Build Coastguard Worker int HttpCache::Writers::DoCacheWriteData(int num_bytes) {
441*6777b538SAndroid Build Coastguard Worker next_state_ = State::CACHE_WRITE_DATA_COMPLETE;
442*6777b538SAndroid Build Coastguard Worker write_len_ = num_bytes;
443*6777b538SAndroid Build Coastguard Worker if (!num_bytes || network_read_only_) {
444*6777b538SAndroid Build Coastguard Worker return num_bytes;
445*6777b538SAndroid Build Coastguard Worker }
446*6777b538SAndroid Build Coastguard Worker
447*6777b538SAndroid Build Coastguard Worker int current_size = entry_->GetEntry()->GetDataSize(kResponseContentIndex);
448*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback io_callback = base::BindOnce(
449*6777b538SAndroid Build Coastguard Worker &HttpCache::Writers::OnIOComplete, weak_factory_.GetWeakPtr());
450*6777b538SAndroid Build Coastguard Worker
451*6777b538SAndroid Build Coastguard Worker int rv = 0;
452*6777b538SAndroid Build Coastguard Worker
453*6777b538SAndroid Build Coastguard Worker PartialData* partial = nullptr;
454*6777b538SAndroid Build Coastguard Worker // The active transaction must be alive if this is a partial request, as
455*6777b538SAndroid Build Coastguard Worker // partial requests are exclusive and hence will always be the active
456*6777b538SAndroid Build Coastguard Worker // transaction.
457*6777b538SAndroid Build Coastguard Worker // TODO(shivanisha): When partial requests support parallel writing, this
458*6777b538SAndroid Build Coastguard Worker // assumption will not be true.
459*6777b538SAndroid Build Coastguard Worker if (active_transaction_) {
460*6777b538SAndroid Build Coastguard Worker partial = all_writers_.find(active_transaction_)->second.partial;
461*6777b538SAndroid Build Coastguard Worker }
462*6777b538SAndroid Build Coastguard Worker
463*6777b538SAndroid Build Coastguard Worker if (!partial) {
464*6777b538SAndroid Build Coastguard Worker last_disk_cache_access_start_time_ = base::TimeTicks::Now();
465*6777b538SAndroid Build Coastguard Worker rv = entry_->GetEntry()->WriteData(kResponseContentIndex, current_size,
466*6777b538SAndroid Build Coastguard Worker read_buf_.get(), num_bytes,
467*6777b538SAndroid Build Coastguard Worker std::move(io_callback), true);
468*6777b538SAndroid Build Coastguard Worker } else {
469*6777b538SAndroid Build Coastguard Worker rv = partial->CacheWrite(entry_->GetEntry(), read_buf_.get(), num_bytes,
470*6777b538SAndroid Build Coastguard Worker std::move(io_callback));
471*6777b538SAndroid Build Coastguard Worker }
472*6777b538SAndroid Build Coastguard Worker return rv;
473*6777b538SAndroid Build Coastguard Worker }
474*6777b538SAndroid Build Coastguard Worker
DoCacheWriteDataComplete(int result)475*6777b538SAndroid Build Coastguard Worker int HttpCache::Writers::DoCacheWriteDataComplete(int result) {
476*6777b538SAndroid Build Coastguard Worker DCHECK(!all_writers_.empty());
477*6777b538SAndroid Build Coastguard Worker DCHECK_GE(write_len_, 0);
478*6777b538SAndroid Build Coastguard Worker
479*6777b538SAndroid Build Coastguard Worker if (result != write_len_) {
480*6777b538SAndroid Build Coastguard Worker next_state_ = State::NONE;
481*6777b538SAndroid Build Coastguard Worker
482*6777b538SAndroid Build Coastguard Worker // Note that it is possible for cache write to fail if the size of the file
483*6777b538SAndroid Build Coastguard Worker // exceeds the per-file limit.
484*6777b538SAndroid Build Coastguard Worker OnCacheWriteFailure();
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Worker // |active_transaction_| can continue reading from the network.
487*6777b538SAndroid Build Coastguard Worker return write_len_;
488*6777b538SAndroid Build Coastguard Worker }
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker if (!last_disk_cache_access_start_time_.is_null() && active_transaction_ &&
491*6777b538SAndroid Build Coastguard Worker !all_writers_.find(active_transaction_)->second.partial) {
492*6777b538SAndroid Build Coastguard Worker active_transaction_->AddDiskCacheWriteTime(
493*6777b538SAndroid Build Coastguard Worker base::TimeTicks::Now() - last_disk_cache_access_start_time_);
494*6777b538SAndroid Build Coastguard Worker last_disk_cache_access_start_time_ = base::TimeTicks();
495*6777b538SAndroid Build Coastguard Worker }
496*6777b538SAndroid Build Coastguard Worker
497*6777b538SAndroid Build Coastguard Worker next_state_ = State::NONE;
498*6777b538SAndroid Build Coastguard Worker OnDataReceived(write_len_);
499*6777b538SAndroid Build Coastguard Worker
500*6777b538SAndroid Build Coastguard Worker return write_len_;
501*6777b538SAndroid Build Coastguard Worker }
502*6777b538SAndroid Build Coastguard Worker
OnDataReceived(int result)503*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::OnDataReceived(int result) {
504*6777b538SAndroid Build Coastguard Worker DCHECK(!all_writers_.empty());
505*6777b538SAndroid Build Coastguard Worker
506*6777b538SAndroid Build Coastguard Worker auto it = all_writers_.find(active_transaction_);
507*6777b538SAndroid Build Coastguard Worker bool is_partial =
508*6777b538SAndroid Build Coastguard Worker active_transaction_ != nullptr && it->second.partial != nullptr;
509*6777b538SAndroid Build Coastguard Worker
510*6777b538SAndroid Build Coastguard Worker // Partial transaction will process the result, return from here.
511*6777b538SAndroid Build Coastguard Worker // This is done because partial requests handling require an awareness of both
512*6777b538SAndroid Build Coastguard Worker // headers and body state machines as they might have to go to the headers
513*6777b538SAndroid Build Coastguard Worker // phase for the next range, so it cannot be completely handled here.
514*6777b538SAndroid Build Coastguard Worker if (is_partial) {
515*6777b538SAndroid Build Coastguard Worker active_transaction_ = nullptr;
516*6777b538SAndroid Build Coastguard Worker return;
517*6777b538SAndroid Build Coastguard Worker }
518*6777b538SAndroid Build Coastguard Worker
519*6777b538SAndroid Build Coastguard Worker if (result == 0) {
520*6777b538SAndroid Build Coastguard Worker // Check if the response is actually completed or if not, attempt to mark
521*6777b538SAndroid Build Coastguard Worker // the entry as truncated in OnNetworkReadFailure.
522*6777b538SAndroid Build Coastguard Worker int current_size = entry_->GetEntry()->GetDataSize(kResponseContentIndex);
523*6777b538SAndroid Build Coastguard Worker DCHECK(network_transaction_);
524*6777b538SAndroid Build Coastguard Worker const HttpResponseInfo* response_info =
525*6777b538SAndroid Build Coastguard Worker network_transaction_->GetResponseInfo();
526*6777b538SAndroid Build Coastguard Worker int64_t content_length = response_info->headers->GetContentLength();
527*6777b538SAndroid Build Coastguard Worker if (content_length >= 0 && content_length > current_size) {
528*6777b538SAndroid Build Coastguard Worker OnNetworkReadFailure(result);
529*6777b538SAndroid Build Coastguard Worker return;
530*6777b538SAndroid Build Coastguard Worker }
531*6777b538SAndroid Build Coastguard Worker
532*6777b538SAndroid Build Coastguard Worker if (active_transaction_) {
533*6777b538SAndroid Build Coastguard Worker EraseTransaction(active_transaction_, result);
534*6777b538SAndroid Build Coastguard Worker }
535*6777b538SAndroid Build Coastguard Worker active_transaction_ = nullptr;
536*6777b538SAndroid Build Coastguard Worker CompleteWaitingForReadTransactions(write_len_);
537*6777b538SAndroid Build Coastguard Worker
538*6777b538SAndroid Build Coastguard Worker // Invoke entry processing.
539*6777b538SAndroid Build Coastguard Worker DCHECK(ContainsOnlyIdleWriters());
540*6777b538SAndroid Build Coastguard Worker TransactionSet make_readers;
541*6777b538SAndroid Build Coastguard Worker for (auto& writer : all_writers_) {
542*6777b538SAndroid Build Coastguard Worker make_readers.insert(writer.first);
543*6777b538SAndroid Build Coastguard Worker }
544*6777b538SAndroid Build Coastguard Worker all_writers_.clear();
545*6777b538SAndroid Build Coastguard Worker SetCacheCallback(true, make_readers);
546*6777b538SAndroid Build Coastguard Worker // We assume the set callback will be called immediately.
547*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(next_state_, State::NONE);
548*6777b538SAndroid Build Coastguard Worker return;
549*6777b538SAndroid Build Coastguard Worker }
550*6777b538SAndroid Build Coastguard Worker
551*6777b538SAndroid Build Coastguard Worker // Notify waiting_for_read_. Tasks will be posted for all the
552*6777b538SAndroid Build Coastguard Worker // transactions.
553*6777b538SAndroid Build Coastguard Worker CompleteWaitingForReadTransactions(write_len_);
554*6777b538SAndroid Build Coastguard Worker
555*6777b538SAndroid Build Coastguard Worker active_transaction_ = nullptr;
556*6777b538SAndroid Build Coastguard Worker }
557*6777b538SAndroid Build Coastguard Worker
OnCacheWriteFailure()558*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::OnCacheWriteFailure() {
559*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "failed to write response data to cache";
560*6777b538SAndroid Build Coastguard Worker
561*6777b538SAndroid Build Coastguard Worker ProcessFailure(ERR_CACHE_WRITE_FAILURE);
562*6777b538SAndroid Build Coastguard Worker
563*6777b538SAndroid Build Coastguard Worker // Now writers will only be reading from the network.
564*6777b538SAndroid Build Coastguard Worker network_read_only_ = true;
565*6777b538SAndroid Build Coastguard Worker
566*6777b538SAndroid Build Coastguard Worker active_transaction_ = nullptr;
567*6777b538SAndroid Build Coastguard Worker
568*6777b538SAndroid Build Coastguard Worker should_keep_entry_ = false;
569*6777b538SAndroid Build Coastguard Worker if (all_writers_.empty()) {
570*6777b538SAndroid Build Coastguard Worker SetCacheCallback(false, TransactionSet());
571*6777b538SAndroid Build Coastguard Worker } else {
572*6777b538SAndroid Build Coastguard Worker cache_->WritersDoomEntryRestartTransactions(entry_.get());
573*6777b538SAndroid Build Coastguard Worker }
574*6777b538SAndroid Build Coastguard Worker }
575*6777b538SAndroid Build Coastguard Worker
CompleteWaitingForReadTransactions(int result)576*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::CompleteWaitingForReadTransactions(int result) {
577*6777b538SAndroid Build Coastguard Worker for (auto it = waiting_for_read_.begin(); it != waiting_for_read_.end();) {
578*6777b538SAndroid Build Coastguard Worker Transaction* transaction = it->first;
579*6777b538SAndroid Build Coastguard Worker int callback_result = result;
580*6777b538SAndroid Build Coastguard Worker
581*6777b538SAndroid Build Coastguard Worker if (result >= 0) { // success
582*6777b538SAndroid Build Coastguard Worker // Save the data in the waiting transaction's read buffer.
583*6777b538SAndroid Build Coastguard Worker it->second.write_len = std::min(it->second.read_buf_len, result);
584*6777b538SAndroid Build Coastguard Worker memcpy(it->second.read_buf->data(), read_buf_->data(),
585*6777b538SAndroid Build Coastguard Worker it->second.write_len);
586*6777b538SAndroid Build Coastguard Worker callback_result = it->second.write_len;
587*6777b538SAndroid Build Coastguard Worker }
588*6777b538SAndroid Build Coastguard Worker
589*6777b538SAndroid Build Coastguard Worker // Post task to notify transaction.
590*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
591*6777b538SAndroid Build Coastguard Worker FROM_HERE,
592*6777b538SAndroid Build Coastguard Worker base::BindOnce(std::move(it->second.callback), callback_result));
593*6777b538SAndroid Build Coastguard Worker
594*6777b538SAndroid Build Coastguard Worker it = waiting_for_read_.erase(it);
595*6777b538SAndroid Build Coastguard Worker
596*6777b538SAndroid Build Coastguard Worker // If its response completion or failure, this transaction needs to be
597*6777b538SAndroid Build Coastguard Worker // removed from writers.
598*6777b538SAndroid Build Coastguard Worker if (result <= 0) {
599*6777b538SAndroid Build Coastguard Worker EraseTransaction(transaction, result);
600*6777b538SAndroid Build Coastguard Worker }
601*6777b538SAndroid Build Coastguard Worker }
602*6777b538SAndroid Build Coastguard Worker }
603*6777b538SAndroid Build Coastguard Worker
RemoveIdleWriters(int result)604*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::RemoveIdleWriters(int result) {
605*6777b538SAndroid Build Coastguard Worker // Since this is only for idle transactions, waiting_for_read_
606*6777b538SAndroid Build Coastguard Worker // should be empty.
607*6777b538SAndroid Build Coastguard Worker DCHECK(waiting_for_read_.empty());
608*6777b538SAndroid Build Coastguard Worker for (auto it = all_writers_.begin(); it != all_writers_.end();) {
609*6777b538SAndroid Build Coastguard Worker Transaction* transaction = it->first;
610*6777b538SAndroid Build Coastguard Worker if (transaction == active_transaction_) {
611*6777b538SAndroid Build Coastguard Worker it++;
612*6777b538SAndroid Build Coastguard Worker continue;
613*6777b538SAndroid Build Coastguard Worker }
614*6777b538SAndroid Build Coastguard Worker it = EraseTransaction(it, result);
615*6777b538SAndroid Build Coastguard Worker }
616*6777b538SAndroid Build Coastguard Worker }
617*6777b538SAndroid Build Coastguard Worker
SetCacheCallback(bool success,const TransactionSet & make_readers)618*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::SetCacheCallback(bool success,
619*6777b538SAndroid Build Coastguard Worker const TransactionSet& make_readers) {
620*6777b538SAndroid Build Coastguard Worker DCHECK(!cache_callback_);
621*6777b538SAndroid Build Coastguard Worker cache_callback_ = base::BindOnce(&HttpCache::WritersDoneWritingToEntry,
622*6777b538SAndroid Build Coastguard Worker cache_->GetWeakPtr(), entry_, success,
623*6777b538SAndroid Build Coastguard Worker should_keep_entry_, make_readers);
624*6777b538SAndroid Build Coastguard Worker }
625*6777b538SAndroid Build Coastguard Worker
OnIOComplete(int result)626*6777b538SAndroid Build Coastguard Worker void HttpCache::Writers::OnIOComplete(int result) {
627*6777b538SAndroid Build Coastguard Worker DoLoop(result);
628*6777b538SAndroid Build Coastguard Worker }
629*6777b538SAndroid Build Coastguard Worker
630*6777b538SAndroid Build Coastguard Worker } // namespace net
631