blob: 1577064bd9c6dd2d6809766ea6463bd860a203e3 [file] [log] [blame]
[email protected]de0fdca22014-08-19 05:26:091// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]e8f96ff2011-08-03 05:07:332// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]de0fdca22014-08-19 05:26:095#include "components/component_updater/component_updater_service.h"
[email protected]e8f96ff2011-08-03 05:07:336
7#include <algorithm>
sorin7c717622015-05-26 19:59:098#include <map>
9#include <string>
10#include <utility>
[email protected]e8f96ff2011-08-03 05:07:3311#include <vector>
12
[email protected]44da56e2011-11-21 19:59:1413#include "base/bind.h"
Sebastien Marchand17fa2782019-01-25 19:28:1014#include "base/bind_helpers.h"
[email protected]78efe2e92014-08-08 15:53:2215#include "base/callback.h"
[email protected]57999812013-02-24 05:40:5216#include "base/files/file_path.h"
thestig819adcc82014-09-10 22:24:5317#include "base/files/file_util.h"
[email protected]e8f96ff2011-08-03 05:07:3318#include "base/logging.h"
sorin5cb1f5492014-09-23 04:07:4419#include "base/macros.h"
sorin85953dc2016-03-10 00:32:4820#include "base/metrics/histogram_macros.h"
waffles77255cc2016-08-02 17:25:1221#include "base/strings/utf_string_conversions.h"
[email protected]ed6fb982014-07-23 16:56:5222#include "base/threading/thread_checker.h"
gab7966d312016-05-11 20:35:0123#include "base/threading/thread_task_runner_handle.h"
sorin85953dc2016-03-10 00:32:4824#include "base/time/time.h"
[email protected]41a17c52013-06-28 00:27:5325#include "base/timer/timer.h"
sorin7c717622015-05-26 19:59:0926#include "components/component_updater/component_updater_service_internal.h"
sorin52ac0882015-01-24 01:15:0027#include "components/update_client/configurator.h"
sorin52ac0882015-01-24 01:15:0028#include "components/update_client/crx_update_item.h"
sorin52ac0882015-01-24 01:15:0029#include "components/update_client/update_client.h"
sorin7b8650522016-11-02 18:23:4130#include "components/update_client/update_client_errors.h"
sorin52ac0882015-01-24 01:15:0031#include "components/update_client/utils.h"
[email protected]761fa4702013-07-02 15:25:1532#include "url/gurl.h"
[email protected]e8f96ff2011-08-03 05:07:3333
sorin7c717622015-05-26 19:59:0934using CrxInstaller = update_client::CrxInstaller;
35using UpdateClient = update_client::UpdateClient;
sorin52ac0882015-01-24 01:15:0036
sorin85953dc2016-03-10 00:32:4837namespace {
38
39enum UpdateType {
40 UPDATE_TYPE_MANUAL = 0,
41 UPDATE_TYPE_AUTOMATIC,
42 UPDATE_TYPE_COUNT,
43};
44
45} // namespace
46
[email protected]055981f2014-01-17 20:22:3247namespace component_updater {
[email protected]3a0092d2013-12-18 03:04:3548
Joshua Pawlicki0499ac82017-08-17 18:29:0749ComponentInfo::ComponentInfo(const std::string& id,
50 const std::string& fingerprint,
51 const base::string16& name,
wafflese7759f72016-10-10 23:41:2552 const base::Version& version)
Joshua Pawlicki0499ac82017-08-17 18:29:0753 : id(id), fingerprint(fingerprint), name(name), version(version) {}
54ComponentInfo::ComponentInfo(const ComponentInfo& other) = default;
55ComponentInfo::ComponentInfo(ComponentInfo&& other) = default;
Sorin Jianu30881152020-03-16 14:31:1956ComponentInfo::~ComponentInfo() = default;
waffles77255cc2016-08-02 17:25:1257
Sorin Jianu49126332018-02-13 17:07:4258CrxUpdateService::CrxUpdateService(scoped_refptr<Configurator> config,
Tibor Goldschwendt5f173cb2018-06-21 22:50:4059 std::unique_ptr<UpdateScheduler> scheduler,
Sorin Jianu49126332018-02-13 17:07:4260 scoped_refptr<UpdateClient> update_client)
Tibor Goldschwendt5f173cb2018-06-21 22:50:4061 : config_(config),
62 scheduler_(std::move(scheduler)),
63 update_client_(update_client) {
sorin7c717622015-05-26 19:59:0964 AddObserver(this);
[email protected]1ea21ad2013-09-02 04:20:3965}
[email protected]e8f96ff2011-08-03 05:07:3366
67CrxUpdateService::~CrxUpdateService() {
sorin7c717622015-05-26 19:59:0968 DCHECK(thread_checker_.CalledOnValidThread());
69
Sorin Jianua8ef73d2017-11-02 16:55:1770 for (auto& item : ready_callbacks_) {
71 std::move(item.second).Run();
sorin7c717622015-05-26 19:59:0972 }
73
74 RemoveObserver(this);
75
[email protected]e8f96ff2011-08-03 05:07:3376 Stop();
[email protected]1ea21ad2013-09-02 04:20:3977}
[email protected]e8f96ff2011-08-03 05:07:3378
[email protected]d3268fe2014-04-25 02:14:2379void CrxUpdateService::AddObserver(Observer* observer) {
[email protected]ed6fb982014-07-23 16:56:5280 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:0981 update_client_->AddObserver(observer);
[email protected]d3268fe2014-04-25 02:14:2382}
83
84void CrxUpdateService::RemoveObserver(Observer* observer) {
[email protected]ed6fb982014-07-23 16:56:5285 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:0986 update_client_->RemoveObserver(observer);
[email protected]d3268fe2014-04-25 02:14:2387}
88
sorin7c717622015-05-26 19:59:0989void CrxUpdateService::Start() {
90 DCHECK(thread_checker_.CalledOnValidThread());
91 VLOG(1) << "CrxUpdateService starting up. "
92 << "First update attempt will take place in "
93 << config_->InitialDelay() << " seconds. "
94 << "Next update attempt will take place in "
95 << config_->NextCheckDelay() << " seconds. ";
[email protected]e8f96ff2011-08-03 05:07:3396
Tibor Goldschwendt5f173cb2018-06-21 22:50:4097 scheduler_->Schedule(
sorin7c717622015-05-26 19:59:0998 base::TimeDelta::FromSeconds(config_->InitialDelay()),
99 base::TimeDelta::FromSeconds(config_->NextCheckDelay()),
Ayu Ishii9f343a42020-02-06 18:29:17100 base::BindRepeating(
101 base::IgnoreResult(&CrxUpdateService::CheckForUpdates),
102 base::Unretained(this)),
Tibor Goldschwendt5f173cb2018-06-21 22:50:40103 base::DoNothing());
[email protected]e8f96ff2011-08-03 05:07:33104}
105
sorin7c717622015-05-26 19:59:09106// Stops the update loop. In flight operations will be completed.
107void CrxUpdateService::Stop() {
108 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]fb53e652014-04-30 11:27:19109 VLOG(1) << "CrxUpdateService stopping";
Tibor Goldschwendt5f173cb2018-06-21 22:50:40110 scheduler_->Stop();
sorinecaad3e2015-11-13 19:15:52111 update_client_->Stop();
[email protected]e8f96ff2011-08-03 05:07:33112}
113
114// Adds a component to be checked for upgrades. If the component exists it
sorin7c717622015-05-26 19:59:09115// it will be replaced.
116bool CrxUpdateService::RegisterComponent(const CrxComponent& component) {
[email protected]ed6fb982014-07-23 16:56:52117 DCHECK(thread_checker_.CalledOnValidThread());
Joshua Pawlicki9656e3922019-09-16 16:34:51118 if (component.app_id.empty() || !component.version.IsValid() ||
sorin7c717622015-05-26 19:59:09119 !component.installer) {
120 return false;
[email protected]e8f96ff2011-08-03 05:07:33121 }
122
sorin7c717622015-05-26 19:59:09123 // Update the registration data if the component has been registered before.
Joshua Pawlicki9656e3922019-09-16 16:34:51124 auto it = components_.find(component.app_id);
sorin7c717622015-05-26 19:59:09125 if (it != components_.end()) {
126 it->second = component;
127 return true;
[email protected]10bc0222014-06-11 13:44:38128 }
[email protected]e8f96ff2011-08-03 05:07:33129
Joshua Pawlicki9656e3922019-09-16 16:34:51130 components_.insert(std::make_pair(component.app_id, component));
131 components_order_.push_back(component.app_id);
waffles77255cc2016-08-02 17:25:12132 for (const auto& mime_type : component.handled_mime_types)
Joshua Pawlicki9656e3922019-09-16 16:34:51133 component_ids_by_mime_type_[mime_type] = component.app_id;
sorin7c717622015-05-26 19:59:09134
135 // Create an initial state for this component. The state is mutated in
136 // response to events from the UpdateClient instance.
137 CrxUpdateItem item;
Joshua Pawlicki9656e3922019-09-16 16:34:51138 item.id = component.app_id;
sorin7c717622015-05-26 19:59:09139 item.component = component;
Joshua Pawlicki9656e3922019-09-16 16:34:51140 const auto inserted =
141 component_states_.insert(std::make_pair(component.app_id, item));
sorin7c717622015-05-26 19:59:09142 DCHECK(inserted.second);
143
144 // Start the timer if this is the first component registered. The first timer
145 // event occurs after an interval defined by the component update
146 // configurator. The subsequent timer events are repeated with a period
147 // defined by the same configurator.
148 if (components_.size() == 1)
149 Start();
150
151 return true;
[email protected]e8f96ff2011-08-03 05:07:33152}
153
sorin7c717622015-05-26 19:59:09154bool CrxUpdateService::UnregisterComponent(const std::string& id) {
155 DCHECK(thread_checker_.CalledOnValidThread());
156 auto it = components_.find(id);
157 if (it == components_.end())
158 return false;
bauerb1f6657e72015-02-09 00:00:27159
sorin7c717622015-05-26 19:59:09160 DCHECK_EQ(id, it->first);
bauerb1f6657e72015-02-09 00:00:27161
sorin7c717622015-05-26 19:59:09162 // Delay the uninstall of the component if the component is being updated.
163 if (update_client_->IsUpdating(id)) {
164 components_pending_unregistration_.push_back(id);
165 return true;
166 }
167
168 return DoUnregisterComponent(it->second);
169}
170
171bool CrxUpdateService::DoUnregisterComponent(const CrxComponent& component) {
172 DCHECK(thread_checker_.CalledOnValidThread());
173
174 const auto id = GetCrxComponentID(component);
175 DCHECK(ready_callbacks_.find(id) == ready_callbacks_.end());
176
177 const bool result = component.installer->Uninstall();
178
179 const auto pos =
180 std::find(components_order_.begin(), components_order_.end(), id);
181 if (pos != components_order_.end())
182 components_order_.erase(pos);
183
184 components_.erase(id);
185 component_states_.erase(id);
186
187 return result;
bauerb1f6657e72015-02-09 00:00:27188}
189
[email protected]68bf09e2014-06-03 00:10:56190std::vector<std::string> CrxUpdateService::GetComponentIDs() const {
[email protected]ed6fb982014-07-23 16:56:52191 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:09192 std::vector<std::string> ids;
193 for (const auto& it : components_)
194 ids.push_back(it.first);
195 return ids;
[email protected]68bf09e2014-06-03 00:10:56196}
197
waffles77255cc2016-08-02 17:25:12198std::unique_ptr<ComponentInfo> CrxUpdateService::GetComponentForMimeType(
199 const std::string& mime_type) const {
200 DCHECK(thread_checker_.CalledOnValidThread());
201 const auto it = component_ids_by_mime_type_.find(mime_type);
202 if (it == component_ids_by_mime_type_.end())
203 return nullptr;
Sorin Jianu73900242018-08-17 01:11:53204 const auto component = GetComponent(it->second);
waffles77255cc2016-08-02 17:25:12205 if (!component)
206 return nullptr;
Gyuyoung Kim6afb5082018-01-19 13:35:57207 return std::make_unique<ComponentInfo>(
Joshua Pawlicki0499ac82017-08-17 18:29:07208 GetCrxComponentID(*component), component->fingerprint,
209 base::UTF8ToUTF16(component->name), component->version);
210}
211
212std::vector<ComponentInfo> CrxUpdateService::GetComponents() const {
213 DCHECK(thread_checker_.CalledOnValidThread());
214 std::vector<ComponentInfo> result;
215 for (const auto& it : components_) {
216 result.push_back(ComponentInfo(it.first, it.second.fingerprint,
217 base::UTF8ToUTF16(it.second.name),
218 it.second.version));
219 }
220 return result;
waffles77255cc2016-08-02 17:25:12221}
222
[email protected]78efe2e92014-08-08 15:53:22223OnDemandUpdater& CrxUpdateService::GetOnDemandUpdater() {
sorin7c717622015-05-26 19:59:09224 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]78efe2e92014-08-08 15:53:22225 return *this;
226}
227
Sorin Jianu73900242018-08-17 01:11:53228base::Optional<CrxComponent> CrxUpdateService::GetComponent(
sorin7c717622015-05-26 19:59:09229 const std::string& id) const {
230 DCHECK(thread_checker_.CalledOnValidThread());
Sorin Jianu73900242018-08-17 01:11:53231 const auto it = components_.find(id);
232 if (it != components_.end())
233 return it->second;
234 return base::nullopt;
sorin7c717622015-05-26 19:59:09235}
236
237const CrxUpdateItem* CrxUpdateService::GetComponentState(
238 const std::string& id) const {
239 DCHECK(thread_checker_.CalledOnValidThread());
240 const auto it(component_states_.find(id));
Ivan Kotenkov75b1c3a2017-10-24 14:47:24241 return it != component_states_.end() ? &it->second : nullptr;
sorin7c717622015-05-26 19:59:09242}
243
244void CrxUpdateService::MaybeThrottle(const std::string& id,
Sorin Jianua8ef73d2017-11-02 16:55:17245 base::OnceClosure callback) {
[email protected]78efe2e92014-08-08 15:53:22246 DCHECK(thread_checker_.CalledOnValidThread());
Sorin Jianua8ef73d2017-11-02 16:55:17247 const auto it = components_.find(id);
sorin7c717622015-05-26 19:59:09248 if (it != components_.end()) {
249 DCHECK_EQ(it->first, id);
250 if (OnDemandUpdateWithCooldown(id)) {
Sorin Jianua8ef73d2017-11-02 16:55:17251 ready_callbacks_.insert(std::make_pair(id, std::move(callback)));
sorin7c717622015-05-26 19:59:09252 return;
253 }
[email protected]78efe2e92014-08-08 15:53:22254 }
sorin7c717622015-05-26 19:59:09255
Sorin Jianua8ef73d2017-11-02 16:55:17256 // Unblock the request if the request can't be throttled.
257 std::move(callback).Run();
sorin7c717622015-05-26 19:59:09258}
259
sorin4c520182016-08-19 17:27:44260void CrxUpdateService::OnDemandUpdate(const std::string& id,
Sorin Jianud20ed8532018-06-28 17:24:31261 Priority priority,
Vladislav Kuzkokov12eca792017-10-20 12:45:38262 Callback callback) {
sorin7c717622015-05-26 19:59:09263 DCHECK(thread_checker_.CalledOnValidThread());
264
sorin4c520182016-08-19 17:27:44265 if (!GetComponent(id)) {
drbasic6d4d9ce2017-02-22 10:33:59266 if (!callback.is_null()) {
267 base::ThreadTaskRunnerHandle::Get()->PostTask(
Vladislav Kuzkokov12eca792017-10-20 12:45:38268 FROM_HERE, base::BindOnce(std::move(callback),
269 update_client::Error::INVALID_ARGUMENT));
drbasic6d4d9ce2017-02-22 10:33:59270 }
sorin4c520182016-08-19 17:27:44271 return;
272 }
sorin7c717622015-05-26 19:59:09273
Sorin Jianud20ed8532018-06-28 17:24:31274 OnDemandUpdateInternal(id, priority, std::move(callback));
sorin7c717622015-05-26 19:59:09275}
276
277bool CrxUpdateService::OnDemandUpdateWithCooldown(const std::string& id) {
278 DCHECK(thread_checker_.CalledOnValidThread());
279
280 DCHECK(GetComponent(id));
281
282 // Check if the request is too soon.
vmpstr2de366b2016-07-20 21:35:48283 const auto* component_state(GetComponentState(id));
Ivan Afanasyevec822ac2017-09-05 14:10:06284 if (component_state && !component_state->last_check.is_null()) {
sorin1827db12016-09-15 20:43:31285 base::TimeDelta delta =
286 base::TimeTicks::Now() - component_state->last_check;
sorin7c717622015-05-26 19:59:09287 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay()))
288 return false;
289 }
290
Sorin Jianud20ed8532018-06-28 17:24:31291 OnDemandUpdateInternal(id, Priority::FOREGROUND, Callback());
sorin4c520182016-08-19 17:27:44292 return true;
sorin7c717622015-05-26 19:59:09293}
294
sorin4c520182016-08-19 17:27:44295void CrxUpdateService::OnDemandUpdateInternal(const std::string& id,
Sorin Jianud20ed8532018-06-28 17:24:31296 Priority priority,
Vladislav Kuzkokov12eca792017-10-20 12:45:38297 Callback callback) {
sorin7c717622015-05-26 19:59:09298 DCHECK(thread_checker_.CalledOnValidThread());
299
sorin85953dc2016-03-10 00:32:48300 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.Calls", UPDATE_TYPE_MANUAL,
301 UPDATE_TYPE_COUNT);
Sorin Jianud20ed8532018-06-28 17:24:31302
303 auto crx_data_callback = base::BindOnce(&CrxUpdateService::GetCrxComponents,
304 base::Unretained(this));
305 auto update_complete_callback = base::BindOnce(
306 &CrxUpdateService::OnUpdateComplete, base::Unretained(this),
307 std::move(callback), base::TimeTicks::Now());
308
309 if (priority == Priority::FOREGROUND)
Sorin Jianudfb12a42020-03-10 04:12:03310 update_client_->Install(id, std::move(crx_data_callback), {},
Sorin Jianud20ed8532018-06-28 17:24:31311 std::move(update_complete_callback));
312 else if (priority == Priority::BACKGROUND)
Sorin Jianudfb12a42020-03-10 04:12:03313 update_client_->Update({id}, std::move(crx_data_callback), {}, false,
Sorin Jianud20ed8532018-06-28 17:24:31314 std::move(update_complete_callback));
315 else
316 NOTREACHED();
sorin7c717622015-05-26 19:59:09317}
318
Tibor Goldschwendt5f173cb2018-06-21 22:50:40319bool CrxUpdateService::CheckForUpdates(
320 UpdateScheduler::OnFinishedCallback on_finished) {
sorin7c717622015-05-26 19:59:09321 DCHECK(thread_checker_.CalledOnValidThread());
sorin85953dc2016-03-10 00:32:48322
Xiaochu Liu6a62ebc9b2018-06-14 19:49:37323 // TODO(xiaochu): remove this log after https://crbug.com/851151 is fixed.
324 VLOG(1) << "CheckForUpdates: automatic updatecheck for components.";
325
sorin85953dc2016-03-10 00:32:48326 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.Calls", UPDATE_TYPE_AUTOMATIC,
327 UPDATE_TYPE_COUNT);
328
sorinfccbf2d2016-04-04 20:34:34329 std::vector<std::string> secure_ids; // Requires HTTPS for update checks.
330 std::vector<std::string> unsecure_ids; // Can fallback to HTTP.
Nico Weber6dcde5b2020-02-22 20:49:20331 for (const auto& id : components_order_) {
sorin7c717622015-05-26 19:59:09332 DCHECK(components_.find(id) != components_.end());
sorinfccbf2d2016-04-04 20:34:34333
Sorin Jianu73900242018-08-17 01:11:53334 const auto component = GetComponent(id);
sorinfccbf2d2016-04-04 20:34:34335 if (!component || component->requires_network_encryption)
336 secure_ids.push_back(id);
337 else
338 unsecure_ids.push_back(id);
sorin7c717622015-05-26 19:59:09339 }
340
Tibor Goldschwendt5f173cb2018-06-21 22:50:40341 if (unsecure_ids.empty() && secure_ids.empty()) {
342 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
343 std::move(on_finished));
344 return true;
345 }
346
347 Callback on_finished_callback = base::BindOnce(
348 [](UpdateScheduler::OnFinishedCallback on_finished,
349 update_client::Error error) { std::move(on_finished).Run(); },
350 std::move(on_finished));
351
sorinfccbf2d2016-04-04 20:34:34352 if (!unsecure_ids.empty()) {
Tibor Goldschwendt5f173cb2018-06-21 22:50:40353 update_client_->Update(
354 unsecure_ids,
355 base::BindOnce(&CrxUpdateService::GetCrxComponents,
356 base::Unretained(this)),
Sorin Jianudfb12a42020-03-10 04:12:03357 {}, false,
Tibor Goldschwendt5f173cb2018-06-21 22:50:40358 base::BindOnce(
359 &CrxUpdateService::OnUpdateComplete, base::Unretained(this),
360 secure_ids.empty() ? std::move(on_finished_callback) : Callback(),
361 base::TimeTicks::Now()));
sorinfccbf2d2016-04-04 20:34:34362 }
363
364 if (!secure_ids.empty()) {
Tibor Goldschwendt5f173cb2018-06-21 22:50:40365 update_client_->Update(
366 secure_ids,
367 base::BindOnce(&CrxUpdateService::GetCrxComponents,
368 base::Unretained(this)),
Sorin Jianudfb12a42020-03-10 04:12:03369 {}, false,
Tibor Goldschwendt5f173cb2018-06-21 22:50:40370 base::BindOnce(&CrxUpdateService::OnUpdateComplete,
371 base::Unretained(this), std::move(on_finished_callback),
372 base::TimeTicks::Now()));
sorinfccbf2d2016-04-04 20:34:34373 }
sorin7c717622015-05-26 19:59:09374
375 return true;
[email protected]78efe2e92014-08-08 15:53:22376}
377
sorin7c717622015-05-26 19:59:09378bool CrxUpdateService::GetComponentDetails(const std::string& id,
[email protected]f392e372014-06-12 07:25:57379 CrxUpdateItem* item) const {
[email protected]ed6fb982014-07-23 16:56:52380 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:09381
382 // First, if this component is currently being updated, return its state from
383 // the update client.
384 if (update_client_->GetCrxUpdateState(id, item))
385 return true;
386
387 // Otherwise, return the last seen state of the component, if such a
388 // state exists.
389 const auto component_states_it = component_states_.find(id);
390 if (component_states_it != component_states_.end()) {
391 *item = component_states_it->second;
392 return true;
393 }
394
395 return false;
[email protected]2e919ddd2013-08-21 05:05:17396}
397
Sorin Jianu73900242018-08-17 01:11:53398std::vector<base::Optional<CrxComponent>> CrxUpdateService::GetCrxComponents(
Sorin Jianu7c22795b2018-04-26 22:16:52399 const std::vector<std::string>& ids) {
sorin7c717622015-05-26 19:59:09400 DCHECK(thread_checker_.CalledOnValidThread());
Sorin Jianu73900242018-08-17 01:11:53401 std::vector<base::Optional<CrxComponent>> components;
402 for (const auto& id : ids)
403 components.push_back(GetComponent(id));
Sorin Jianu7c22795b2018-04-26 22:16:52404 return components;
[email protected]ed6fb982014-07-23 16:56:52405}
406
sorin842703b2016-11-02 23:59:23407void CrxUpdateService::OnUpdateComplete(Callback callback,
sorin4c520182016-08-19 17:27:44408 const base::TimeTicks& start_time,
sorin7b8650522016-11-02 18:23:41409 update_client::Error error) {
sorin7c717622015-05-26 19:59:09410 DCHECK(thread_checker_.CalledOnValidThread());
sorin7b8650522016-11-02 18:23:41411 VLOG(1) << "Update completed with error " << static_cast<int>(error);
sorin7c717622015-05-26 19:59:09412
sorin7b8650522016-11-02 18:23:41413 UMA_HISTOGRAM_BOOLEAN("ComponentUpdater.UpdateCompleteResult",
414 error != update_client::Error::NONE);
Joshua Pawlickida716cb2018-06-27 15:32:04415 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.UpdateCompleteError", error,
416 update_client::Error::MAX_VALUE);
sorin85953dc2016-03-10 00:32:48417 UMA_HISTOGRAM_LONG_TIMES_100("ComponentUpdater.UpdateCompleteTime",
418 base::TimeTicks::Now() - start_time);
419
Nico Weber6dcde5b2020-02-22 20:49:20420 for (const auto& id : components_pending_unregistration_) {
sorin7c717622015-05-26 19:59:09421 if (!update_client_->IsUpdating(id)) {
Sorin Jianu73900242018-08-17 01:11:53422 const auto component = GetComponent(id);
sorin7c717622015-05-26 19:59:09423 if (component)
424 DoUnregisterComponent(*component);
425 }
426 }
sorin4c520182016-08-19 17:27:44427
428 if (!callback.is_null()) {
Sorin Jianuebd652462017-07-23 02:00:58429 base::ThreadTaskRunnerHandle::Get()->PostTask(
Vladislav Kuzkokov12eca792017-10-20 12:45:38430 FROM_HERE, base::BindOnce(std::move(callback), error));
sorin4c520182016-08-19 17:27:44431 }
sorin7c717622015-05-26 19:59:09432}
433
434void CrxUpdateService::OnEvent(Events event, const std::string& id) {
[email protected]ed6fb982014-07-23 16:56:52435 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]93e8e2c2014-01-04 12:29:23436
sorin7c717622015-05-26 19:59:09437 // Unblock all throttles for the component.
438 if (event == Observer::Events::COMPONENT_UPDATED ||
Sorin Jianucbb10e12018-01-23 18:01:44439 event == Observer::Events::COMPONENT_NOT_UPDATED ||
440 event == Observer::Events::COMPONENT_UPDATE_ERROR) {
sorin7c717622015-05-26 19:59:09441 auto callbacks = ready_callbacks_.equal_range(id);
442 for (auto it = callbacks.first; it != callbacks.second; ++it) {
Sorin Jianua8ef73d2017-11-02 16:55:17443 std::move(it->second).Run();
sorin7c717622015-05-26 19:59:09444 }
445 ready_callbacks_.erase(id);
446 }
447
448 CrxUpdateItem update_item;
449 if (!update_client_->GetCrxUpdateState(id, &update_item))
[email protected]e8f96ff2011-08-03 05:07:33450 return;
[email protected]93e8e2c2014-01-04 12:29:23451
sorin7c717622015-05-26 19:59:09452 // Update the state of the item.
Sorin Jianu73900242018-08-17 01:11:53453 const auto it = component_states_.find(id);
454 if (it != component_states_.end())
455 it->second = update_item;
bauerb1f6657e72015-02-09 00:00:27456
sorin7c717622015-05-26 19:59:09457 // Update the component registration with the new version.
458 if (event == Observer::Events::COMPONENT_UPDATED) {
Sorin Jianu73900242018-08-17 01:11:53459 const auto it = components_.find(id);
460 if (it != components_.end()) {
461 it->second.version = update_item.next_version;
462 it->second.fingerprint = update_item.next_fp;
bauerb1f6657e72015-02-09 00:00:27463 }
464 }
[email protected]68bf09e2014-06-03 00:10:56465}
466
[email protected]00a77fa2013-11-02 04:18:46467///////////////////////////////////////////////////////////////////////////////
468
[email protected]e8f96ff2011-08-03 05:07:33469// The component update factory. Using the component updater as a singleton
470// is the job of the browser process.
sorin7c717622015-05-26 19:59:09471// TODO(sorin): consider making this a singleton.
dchenga0ee5fb82016-04-26 02:46:55472std::unique_ptr<ComponentUpdateService> ComponentUpdateServiceFactory(
Tibor Goldschwendt5f173cb2018-06-21 22:50:40473 scoped_refptr<Configurator> config,
474 std::unique_ptr<UpdateScheduler> scheduler) {
[email protected]e8f96ff2011-08-03 05:07:33475 DCHECK(config);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40476 DCHECK(scheduler);
sorin7c717622015-05-26 19:59:09477 auto update_client = update_client::UpdateClientFactory(config);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40478 return std::make_unique<CrxUpdateService>(config, std::move(scheduler),
479 std::move(update_client));
[email protected]e8f96ff2011-08-03 05:07:33480}
[email protected]2cddef42013-11-22 08:23:22481
[email protected]055981f2014-01-17 20:22:32482} // namespace component_updater