blob: 8cbe5ec7c65097a87e5a5c7e4216096fe5513a6d [file] [log] [blame]
Max Boguefef332d2016-07-28 22:09:091// Copyright 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
maxboguef0ab40f52016-10-11 16:12:405#include "components/sync/engine/net/http_bridge.h"
Max Boguefef332d2016-07-28 22:09:096
7#include <stddef.h>
Max Boguefef332d2016-07-28 22:09:098
Antonio Gomesbf4f2992018-08-25 03:35:079#include <utility>
Max Boguefef332d2016-07-28 22:09:0910
Sebastien Marchand53801a32019-01-25 16:26:1111#include "base/bind.h"
Matt Menke991dd7e2021-07-22 17:31:5112#include "base/lazy_instance.h"
Max Boguefef332d2016-07-28 22:09:0913#include "base/location.h"
Ilya Sherman1edb6f182017-12-12 04:00:4214#include "base/metrics/histogram_functions.h"
Max Boguefef332d2016-07-28 22:09:0915#include "base/metrics/histogram_macros.h"
Antonio Gomesbf4f2992018-08-25 03:35:0716#include "base/task/post_task.h"
Gabriel Charettedd8d5985e2020-02-26 18:38:3517#include "base/task/thread_pool.h"
Olivier Li4db886a2019-11-13 13:48:2218#include "base/threading/thread_restrictions.h"
Mikel Astizf66cb7262019-12-04 20:16:4519#include "components/variations/net/variations_http_headers.h"
Max Boguefef332d2016-07-28 22:09:0920#include "net/base/load_flags.h"
21#include "net/base/net_errors.h"
22#include "net/http/http_cache.h"
23#include "net/http/http_network_layer.h"
24#include "net/http/http_request_headers.h"
25#include "net/http/http_response_headers.h"
rhalavati75a414c2017-03-09 13:56:3726#include "net/traffic_annotation/network_traffic_annotation.h"
Max Boguefef332d2016-07-28 22:09:0927#include "net/url_request/static_http_user_agent_settings.h"
Sigurd Schneidere3d43c6b2021-07-27 13:35:0128#include "services/network/public/cpp/resource_request.h"
Antonio Gomesbf4f2992018-08-25 03:35:0729#include "services/network/public/cpp/simple_url_loader.h"
Matt Menke5096a862021-07-17 20:30:0030#include "services/network/public/mojom/url_response_head.mojom.h"
gangwu56d48222016-10-20 00:00:4631#include "third_party/zlib/google/compression_utils.h"
Max Boguefef332d2016-07-28 22:09:0932
33namespace syncer {
34
35namespace {
36
37// It's possible for an http request to be silently stalled. We set a time
38// limit for all http requests, beyond which the request is cancelled and
39// treated as a transient failure.
Peter Kastinge5a38ed2021-10-02 03:06:3540constexpr base::TimeDelta kMaxHttpRequestTime = base::Minutes(5);
Max Boguefef332d2016-07-28 22:09:0941
42// Helper method for logging timeouts via UMA.
43void LogTimeout(bool timed_out) {
44 UMA_HISTOGRAM_BOOLEAN("Sync.URLFetchTimedOut", timed_out);
45}
46
Antonio Gomesbf4f2992018-08-25 03:35:0747base::LazyInstance<scoped_refptr<base::SequencedTaskRunner>>::Leaky
48 g_io_capable_task_runner_for_tests = LAZY_INSTANCE_INITIALIZER;
49
Max Boguefef332d2016-07-28 22:09:0950} // namespace
51
52HttpBridgeFactory::HttpBridgeFactory(
Marc Treib0df8aa42019-11-14 13:51:3253 const std::string& user_agent,
Dominic Farolinobc280d22019-12-05 05:49:2454 std::unique_ptr<network::PendingSharedURLLoaderFactory>
Victor Hugo Vianna Silvaaa4984172021-06-29 11:29:1955 pending_url_loader_factory)
56 : user_agent_(user_agent) {
Dominic Farolinobc280d22019-12-05 05:49:2457 // Some tests pass null'ed out pending_url_loader_factory instances.
58 if (pending_url_loader_factory) {
Antonio Gomesbf4f2992018-08-25 03:35:0759 url_loader_factory_ = network::SharedURLLoaderFactory::Create(
Dominic Farolinobc280d22019-12-05 05:49:2460 std::move(pending_url_loader_factory));
Antonio Gomesbf4f2992018-08-25 03:35:0761 }
Max Boguefef332d2016-07-28 22:09:0962}
63
Marc Treibe6ace162019-11-13 15:23:2264HttpBridgeFactory::~HttpBridgeFactory() = default;
Max Boguefef332d2016-07-28 22:09:0965
Marc Treibb9454e02020-10-13 09:31:0766scoped_refptr<HttpPostProviderInterface> HttpBridgeFactory::Create() {
Antonio Gomesbf4f2992018-08-25 03:35:0767 DCHECK(url_loader_factory_);
Max Boguefef332d2016-07-28 22:09:0968
Victor Hugo Vianna Silvaaa4984172021-06-29 11:29:1969 scoped_refptr<HttpPostProviderInterface> http =
70 new HttpBridge(user_agent_, url_loader_factory_->Clone());
Marc Treibb9454e02020-10-13 09:31:0771 return http;
Max Boguefef332d2016-07-28 22:09:0972}
73
Max Boguefef332d2016-07-28 22:09:0974HttpBridge::URLFetchState::URLFetchState()
Antonio Gomesbf4f2992018-08-25 03:35:0775 : aborted(false),
Max Boguefef332d2016-07-28 22:09:0976 request_completed(false),
77 request_succeeded(false),
Mikel Astiz1de5fe92018-11-23 11:43:4278 http_status_code(-1),
Mikel Astiz3a64405f2018-11-22 15:50:3179 net_error_code(-1) {}
Victor Hugo Vianna Silva988fe7322021-09-23 18:16:5680HttpBridge::URLFetchState::~URLFetchState() = default;
Max Boguefef332d2016-07-28 22:09:0981
Victor Hugo Vianna Silvaaa4984172021-06-29 11:29:1982HttpBridge::HttpBridge(const std::string& user_agent,
83 std::unique_ptr<network::PendingSharedURLLoaderFactory>
84 pending_url_loader_factory)
Max Boguefef332d2016-07-28 22:09:0985 : user_agent_(user_agent),
86 http_post_completed_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
87 base::WaitableEvent::InitialState::NOT_SIGNALED),
Dominic Farolinobc280d22019-12-05 05:49:2488 pending_url_loader_factory_(std::move(pending_url_loader_factory)),
Sami Kyostila14ca7642019-08-01 17:52:2589 network_task_runner_(g_io_capable_task_runner_for_tests.Get()
90 ? g_io_capable_task_runner_for_tests.Get()
Gabriel Charettedd8d5985e2020-02-26 18:38:3591 : base::ThreadPool::CreateSequencedTaskRunner(
Victor Hugo Vianna Silvaaa4984172021-06-29 11:29:1992 {base::MayBlock()})) {}
Max Boguefef332d2016-07-28 22:09:0993
Marc Treibb9454e02020-10-13 09:31:0794HttpBridge::~HttpBridge() = default;
Max Boguefef332d2016-07-28 22:09:0995
96void HttpBridge::SetExtraRequestHeaders(const char* headers) {
97 DCHECK(extra_headers_.empty())
98 << "HttpBridge::SetExtraRequestHeaders called twice.";
99 extra_headers_.assign(headers);
100}
101
Marc Treibbdbf75422020-10-15 09:42:39102void HttpBridge::SetURL(const GURL& url) {
Max Boguefef332d2016-07-28 22:09:09103#if DCHECK_IS_ON()
104 DCHECK(thread_checker_.CalledOnValidThread());
105 {
106 base::AutoLock lock(fetch_state_lock_);
107 DCHECK(!fetch_state_.request_completed);
108 }
109 DCHECK(url_for_request_.is_empty())
110 << "HttpBridge::SetURL called more than once?!";
111#endif
Marc Treibbdbf75422020-10-15 09:42:39112 url_for_request_ = url;
Max Boguefef332d2016-07-28 22:09:09113}
114
115void HttpBridge::SetPostPayload(const char* content_type,
116 int content_length,
117 const char* content) {
118#if DCHECK_IS_ON()
119 DCHECK(thread_checker_.CalledOnValidThread());
120 {
121 base::AutoLock lock(fetch_state_lock_);
122 DCHECK(!fetch_state_.request_completed);
123 }
124 DCHECK(content_type_.empty()) << "Bridge payload already set.";
125 DCHECK_GE(content_length, 0) << "Content length < 0";
126#endif
127 content_type_ = content_type;
128 if (!content || (content_length == 0)) {
129 DCHECK_EQ(content_length, 0);
130 request_content_ = " "; // TODO(timsteele): URLFetcher requires non-empty
131 // content for POSTs whereas CURL does not, for now
132 // we hack this to support the sync backend.
133 } else {
134 request_content_.assign(content, content_length);
135 }
136}
137
Mikel Astiz3a64405f2018-11-22 15:50:31138bool HttpBridge::MakeSynchronousPost(int* net_error_code,
Mikel Astiz1de5fe92018-11-23 11:43:42139 int* http_status_code) {
Max Boguefef332d2016-07-28 22:09:09140#if DCHECK_IS_ON()
141 DCHECK(thread_checker_.CalledOnValidThread());
142 {
143 base::AutoLock lock(fetch_state_lock_);
144 DCHECK(!fetch_state_.request_completed);
145 }
146 DCHECK(url_for_request_.is_valid()) << "Invalid URL for request";
147 DCHECK(!content_type_.empty()) << "Payload not set";
148#endif
149
150 if (!network_task_runner_->PostTask(
tzik2bcf8e42018-07-31 11:22:15151 FROM_HERE,
152 base::BindOnce(&HttpBridge::CallMakeAsynchronousPost, this))) {
Max Boguefef332d2016-07-28 22:09:09153 // This usually happens when we're in a unit test.
154 LOG(WARNING) << "Could not post CallMakeAsynchronousPost task";
155 return false;
156 }
157
158 // Block until network request completes or is aborted. See
159 // OnURLFetchComplete and Abort.
Olivier Li4db886a2019-11-13 13:48:22160 {
161 base::ScopedAllowBaseSyncPrimitives allow_wait;
162 http_post_completed_.Wait();
163 }
Max Boguefef332d2016-07-28 22:09:09164
165 base::AutoLock lock(fetch_state_lock_);
166 DCHECK(fetch_state_.request_completed || fetch_state_.aborted);
Mikel Astiz3a64405f2018-11-22 15:50:31167 *net_error_code = fetch_state_.net_error_code;
Mikel Astiz1de5fe92018-11-23 11:43:42168 *http_status_code = fetch_state_.http_status_code;
Max Boguefef332d2016-07-28 22:09:09169 return fetch_state_.request_succeeded;
170}
171
172void HttpBridge::MakeAsynchronousPost() {
Antonio Gomesbf4f2992018-08-25 03:35:07173 DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
Max Boguefef332d2016-07-28 22:09:09174
175 base::AutoLock lock(fetch_state_lock_);
176 DCHECK(!fetch_state_.request_completed);
177 if (fetch_state_.aborted)
178 return;
179
180 // Start the timer on the network thread (the same thread progress is made
181 // on, and on which the url fetcher lives).
Zinovy Nis701103b2018-05-10 22:59:38182 DCHECK(!fetch_state_.http_request_timeout_timer);
Patrick Monettead70b872021-04-16 18:49:26183 fetch_state_.http_request_timeout_timer = std::make_unique<base::DelayTimer>(
184 FROM_HERE, kMaxHttpRequestTime, this, &HttpBridge::OnURLLoadTimedOut);
185 fetch_state_.http_request_timeout_timer->Reset();
Max Boguefef332d2016-07-28 22:09:09186
Antonio Gomesbf4f2992018-08-25 03:35:07187 // Some tests inject |url_loader_factory_| created to operated on the
188 // IO-capable thread currently running.
Dominic Farolinobc280d22019-12-05 05:49:24189 DCHECK((!url_loader_factory_ && pending_url_loader_factory_) ||
190 (url_loader_factory_ && !pending_url_loader_factory_));
Antonio Gomesbf4f2992018-08-25 03:35:07191 if (!url_loader_factory_) {
Dominic Farolinobc280d22019-12-05 05:49:24192 DCHECK(pending_url_loader_factory_);
Antonio Gomesbf4f2992018-08-25 03:35:07193 url_loader_factory_ = network::SharedURLLoaderFactory::Create(
Dominic Farolinobc280d22019-12-05 05:49:24194 std::move(pending_url_loader_factory_));
Antonio Gomesbf4f2992018-08-25 03:35:07195 }
196
Max Boguefef332d2016-07-28 22:09:09197 fetch_state_.start_time = base::Time::Now();
rhalavati75a414c2017-03-09 13:56:37198 net::NetworkTrafficAnnotationTag traffic_annotation =
199 net::DefineNetworkTrafficAnnotation("sync_http_bridge", R"(
200 semantics {
201 sender: "Chrome Sync"
202 description:
203 "Chrome Sync synchronizes profile data between Chromium clients "
204 "and Google for a given user account."
205 trigger:
206 "User makes a change to syncable profile data after enabling sync "
207 "on the device."
208 data:
209 "The device and user identifiers, along with any profile data that "
210 "is changing."
211 destination: GOOGLE_OWNED_SERVICE
212 }
213 policy {
Ramin Halavati3b979782017-07-21 11:40:26214 cookies_allowed: NO
rhalavati75a414c2017-03-09 13:56:37215 setting:
216 "Users can disable Chrome Sync by going into the profile settings "
217 "and choosing to Sign Out."
218 chrome_policy {
219 SyncDisabled {
220 policy_options {mode: MANDATORY}
221 SyncDisabled: true
222 }
223 }
224 })");
Antonio Gomesbf4f2992018-08-25 03:35:07225 auto resource_request = std::make_unique<network::ResourceRequest>();
226 resource_request->url = url_for_request_;
227 resource_request->method = "POST";
228 resource_request->load_flags =
David Benjamin29f864ef2019-08-13 20:51:01229 net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
230 resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
Antonio Gomesbf4f2992018-08-25 03:35:07231
232 if (!extra_headers_.empty())
233 resource_request->headers.AddHeadersFromString(extra_headers_);
234
235 resource_request->headers.SetHeader("Content-Encoding", "gzip");
236 resource_request->headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
237 user_agent_);
238
Mikel Astizf66cb7262019-12-04 20:16:45239 variations::AppendVariationsHeader(
240 url_for_request_, variations::InIncognito::kNo,
241 variations::SignedIn::kYes, resource_request.get());
242
Antonio Gomesbf4f2992018-08-25 03:35:07243 fetch_state_.url_loader = network::SimpleURLLoader::Create(
244 std::move(resource_request), traffic_annotation);
245 network::SimpleURLLoader* url_loader = fetch_state_.url_loader.get();
246
gangwu56d48222016-10-20 00:00:46247 std::string request_to_send;
gangwua3141372017-02-22 07:13:14248 compression::GzipCompress(request_content_, &request_to_send);
Antonio Gomesbf4f2992018-08-25 03:35:07249 url_loader->AttachStringForUpload(request_to_send, content_type_);
Max Boguefef332d2016-07-28 22:09:09250
Antonio Gomes05b9b9762018-09-11 17:10:45251 // Sync relies on HTTP errors being detectable (and distinct from
252 // net/connection errors).
253 url_loader->SetAllowHttpErrorResults(true);
254
Antonio Gomesbf4f2992018-08-25 03:35:07255 url_loader->SetOnUploadProgressCallback(base::BindRepeating(
256 &HttpBridge::OnURLLoadUploadProgress, base::Unretained(this)));
257 url_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
258 url_loader_factory_.get(),
259 base::BindOnce(&HttpBridge::OnURLLoadComplete, base::Unretained(this)));
Max Boguefef332d2016-07-28 22:09:09260}
261
262int HttpBridge::GetResponseContentLength() const {
263 DCHECK(thread_checker_.CalledOnValidThread());
264 base::AutoLock lock(fetch_state_lock_);
265 DCHECK(fetch_state_.request_completed);
266 return fetch_state_.response_content.size();
267}
268
269const char* HttpBridge::GetResponseContent() const {
270 DCHECK(thread_checker_.CalledOnValidThread());
271 base::AutoLock lock(fetch_state_lock_);
272 DCHECK(fetch_state_.request_completed);
273 return fetch_state_.response_content.data();
274}
275
276const std::string HttpBridge::GetResponseHeaderValue(
277 const std::string& name) const {
278 DCHECK(thread_checker_.CalledOnValidThread());
279 base::AutoLock lock(fetch_state_lock_);
280 DCHECK(fetch_state_.request_completed);
281
282 std::string value;
skym8d8162f2016-10-17 22:12:44283 fetch_state_.response_headers->EnumerateHeader(nullptr, name, &value);
Max Boguefef332d2016-07-28 22:09:09284 return value;
285}
286
287void HttpBridge::Abort() {
288 base::AutoLock lock(fetch_state_lock_);
289
Dominic Farolinobc280d22019-12-05 05:49:24290 // Release |pending_url_loader_factory_| as soon as possible so that
Antonio Gomesbf4f2992018-08-25 03:35:07291 // no URLLoaderFactory instances proceed on the network task runner.
Dominic Farolinobc280d22019-12-05 05:49:24292 pending_url_loader_factory_.reset();
Max Boguefef332d2016-07-28 22:09:09293
294 DCHECK(!fetch_state_.aborted);
295 if (fetch_state_.aborted || fetch_state_.request_completed)
296 return;
297
298 fetch_state_.aborted = true;
299 if (!network_task_runner_->PostTask(
300 FROM_HERE,
Antonio Gomesbf4f2992018-08-25 03:35:07301 base::BindOnce(&HttpBridge::DestroyURLLoaderOnIOThread, this,
302 std::move(fetch_state_.url_loader),
303 std::move(fetch_state_.http_request_timeout_timer)))) {
Max Boguefef332d2016-07-28 22:09:09304 // Madness ensues.
Antonio Gomesbf4f2992018-08-25 03:35:07305 NOTREACHED() << "Could not post task to delete URLLoader";
Max Boguefef332d2016-07-28 22:09:09306 }
307
Mikel Astiz3a64405f2018-11-22 15:50:31308 fetch_state_.net_error_code = net::ERR_ABORTED;
Max Boguefef332d2016-07-28 22:09:09309 http_post_completed_.Signal();
310}
311
Antonio Gomesbf4f2992018-08-25 03:35:07312void HttpBridge::DestroyURLLoaderOnIOThread(
313 std::unique_ptr<network::SimpleURLLoader> loader,
Patrick Monettead70b872021-04-16 18:49:26314 std::unique_ptr<base::DelayTimer> loader_timer) {
Antonio Gomesbf4f2992018-08-25 03:35:07315 DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
Zinovy Nis701103b2018-05-10 22:59:38316
Antonio Gomesbf4f2992018-08-25 03:35:07317 // Both |loader_timer| and |loader| go out of scope.
318 url_loader_factory_ = nullptr;
Max Boguefef332d2016-07-28 22:09:09319}
320
Antonio Gomesbf4f2992018-08-25 03:35:07321void HttpBridge::OnURLLoadComplete(std::unique_ptr<std::string> response_body) {
322 DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
Max Boguefef332d2016-07-28 22:09:09323
324 base::AutoLock lock(fetch_state_lock_);
325
Antonio Gomesbf4f2992018-08-25 03:35:07326 network::SimpleURLLoader* url_loader = fetch_state_.url_loader.get();
Maks Orloviche95c25662018-08-30 17:56:04327 // If the fetch completes in the window between Abort() and
328 // DestroyURLLoaderOnIOThread() this will still run. Abort() has already
329 // reported the result, so no extra work is needed.
330 if (fetch_state_.aborted)
331 return;
Antonio Gomesbf4f2992018-08-25 03:35:07332
Mikel Astiz1de5fe92018-11-23 11:43:42333 int http_status_code = -1;
Antonio Gomesbf4f2992018-08-25 03:35:07334 if (url_loader->ResponseInfo() && url_loader->ResponseInfo()->headers) {
Mikel Astiz1de5fe92018-11-23 11:43:42335 http_status_code = url_loader->ResponseInfo()->headers->response_code();
Antonio Gomesbf4f2992018-08-25 03:35:07336 fetch_state_.response_headers = url_loader->ResponseInfo()->headers;
337 }
338
Angelika Kurtzd266ea62019-04-10 09:22:18339 OnURLLoadCompleteInternal(http_status_code, url_loader->NetError(),
340 url_loader->GetFinalURL(),
341 std::move(response_body));
Antonio Gomesbf4f2992018-08-25 03:35:07342}
343
344void HttpBridge::OnURLLoadCompleteInternal(
Mikel Astiz1de5fe92018-11-23 11:43:42345 int http_status_code,
Mikel Astiz3a64405f2018-11-22 15:50:31346 int net_error_code,
Antonio Gomesbf4f2992018-08-25 03:35:07347 const GURL& final_url,
348 std::unique_ptr<std::string> response_body) {
349 DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
350
Max Boguefef332d2016-07-28 22:09:09351 // Stop the request timer now that the request completed.
Patrick Monettead70b872021-04-16 18:49:26352 fetch_state_.http_request_timeout_timer = nullptr;
Max Boguefef332d2016-07-28 22:09:09353
Antonio Gomesbf4f2992018-08-25 03:35:07354 // TODO(crbug.com/844968): Relax this if-check to become a DCHECK?
Max Boguefef332d2016-07-28 22:09:09355 if (fetch_state_.aborted)
356 return;
357
358 fetch_state_.end_time = base::Time::Now();
359 fetch_state_.request_completed = true;
Mikel Astiz3a64405f2018-11-22 15:50:31360 fetch_state_.request_succeeded =
Mikel Astiz1de5fe92018-11-23 11:43:42361 net_error_code == net::OK && http_status_code != -1;
362 fetch_state_.http_status_code = http_status_code;
Mikel Astiz3a64405f2018-11-22 15:50:31363 fetch_state_.net_error_code = net_error_code;
Max Boguefef332d2016-07-28 22:09:09364
365 if (fetch_state_.request_succeeded)
366 LogTimeout(false);
Matt Menke627234692019-12-18 13:36:10367 base::UmaHistogramSparse("Sync.URLFetchResponse",
368 fetch_state_.request_succeeded
369 ? fetch_state_.http_status_code
370 : fetch_state_.net_error_code);
Max Boguefef332d2016-07-28 22:09:09371
372 // Use a real (non-debug) log to facilitate troubleshooting in the wild.
Antonio Gomesbf4f2992018-08-25 03:35:07373 VLOG(2) << "HttpBridge::OnURLFetchComplete for: " << final_url.spec();
Max Boguefef332d2016-07-28 22:09:09374 VLOG(1) << "HttpBridge received response code: "
Mikel Astiz1de5fe92018-11-23 11:43:42375 << fetch_state_.http_status_code;
Max Boguefef332d2016-07-28 22:09:09376
Antonio Gomesbf4f2992018-08-25 03:35:07377 if (response_body)
378 fetch_state_.response_content = std::move(*response_body);
379
Antonio Gomesbf4f2992018-08-25 03:35:07380 fetch_state_.url_loader.reset();
381 url_loader_factory_ = nullptr;
Max Boguefef332d2016-07-28 22:09:09382
383 // Wake the blocked syncer thread in MakeSynchronousPost.
384 // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted!
385 http_post_completed_.Signal();
386}
387
Antonio Gomesbf4f2992018-08-25 03:35:07388void HttpBridge::OnURLLoadUploadProgress(uint64_t position, uint64_t total) {
389 DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
Max Boguefef332d2016-07-28 22:09:09390 // Reset the delay when forward progress is made.
391 base::AutoLock lock(fetch_state_lock_);
Zinovy Nis701103b2018-05-10 22:59:38392 if (fetch_state_.http_request_timeout_timer)
Max Boguefef332d2016-07-28 22:09:09393 fetch_state_.http_request_timeout_timer->Reset();
394}
395
Antonio Gomesbf4f2992018-08-25 03:35:07396void HttpBridge::OnURLLoadTimedOut() {
397 DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
Max Boguefef332d2016-07-28 22:09:09398
399 base::AutoLock lock(fetch_state_lock_);
Antonio Gomesbf4f2992018-08-25 03:35:07400 if (!fetch_state_.url_loader)
Max Boguefef332d2016-07-28 22:09:09401 return;
402
403 LogTimeout(true);
404 DVLOG(1) << "Sync url fetch timed out. Canceling.";
405
406 fetch_state_.end_time = base::Time::Now();
407 fetch_state_.request_completed = true;
408 fetch_state_.request_succeeded = false;
Mikel Astiz1de5fe92018-11-23 11:43:42409 fetch_state_.http_status_code = -1;
Mikel Astiz3a64405f2018-11-22 15:50:31410 fetch_state_.net_error_code = net::ERR_TIMED_OUT;
Max Boguefef332d2016-07-28 22:09:09411
412 // This method is called by the timer, not the url fetcher implementation,
413 // so it's safe to delete the fetcher here.
Antonio Gomesbf4f2992018-08-25 03:35:07414 fetch_state_.url_loader.reset();
415 url_loader_factory_ = nullptr;
Max Boguefef332d2016-07-28 22:09:09416
417 // Timer is smart enough to handle being deleted as part of the invoked task.
Patrick Monettead70b872021-04-16 18:49:26418 fetch_state_.http_request_timeout_timer = nullptr;
Max Boguefef332d2016-07-28 22:09:09419
420 // Wake the blocked syncer thread in MakeSynchronousPost.
421 // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted!
422 http_post_completed_.Signal();
423}
424
Antonio Gomesbf4f2992018-08-25 03:35:07425void HttpBridge::SetIOCapableTaskRunnerForTest(
426 scoped_refptr<base::SequencedTaskRunner> task_runner) {
427 g_io_capable_task_runner_for_tests.Get() = task_runner;
Max Boguefef332d2016-07-28 22:09:09428}
429
Max Boguefef332d2016-07-28 22:09:09430} // namespace syncer