1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/url_request/url_fetcher_core.h"
6 
7 #include <stdint.h>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
12 #include "base/check_op.h"
13 #include "base/notreached.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/stl_util.h"
17 #include "base/threading/sequenced_task_runner_handle.h"
18 #include "net/base/elements_upload_data_stream.h"
19 #include "net/base/io_buffer.h"
20 #include "net/base/load_flags.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/request_priority.h"
23 #include "net/base/upload_bytes_element_reader.h"
24 #include "net/base/upload_data_stream.h"
25 #include "net/base/upload_file_element_reader.h"
26 #include "net/http/http_response_headers.h"
27 #include "net/url_request/redirect_info.h"
28 #include "net/url_request/url_fetcher_delegate.h"
29 #include "net/url_request/url_fetcher_response_writer.h"
30 #include "net/url_request/url_request_context.h"
31 #include "net/url_request/url_request_context_getter.h"
32 #include "net/url_request/url_request_throttler_manager.h"
33 #include "url/origin.h"
34 
35 namespace {
36 
37 const int kBufferSize = 4096;
38 const int kUploadProgressTimerInterval = 100;
39 bool g_ignore_certificate_requests = false;
40 
41 }  // namespace
42 
43 namespace net {
44 
45 // URLFetcherCore::Registry ---------------------------------------------------
46 
47 URLFetcherCore::Registry::Registry() = default;
48 URLFetcherCore::Registry::~Registry() = default;
49 
AddURLFetcherCore(URLFetcherCore * core)50 void URLFetcherCore::Registry::AddURLFetcherCore(URLFetcherCore* core) {
51   DCHECK(!base::Contains(fetchers_, core));
52   fetchers_.insert(core);
53 }
54 
RemoveURLFetcherCore(URLFetcherCore * core)55 void URLFetcherCore::Registry::RemoveURLFetcherCore(URLFetcherCore* core) {
56   DCHECK(base::Contains(fetchers_, core));
57   fetchers_.erase(core);
58 }
59 
CancelAll()60 void URLFetcherCore::Registry::CancelAll() {
61   while (!fetchers_.empty())
62     (*fetchers_.begin())->CancelURLRequest(ERR_ABORTED);
63 }
64 
65 // URLFetcherCore -------------------------------------------------------------
66 
67 // static
68 base::LazyInstance<URLFetcherCore::Registry>::DestructorAtExit
69     URLFetcherCore::g_registry = LAZY_INSTANCE_INITIALIZER;
70 
URLFetcherCore(URLFetcher * fetcher,const GURL & original_url,URLFetcher::RequestType request_type,URLFetcherDelegate * d,net::NetworkTrafficAnnotationTag traffic_annotation)71 URLFetcherCore::URLFetcherCore(
72     URLFetcher* fetcher,
73     const GURL& original_url,
74     URLFetcher::RequestType request_type,
75     URLFetcherDelegate* d,
76     net::NetworkTrafficAnnotationTag traffic_annotation)
77     : fetcher_(fetcher),
78       original_url_(original_url),
79       request_type_(request_type),
80       delegate_(d),
81       delegate_task_runner_(base::SequencedTaskRunnerHandle::Get()),
82       load_flags_(LOAD_NORMAL),
83       allow_credentials_(base::nullopt),
84       response_code_(URLFetcher::RESPONSE_CODE_INVALID),
85       url_request_data_key_(nullptr),
86       was_cached_(false),
87       received_response_content_length_(0),
88       total_received_bytes_(0),
89       upload_content_set_(false),
90       upload_range_offset_(0),
91       upload_range_length_(0),
92       referrer_policy_(
93           ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
94       is_chunked_upload_(false),
95       was_cancelled_(false),
96       stop_on_redirect_(false),
97       stopped_on_redirect_(false),
98       automatically_retry_on_5xx_(true),
99       num_retries_on_5xx_(0),
100       max_retries_on_5xx_(0),
101       num_retries_on_network_changes_(0),
102       max_retries_on_network_changes_(0),
103       current_upload_bytes_(-1),
104       current_response_bytes_(0),
105       total_response_bytes_(-1),
106       traffic_annotation_(traffic_annotation) {
107   CHECK(original_url_.is_valid());
108 }
109 
Start()110 void URLFetcherCore::Start() {
111   DCHECK(delegate_task_runner_);
112   DCHECK(request_context_getter_.get()) << "We need an URLRequestContext!";
113   if (network_task_runner_.get()) {
114     DCHECK_EQ(network_task_runner_,
115               request_context_getter_->GetNetworkTaskRunner());
116   } else {
117     network_task_runner_ = request_context_getter_->GetNetworkTaskRunner();
118   }
119   DCHECK(network_task_runner_.get()) << "We need an IO task runner";
120 
121   network_task_runner_->PostTask(
122       FROM_HERE, base::BindOnce(&URLFetcherCore::StartOnIOThread, this));
123 }
124 
Stop()125 void URLFetcherCore::Stop() {
126   if (delegate_task_runner_)  // May be NULL in tests.
127     DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
128 
129   delegate_ = nullptr;
130   fetcher_ = nullptr;
131   if (!network_task_runner_.get())
132     return;
133   if (network_task_runner_->RunsTasksInCurrentSequence()) {
134     CancelURLRequest(ERR_ABORTED);
135   } else {
136     network_task_runner_->PostTask(
137         FROM_HERE,
138         base::BindOnce(&URLFetcherCore::CancelURLRequest, this, ERR_ABORTED));
139   }
140 }
141 
SetUploadData(const std::string & upload_content_type,const std::string & upload_content)142 void URLFetcherCore::SetUploadData(const std::string& upload_content_type,
143                                    const std::string& upload_content) {
144   AssertHasNoUploadData();
145   DCHECK(!is_chunked_upload_);
146   DCHECK(upload_content_type_.empty());
147 
148   // Empty |upload_content_type| is allowed iff the |upload_content| is empty.
149   DCHECK(upload_content.empty() || !upload_content_type.empty());
150 
151   upload_content_type_ = upload_content_type;
152   upload_content_ = upload_content;
153   upload_content_set_ = true;
154 }
155 
SetUploadFilePath(const std::string & upload_content_type,const base::FilePath & file_path,uint64_t range_offset,uint64_t range_length,scoped_refptr<base::TaskRunner> file_task_runner)156 void URLFetcherCore::SetUploadFilePath(
157     const std::string& upload_content_type,
158     const base::FilePath& file_path,
159     uint64_t range_offset,
160     uint64_t range_length,
161     scoped_refptr<base::TaskRunner> file_task_runner) {
162   AssertHasNoUploadData();
163   DCHECK(!is_chunked_upload_);
164   DCHECK_EQ(upload_range_offset_, 0ULL);
165   DCHECK_EQ(upload_range_length_, 0ULL);
166   DCHECK(upload_content_type_.empty());
167   DCHECK(!upload_content_type.empty());
168 
169   upload_content_type_ = upload_content_type;
170   upload_file_path_ = file_path;
171   upload_range_offset_ = range_offset;
172   upload_range_length_ = range_length;
173   upload_file_task_runner_ = file_task_runner;
174   upload_content_set_ = true;
175 }
176 
SetUploadStreamFactory(const std::string & upload_content_type,const URLFetcher::CreateUploadStreamCallback & factory)177 void URLFetcherCore::SetUploadStreamFactory(
178     const std::string& upload_content_type,
179     const URLFetcher::CreateUploadStreamCallback& factory) {
180   AssertHasNoUploadData();
181   DCHECK(!is_chunked_upload_);
182   DCHECK(upload_content_type_.empty());
183 
184   upload_content_type_ = upload_content_type;
185   upload_stream_factory_ = factory;
186   upload_content_set_ = true;
187 }
188 
SetChunkedUpload(const std::string & content_type)189 void URLFetcherCore::SetChunkedUpload(const std::string& content_type) {
190   if (!is_chunked_upload_) {
191     AssertHasNoUploadData();
192     DCHECK(upload_content_type_.empty());
193   }
194 
195   // Empty |content_type| is not allowed here, because it is impossible
196   // to ensure non-empty upload content as it is not yet supplied.
197   DCHECK(!content_type.empty());
198 
199   upload_content_type_ = content_type;
200   base::STLClearObject(&upload_content_);
201   is_chunked_upload_ = true;
202 }
203 
AppendChunkToUpload(const std::string & content,bool is_last_chunk)204 void URLFetcherCore::AppendChunkToUpload(const std::string& content,
205                                          bool is_last_chunk) {
206   DCHECK(delegate_task_runner_);
207   DCHECK(network_task_runner_.get());
208   DCHECK(is_chunked_upload_);
209   network_task_runner_->PostTask(
210       FROM_HERE, base::BindOnce(&URLFetcherCore::CompleteAddingUploadDataChunk,
211                                 this, content, is_last_chunk));
212 }
213 
SetLoadFlags(int load_flags)214 void URLFetcherCore::SetLoadFlags(int load_flags) {
215   load_flags_ = load_flags;
216 }
217 
SetAllowCredentials(bool allow_credentials)218 void URLFetcherCore::SetAllowCredentials(bool allow_credentials) {
219   allow_credentials_ = base::make_optional<bool>(allow_credentials);
220 }
221 
GetLoadFlags() const222 int URLFetcherCore::GetLoadFlags() const {
223   return load_flags_;
224 }
225 
SetReferrer(const std::string & referrer)226 void URLFetcherCore::SetReferrer(const std::string& referrer) {
227   referrer_ = referrer;
228 }
229 
SetReferrerPolicy(ReferrerPolicy referrer_policy)230 void URLFetcherCore::SetReferrerPolicy(ReferrerPolicy referrer_policy) {
231   referrer_policy_ = referrer_policy;
232 }
233 
SetExtraRequestHeaders(const std::string & extra_request_headers)234 void URLFetcherCore::SetExtraRequestHeaders(
235     const std::string& extra_request_headers) {
236   extra_request_headers_.Clear();
237   extra_request_headers_.AddHeadersFromString(extra_request_headers);
238 }
239 
AddExtraRequestHeader(const std::string & header_line)240 void URLFetcherCore::AddExtraRequestHeader(const std::string& header_line) {
241   extra_request_headers_.AddHeaderFromString(header_line);
242 }
243 
SetRequestContext(URLRequestContextGetter * request_context_getter)244 void URLFetcherCore::SetRequestContext(
245     URLRequestContextGetter* request_context_getter) {
246   DCHECK(!request_context_getter_.get());
247   DCHECK(request_context_getter);
248   request_context_getter_ = request_context_getter;
249 }
250 
SetInitiator(const base::Optional<url::Origin> & initiator)251 void URLFetcherCore::SetInitiator(
252     const base::Optional<url::Origin>& initiator) {
253   DCHECK(!initiator_.has_value());
254   initiator_ = initiator;
255 }
256 
SetURLRequestUserData(const void * key,const URLFetcher::CreateDataCallback & create_data_callback)257 void URLFetcherCore::SetURLRequestUserData(
258     const void* key,
259     const URLFetcher::CreateDataCallback& create_data_callback) {
260   DCHECK(key);
261   DCHECK(!create_data_callback.is_null());
262   url_request_data_key_ = key;
263   url_request_create_data_callback_ = create_data_callback;
264 }
265 
SetStopOnRedirect(bool stop_on_redirect)266 void URLFetcherCore::SetStopOnRedirect(bool stop_on_redirect) {
267   stop_on_redirect_ = stop_on_redirect;
268 }
269 
SetAutomaticallyRetryOn5xx(bool retry)270 void URLFetcherCore::SetAutomaticallyRetryOn5xx(bool retry) {
271   automatically_retry_on_5xx_ = retry;
272 }
273 
SetMaxRetriesOn5xx(int max_retries)274 void URLFetcherCore::SetMaxRetriesOn5xx(int max_retries) {
275   max_retries_on_5xx_ = max_retries;
276 }
277 
GetMaxRetriesOn5xx() const278 int URLFetcherCore::GetMaxRetriesOn5xx() const {
279   return max_retries_on_5xx_;
280 }
281 
GetBackoffDelay() const282 base::TimeDelta URLFetcherCore::GetBackoffDelay() const {
283   return backoff_delay_;
284 }
285 
SetAutomaticallyRetryOnNetworkChanges(int max_retries)286 void URLFetcherCore::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
287   max_retries_on_network_changes_ = max_retries;
288 }
289 
SaveResponseToFileAtPath(const base::FilePath & file_path,scoped_refptr<base::SequencedTaskRunner> file_task_runner)290 void URLFetcherCore::SaveResponseToFileAtPath(
291     const base::FilePath& file_path,
292     scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
293   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
294   SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
295       new URLFetcherFileWriter(file_task_runner, file_path)));
296 }
297 
SaveResponseToTemporaryFile(scoped_refptr<base::SequencedTaskRunner> file_task_runner)298 void URLFetcherCore::SaveResponseToTemporaryFile(
299     scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
300   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
301   SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
302       new URLFetcherFileWriter(file_task_runner, base::FilePath())));
303 }
304 
SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter> response_writer)305 void URLFetcherCore::SaveResponseWithWriter(
306     std::unique_ptr<URLFetcherResponseWriter> response_writer) {
307   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
308   response_writer_ = std::move(response_writer);
309 }
310 
GetResponseHeaders() const311 HttpResponseHeaders* URLFetcherCore::GetResponseHeaders() const {
312   return response_headers_.get();
313 }
314 
315 // TODO(panayiotis): remote_endpoint_ is written in the IO thread,
316 // if this is accessed in the UI thread, this could result in a race.
317 // Same for response_headers_ above.
GetSocketAddress() const318 IPEndPoint URLFetcherCore::GetSocketAddress() const {
319   return remote_endpoint_;
320 }
321 
ProxyServerUsed() const322 const ProxyServer& URLFetcherCore::ProxyServerUsed() const {
323   return proxy_server_;
324 }
325 
WasCached() const326 bool URLFetcherCore::WasCached() const {
327   return was_cached_;
328 }
329 
GetReceivedResponseContentLength() const330 int64_t URLFetcherCore::GetReceivedResponseContentLength() const {
331   return received_response_content_length_;
332 }
333 
GetTotalReceivedBytes() const334 int64_t URLFetcherCore::GetTotalReceivedBytes() const {
335   return total_received_bytes_;
336 }
337 
GetOriginalURL() const338 const GURL& URLFetcherCore::GetOriginalURL() const {
339   return original_url_;
340 }
341 
GetURL() const342 const GURL& URLFetcherCore::GetURL() const {
343   return url_;
344 }
345 
GetError() const346 Error URLFetcherCore::GetError() const {
347   return error_;
348 }
349 
GetResponseCode() const350 int URLFetcherCore::GetResponseCode() const {
351   return response_code_;
352 }
353 
ReceivedContentWasMalformed()354 void URLFetcherCore::ReceivedContentWasMalformed() {
355   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
356   if (network_task_runner_.get()) {
357     network_task_runner_->PostTask(
358         FROM_HERE,
359         base::BindOnce(&URLFetcherCore::NotifyMalformedContent, this));
360   }
361 }
362 
GetResponseAsString(std::string * out_response_string) const363 bool URLFetcherCore::GetResponseAsString(
364     std::string* out_response_string) const {
365   URLFetcherStringWriter* string_writer =
366       response_writer_ ? response_writer_->AsStringWriter() : nullptr;
367   if (!string_writer)
368     return false;
369 
370   *out_response_string = string_writer->data();
371   return true;
372 }
373 
GetResponseAsFilePath(bool take_ownership,base::FilePath * out_response_path)374 bool URLFetcherCore::GetResponseAsFilePath(bool take_ownership,
375                                            base::FilePath* out_response_path) {
376   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
377 
378   URLFetcherFileWriter* file_writer =
379       response_writer_ ? response_writer_->AsFileWriter() : nullptr;
380   if (!file_writer)
381     return false;
382 
383   *out_response_path = file_writer->file_path();
384 
385   if (take_ownership) {
386     // Intentionally calling a file_writer_ method directly without posting
387     // the task to network_task_runner_.
388     //
389     // This is for correctly handling the case when file_writer_->DisownFile()
390     // is soon followed by URLFetcherCore::Stop(). We have to make sure that
391     // DisownFile takes effect before Stop deletes file_writer_.
392     //
393     // This direct call should be thread-safe, since DisownFile itself does no
394     // file operation. It just flips the state to be referred in destruction.
395     file_writer->DisownFile();
396   }
397   return true;
398 }
399 
OnReceivedRedirect(URLRequest * request,const RedirectInfo & redirect_info,bool * defer_redirect)400 void URLFetcherCore::OnReceivedRedirect(URLRequest* request,
401                                         const RedirectInfo& redirect_info,
402                                         bool* defer_redirect) {
403   DCHECK_EQ(request, request_.get());
404   DCHECK(network_task_runner_->BelongsToCurrentThread());
405   if (stop_on_redirect_) {
406     stopped_on_redirect_ = true;
407     url_ = redirect_info.new_url;
408     response_code_ = request_->GetResponseCode();
409     response_headers_ = request_->response_headers();
410     proxy_server_ = request_->proxy_server();
411     was_cached_ = request_->was_cached();
412     total_received_bytes_ += request_->GetTotalReceivedBytes();
413     int result = request->Cancel();
414     OnReadCompleted(request, result);
415   }
416 }
417 
OnResponseStarted(URLRequest * request,int net_error)418 void URLFetcherCore::OnResponseStarted(URLRequest* request, int net_error) {
419   DCHECK_EQ(request, request_.get());
420   DCHECK(network_task_runner_->BelongsToCurrentThread());
421   DCHECK_NE(ERR_IO_PENDING, net_error);
422 
423   if (net_error == OK) {
424     response_code_ = request_->GetResponseCode();
425     response_headers_ = request_->response_headers();
426     remote_endpoint_ = request_->GetResponseRemoteEndpoint();
427     proxy_server_ = request_->proxy_server();
428     was_cached_ = request_->was_cached();
429     total_response_bytes_ = request_->GetExpectedContentSize();
430   }
431 
432   DCHECK(!buffer_);
433   if (request_type_ != URLFetcher::HEAD)
434     buffer_ = base::MakeRefCounted<IOBuffer>(kBufferSize);
435   ReadResponse();
436 }
437 
OnCertificateRequested(URLRequest * request,SSLCertRequestInfo * cert_request_info)438 void URLFetcherCore::OnCertificateRequested(
439     URLRequest* request,
440     SSLCertRequestInfo* cert_request_info) {
441   DCHECK_EQ(request, request_.get());
442   DCHECK(network_task_runner_->BelongsToCurrentThread());
443 
444   if (g_ignore_certificate_requests) {
445     request->ContinueWithCertificate(nullptr, nullptr);
446   } else {
447     request->Cancel();
448   }
449 }
450 
OnReadCompleted(URLRequest * request,int bytes_read)451 void URLFetcherCore::OnReadCompleted(URLRequest* request,
452                                      int bytes_read) {
453   DCHECK_EQ(request, request_.get());
454   DCHECK(network_task_runner_->BelongsToCurrentThread());
455 
456   if (!stopped_on_redirect_)
457     url_ = request->url();
458   URLRequestThrottlerManager* throttler_manager =
459       request->context()->throttler_manager();
460   if (throttler_manager)
461     url_throttler_entry_ = throttler_manager->RegisterRequestUrl(url_);
462 
463   while (bytes_read > 0) {
464     current_response_bytes_ += bytes_read;
465     InformDelegateDownloadProgress();
466 
467     const int result = WriteBuffer(
468         base::MakeRefCounted<DrainableIOBuffer>(buffer_, bytes_read));
469     if (result < 0) {
470       // Write failed or waiting for write completion.
471       return;
472     }
473     bytes_read = request_->Read(buffer_.get(), kBufferSize);
474   }
475 
476   // See comments re: HEAD requests in ReadResponse().
477   if (bytes_read != ERR_IO_PENDING || request_type_ == URLFetcher::HEAD) {
478     error_ = static_cast<Error>(bytes_read);
479     received_response_content_length_ =
480         request_->received_response_content_length();
481     total_received_bytes_ += request_->GetTotalReceivedBytes();
482     ReleaseRequest();
483 
484     // No more data to write.
485     const int result = response_writer_->Finish(
486         bytes_read > 0 ? OK : bytes_read,
487         base::BindOnce(&URLFetcherCore::DidFinishWriting, this));
488     if (result != ERR_IO_PENDING)
489       DidFinishWriting(result);
490   }
491 }
492 
OnContextShuttingDown()493 void URLFetcherCore::OnContextShuttingDown() {
494   DCHECK(request_);
495   CancelRequestAndInformDelegate(ERR_CONTEXT_SHUT_DOWN);
496 }
497 
CancelAll()498 void URLFetcherCore::CancelAll() {
499   g_registry.Get().CancelAll();
500 }
501 
GetNumFetcherCores()502 int URLFetcherCore::GetNumFetcherCores() {
503   return g_registry.Get().size();
504 }
505 
SetIgnoreCertificateRequests(bool ignored)506 void URLFetcherCore::SetIgnoreCertificateRequests(bool ignored) {
507   g_ignore_certificate_requests = ignored;
508 }
509 
~URLFetcherCore()510 URLFetcherCore::~URLFetcherCore() {
511   // |request_| should be NULL. If not, it's unsafe to delete it here since we
512   // may not be on the IO thread.
513   DCHECK(!request_.get());
514 }
515 
StartOnIOThread()516 void URLFetcherCore::StartOnIOThread() {
517   DCHECK(network_task_runner_->BelongsToCurrentThread());
518 
519   // Create ChunkedUploadDataStream, if needed, so the consumer can start
520   // appending data.  Have to do it here because StartURLRequest() may be called
521   // asynchonously.
522   if (is_chunked_upload_) {
523     chunked_stream_.reset(new ChunkedUploadDataStream(0));
524     chunked_stream_writer_ = chunked_stream_->CreateWriter();
525   }
526 
527   if (!response_writer_)
528     response_writer_.reset(new URLFetcherStringWriter);
529 
530   const int result = response_writer_->Initialize(
531       base::BindOnce(&URLFetcherCore::DidInitializeWriter, this));
532   if (result != ERR_IO_PENDING)
533     DidInitializeWriter(result);
534 }
535 
StartURLRequest()536 void URLFetcherCore::StartURLRequest() {
537   DCHECK(network_task_runner_->BelongsToCurrentThread());
538 
539   if (was_cancelled_) {
540     // Since StartURLRequest() is posted as a *delayed* task, it may
541     // run after the URLFetcher was already stopped.
542     return;
543   }
544 
545   DCHECK(request_context_getter_);
546   if (!request_context_getter_->GetURLRequestContext()) {
547     CancelRequestAndInformDelegate(ERR_CONTEXT_SHUT_DOWN);
548     return;
549   }
550 
551   DCHECK(!request_.get());
552 
553   g_registry.Get().AddURLFetcherCore(this);
554   current_response_bytes_ = 0;
555   request_context_getter_->AddObserver(this);
556   request_ = request_context_getter_->GetURLRequestContext()->CreateRequest(
557       original_url_, DEFAULT_PRIORITY, this, traffic_annotation_);
558   int flags = request_->load_flags() | load_flags_;
559 
560   // TODO(mmenke): This should really be with the other code to set the upload
561   // body, below.
562   if (chunked_stream_)
563     request_->set_upload(std::move(chunked_stream_));
564 
565   request_->SetLoadFlags(flags);
566   if (allow_credentials_) {
567     request_->set_allow_credentials(allow_credentials_.value());
568   }
569   request_->SetReferrer(referrer_);
570   request_->set_referrer_policy(referrer_policy_);
571   request_->set_site_for_cookies(SiteForCookies::FromUrl(
572       initiator_.has_value() && !initiator_.value().opaque()
573           ? initiator_.value().GetURL()
574           : original_url_));
575   request_->set_initiator(initiator_);
576   if (url_request_data_key_ && !url_request_create_data_callback_.is_null()) {
577     request_->SetUserData(url_request_data_key_,
578                           url_request_create_data_callback_.Run());
579   }
580 
581   switch (request_type_) {
582     case URLFetcher::GET:
583       break;
584 
585     case URLFetcher::POST:
586     case URLFetcher::PUT:
587     case URLFetcher::PATCH: {
588       // Upload content must be set.
589       DCHECK(is_chunked_upload_ || upload_content_set_);
590 
591       request_->set_method(
592           request_type_ == URLFetcher::POST ? "POST" :
593           request_type_ == URLFetcher::PUT ? "PUT" : "PATCH");
594       if (!upload_content_type_.empty()) {
595         extra_request_headers_.SetHeader(HttpRequestHeaders::kContentType,
596                                          upload_content_type_);
597       }
598       if (!upload_content_.empty()) {
599         std::unique_ptr<UploadElementReader> reader(
600             new UploadBytesElementReader(upload_content_.data(),
601                                          upload_content_.size()));
602         request_->set_upload(
603             ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
604       } else if (!upload_file_path_.empty()) {
605         std::unique_ptr<UploadElementReader> reader(new UploadFileElementReader(
606             upload_file_task_runner_.get(), upload_file_path_,
607             upload_range_offset_, upload_range_length_, base::Time()));
608         request_->set_upload(
609             ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
610       } else if (!upload_stream_factory_.is_null()) {
611         std::unique_ptr<UploadDataStream> stream = upload_stream_factory_.Run();
612         DCHECK(stream);
613         request_->set_upload(std::move(stream));
614       }
615 
616       current_upload_bytes_ = -1;
617       // TODO(kinaba): http://crbug.com/118103. Implement upload callback in the
618       //  layer and avoid using timer here.
619       upload_progress_checker_timer_.reset(new base::RepeatingTimer());
620       upload_progress_checker_timer_->Start(
621           FROM_HERE,
622           base::TimeDelta::FromMilliseconds(kUploadProgressTimerInterval),
623           this,
624           &URLFetcherCore::InformDelegateUploadProgress);
625       break;
626     }
627 
628     case URLFetcher::HEAD:
629       request_->set_method("HEAD");
630       break;
631 
632     case URLFetcher::DELETE_REQUEST:
633       request_->set_method("DELETE");
634       break;
635 
636     default:
637       NOTREACHED();
638   }
639 
640   if (!extra_request_headers_.IsEmpty())
641     request_->SetExtraRequestHeaders(extra_request_headers_);
642 
643   request_->Start();
644 }
645 
DidInitializeWriter(int result)646 void URLFetcherCore::DidInitializeWriter(int result) {
647   if (result != OK) {
648     CancelRequestAndInformDelegate(result);
649     return;
650   }
651   StartURLRequestWhenAppropriate();
652 }
653 
StartURLRequestWhenAppropriate()654 void URLFetcherCore::StartURLRequestWhenAppropriate() {
655   DCHECK(network_task_runner_->BelongsToCurrentThread());
656 
657   if (was_cancelled_)
658     return;
659 
660   DCHECK(request_context_getter_.get());
661 
662   // Check if the request should be delayed, and if so, post a task to start it
663   // after the delay has expired.  Otherwise, start it now.
664 
665   URLRequestContext* context = request_context_getter_->GetURLRequestContext();
666   // If the context has been shut down, or there's no ThrottlerManager, just
667   // start the request.  In the former case, StartURLRequest() will just inform
668   // the URLFetcher::Delegate the request has been canceled.
669   if (context && context->throttler_manager()) {
670     if (!original_url_throttler_entry_.get()) {
671       original_url_throttler_entry_ =
672           context->throttler_manager()->RegisterRequestUrl(original_url_);
673     }
674 
675     if (original_url_throttler_entry_.get()) {
676       int64_t delay =
677           original_url_throttler_entry_->ReserveSendingTimeForNextRequest(
678               GetBackoffReleaseTime());
679       if (delay != 0) {
680         network_task_runner_->PostDelayedTask(
681             FROM_HERE, base::BindOnce(&URLFetcherCore::StartURLRequest, this),
682             base::TimeDelta::FromMilliseconds(delay));
683         return;
684       }
685     }
686   }
687 
688   StartURLRequest();
689 }
690 
CancelURLRequest(int error)691 void URLFetcherCore::CancelURLRequest(int error) {
692   DCHECK(network_task_runner_->BelongsToCurrentThread());
693 
694   if (request_.get()) {
695     request_->CancelWithError(error);
696     ReleaseRequest();
697   }
698   error_ = static_cast<Error>(error);
699 
700   // Release the reference to the request context. There could be multiple
701   // references to URLFetcher::Core at this point so it may take a while to
702   // delete the object, but we cannot delay the destruction of the request
703   // context.
704   request_context_getter_ = nullptr;
705   initiator_.reset();
706   url_request_data_key_ = nullptr;
707   url_request_create_data_callback_.Reset();
708   was_cancelled_ = true;
709 }
710 
OnCompletedURLRequest(base::TimeDelta backoff_delay)711 void URLFetcherCore::OnCompletedURLRequest(
712     base::TimeDelta backoff_delay) {
713   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
714 
715   // Save the status and backoff_delay so that delegates can read it.
716   if (delegate_) {
717     backoff_delay_ = backoff_delay;
718     InformDelegateFetchIsComplete();
719   }
720 }
721 
InformDelegateFetchIsComplete()722 void URLFetcherCore::InformDelegateFetchIsComplete() {
723   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
724   if (delegate_)
725     delegate_->OnURLFetchComplete(fetcher_);
726 }
727 
NotifyMalformedContent()728 void URLFetcherCore::NotifyMalformedContent() {
729   DCHECK(network_task_runner_->BelongsToCurrentThread());
730   if (url_throttler_entry_.get()) {
731     int status_code = response_code_;
732     if (status_code == URLFetcher::RESPONSE_CODE_INVALID) {
733       // The status code will generally be known by the time clients
734       // call the |ReceivedContentWasMalformed()| function (which ends up
735       // calling the current function) but if it's not, we need to assume
736       // the response was successful so that the total failure count
737       // used to calculate exponential back-off goes up.
738       status_code = 200;
739     }
740     url_throttler_entry_->ReceivedContentWasMalformed(status_code);
741   }
742 }
743 
DidFinishWriting(int result)744 void URLFetcherCore::DidFinishWriting(int result) {
745   if (result != OK) {
746     CancelRequestAndInformDelegate(result);
747     return;
748   }
749   // If the file was successfully closed, then the URL request is complete.
750   RetryOrCompleteUrlFetch();
751 }
752 
RetryOrCompleteUrlFetch()753 void URLFetcherCore::RetryOrCompleteUrlFetch() {
754   DCHECK(network_task_runner_->BelongsToCurrentThread());
755   base::TimeDelta backoff_delay;
756 
757   // Checks the response from server.
758   if (response_code_ >= 500 || error_ == ERR_TEMPORARILY_THROTTLED) {
759     // When encountering a server error, we will send the request again
760     // after backoff time.
761     ++num_retries_on_5xx_;
762 
763     // Note that backoff_delay may be 0 because (a) the
764     // URLRequestThrottlerManager and related code does not
765     // necessarily back off on the first error, (b) it only backs off
766     // on some of the 5xx status codes, (c) not all URLRequestContexts
767     // have a throttler manager.
768     base::TimeTicks backoff_release_time = GetBackoffReleaseTime();
769     backoff_delay = backoff_release_time - base::TimeTicks::Now();
770     if (backoff_delay < base::TimeDelta())
771       backoff_delay = base::TimeDelta();
772 
773     if (automatically_retry_on_5xx_ &&
774         num_retries_on_5xx_ <= max_retries_on_5xx_) {
775       StartOnIOThread();
776       return;
777     }
778   } else {
779     backoff_delay = base::TimeDelta();
780   }
781 
782   // Retry if the request failed due to network changes.
783   if (error_ == ERR_NETWORK_CHANGED &&
784       num_retries_on_network_changes_ < max_retries_on_network_changes_) {
785     ++num_retries_on_network_changes_;
786 
787     // Retry soon, after flushing all the current tasks which may include
788     // further network change observers.
789     network_task_runner_->PostTask(
790         FROM_HERE, base::BindOnce(&URLFetcherCore::StartOnIOThread, this));
791     return;
792   }
793 
794   request_context_getter_ = nullptr;
795   initiator_.reset();
796   url_request_data_key_ = nullptr;
797   url_request_create_data_callback_.Reset();
798   bool posted = delegate_task_runner_->PostTask(
799       FROM_HERE, base::BindOnce(&URLFetcherCore::OnCompletedURLRequest, this,
800                                 backoff_delay));
801 
802   // If the delegate message loop does not exist any more, then the delegate
803   // should be gone too.
804   DCHECK(posted || !delegate_);
805 }
806 
CancelRequestAndInformDelegate(int result)807 void URLFetcherCore::CancelRequestAndInformDelegate(int result) {
808   CancelURLRequest(result);
809   delegate_task_runner_->PostTask(
810       FROM_HERE,
811       base::BindOnce(&URLFetcherCore::InformDelegateFetchIsComplete, this));
812 }
813 
ReleaseRequest()814 void URLFetcherCore::ReleaseRequest() {
815   request_context_getter_->RemoveObserver(this);
816   upload_progress_checker_timer_.reset();
817   request_.reset();
818   buffer_ = nullptr;
819   g_registry.Get().RemoveURLFetcherCore(this);
820 }
821 
GetBackoffReleaseTime()822 base::TimeTicks URLFetcherCore::GetBackoffReleaseTime() {
823   DCHECK(network_task_runner_->BelongsToCurrentThread());
824 
825   if (!original_url_throttler_entry_.get())
826     return base::TimeTicks();
827 
828   base::TimeTicks original_url_backoff =
829       original_url_throttler_entry_->GetExponentialBackoffReleaseTime();
830   base::TimeTicks destination_url_backoff;
831   if (url_throttler_entry_.get() &&
832       original_url_throttler_entry_.get() != url_throttler_entry_.get()) {
833     destination_url_backoff =
834         url_throttler_entry_->GetExponentialBackoffReleaseTime();
835   }
836 
837   return original_url_backoff > destination_url_backoff ?
838       original_url_backoff : destination_url_backoff;
839 }
840 
CompleteAddingUploadDataChunk(const std::string & content,bool is_last_chunk)841 void URLFetcherCore::CompleteAddingUploadDataChunk(
842     const std::string& content, bool is_last_chunk) {
843   DCHECK(is_chunked_upload_);
844   DCHECK(!content.empty());
845   chunked_stream_writer_->AppendData(
846       content.data(), static_cast<int>(content.length()), is_last_chunk);
847 }
848 
WriteBuffer(scoped_refptr<DrainableIOBuffer> data)849 int URLFetcherCore::WriteBuffer(scoped_refptr<DrainableIOBuffer> data) {
850   while (data->BytesRemaining() > 0) {
851     const int result = response_writer_->Write(
852         data.get(), data->BytesRemaining(),
853         base::BindOnce(&URLFetcherCore::DidWriteBuffer, this, data));
854     if (result < 0) {
855       if (result != ERR_IO_PENDING)
856         DidWriteBuffer(data, result);
857       return result;
858     }
859     data->DidConsume(result);
860   }
861   return OK;
862 }
863 
DidWriteBuffer(scoped_refptr<DrainableIOBuffer> data,int result)864 void URLFetcherCore::DidWriteBuffer(scoped_refptr<DrainableIOBuffer> data,
865                                     int result) {
866   if (result < 0) {  // Handle errors.
867     response_writer_->Finish(result, base::DoNothing());
868     CancelRequestAndInformDelegate(result);
869     return;
870   }
871 
872   // Continue writing.
873   data->DidConsume(result);
874   if (WriteBuffer(data) < 0)
875     return;
876 
877   // Finished writing buffer_. Read some more, unless the request has been
878   // cancelled and deleted.
879   DCHECK_EQ(0, data->BytesRemaining());
880   if (request_.get())
881     ReadResponse();
882 }
883 
ReadResponse()884 void URLFetcherCore::ReadResponse() {
885   // Some servers may treat HEAD requests as GET requests. To free up the
886   // network connection as soon as possible, signal that the request has
887   // completed immediately, without trying to read any data back (all we care
888   // about is the response code and headers, which we already have).
889   int bytes_read = 0;
890   if (request_type_ != URLFetcher::HEAD)
891     bytes_read = request_->Read(buffer_.get(), kBufferSize);
892 
893   OnReadCompleted(request_.get(), bytes_read);
894 }
895 
InformDelegateUploadProgress()896 void URLFetcherCore::InformDelegateUploadProgress() {
897   DCHECK(network_task_runner_->BelongsToCurrentThread());
898   if (request_.get()) {
899     int64_t current = request_->GetUploadProgress().position();
900     if (current_upload_bytes_ != current) {
901       current_upload_bytes_ = current;
902       int64_t total = -1;
903       if (!is_chunked_upload_) {
904         total = static_cast<int64_t>(request_->GetUploadProgress().size());
905         // Total may be zero if the UploadDataStream::Init has not been called
906         // yet. Don't send the upload progress until the size is initialized.
907         if (!total)
908           return;
909       }
910       delegate_task_runner_->PostTask(
911           FROM_HERE,
912           base::BindOnce(
913               &URLFetcherCore::InformDelegateUploadProgressInDelegateSequence,
914               this, current, total));
915     }
916   }
917 }
918 
InformDelegateUploadProgressInDelegateSequence(int64_t current,int64_t total)919 void URLFetcherCore::InformDelegateUploadProgressInDelegateSequence(
920     int64_t current,
921     int64_t total) {
922   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
923   if (delegate_)
924     delegate_->OnURLFetchUploadProgress(fetcher_, current, total);
925 }
926 
InformDelegateDownloadProgress()927 void URLFetcherCore::InformDelegateDownloadProgress() {
928   DCHECK(network_task_runner_->BelongsToCurrentThread());
929   delegate_task_runner_->PostTask(
930       FROM_HERE,
931       base::BindOnce(
932           &URLFetcherCore::InformDelegateDownloadProgressInDelegateSequence,
933           this, current_response_bytes_, total_response_bytes_,
934           request_->GetTotalReceivedBytes()));
935 }
936 
InformDelegateDownloadProgressInDelegateSequence(int64_t current,int64_t total,int64_t current_network_bytes)937 void URLFetcherCore::InformDelegateDownloadProgressInDelegateSequence(
938     int64_t current,
939     int64_t total,
940     int64_t current_network_bytes) {
941   DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
942   if (delegate_)
943     delegate_->OnURLFetchDownloadProgress(fetcher_, current, total,
944                                           current_network_bytes);
945 }
946 
AssertHasNoUploadData() const947 void URLFetcherCore::AssertHasNoUploadData() const {
948   DCHECK(!upload_content_set_);
949   DCHECK(upload_content_.empty());
950   DCHECK(upload_file_path_.empty());
951   DCHECK(upload_stream_factory_.is_null());
952 }
953 
954 }  // namespace net
955