xref: /aosp_15_r20/external/cronet/net/http/http_cache_writers.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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