blob: 5833ba3ebf363f28b6812c3c0d85ecff0d3d4ff2 [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"
[email protected]78efe2e92014-08-08 15:53:2214#include "base/callback.h"
[email protected]57999812013-02-24 05:40:5215#include "base/files/file_path.h"
thestig819adcc82014-09-10 22:24:5316#include "base/files/file_util.h"
[email protected]e8f96ff2011-08-03 05:07:3317#include "base/logging.h"
sorin5cb1f5492014-09-23 04:07:4418#include "base/macros.h"
sorin85953dc2016-03-10 00:32:4819#include "base/metrics/histogram_macros.h"
waffles77255cc2016-08-02 17:25:1220#include "base/strings/utf_string_conversions.h"
[email protected]ed6fb982014-07-23 16:56:5221#include "base/threading/thread_checker.h"
gab7966d312016-05-11 20:35:0122#include "base/threading/thread_task_runner_handle.h"
sorin85953dc2016-03-10 00:32:4823#include "base/time/time.h"
[email protected]41a17c52013-06-28 00:27:5324#include "base/timer/timer.h"
sorin7c717622015-05-26 19:59:0925#include "components/component_updater/component_updater_service_internal.h"
sorin52ac0882015-01-24 01:15:0026#include "components/update_client/configurator.h"
sorin52ac0882015-01-24 01:15:0027#include "components/update_client/crx_update_item.h"
sorin52ac0882015-01-24 01:15:0028#include "components/update_client/update_client.h"
sorin7b8650522016-11-02 18:23:4129#include "components/update_client/update_client_errors.h"
sorin52ac0882015-01-24 01:15:0030#include "components/update_client/utils.h"
[email protected]761fa4702013-07-02 15:25:1531#include "url/gurl.h"
[email protected]e8f96ff2011-08-03 05:07:3332
sorin7c717622015-05-26 19:59:0933using CrxInstaller = update_client::CrxInstaller;
34using UpdateClient = update_client::UpdateClient;
sorin52ac0882015-01-24 01:15:0035
sorin85953dc2016-03-10 00:32:4836namespace {
37
38enum UpdateType {
39 UPDATE_TYPE_MANUAL = 0,
40 UPDATE_TYPE_AUTOMATIC,
41 UPDATE_TYPE_COUNT,
42};
43
44} // namespace
45
[email protected]055981f2014-01-17 20:22:3246namespace component_updater {
[email protected]3a0092d2013-12-18 03:04:3547
Joshua Pawlicki0499ac82017-08-17 18:29:0748ComponentInfo::ComponentInfo(const std::string& id,
49 const std::string& fingerprint,
50 const base::string16& name,
wafflese7759f72016-10-10 23:41:2551 const base::Version& version)
Joshua Pawlicki0499ac82017-08-17 18:29:0752 : id(id), fingerprint(fingerprint), name(name), version(version) {}
53ComponentInfo::ComponentInfo(const ComponentInfo& other) = default;
54ComponentInfo::ComponentInfo(ComponentInfo&& other) = default;
waffles77255cc2016-08-02 17:25:1255ComponentInfo::~ComponentInfo() {}
56
Sorin Jianu49126332018-02-13 17:07:4257CrxUpdateService::CrxUpdateService(scoped_refptr<Configurator> config,
Tibor Goldschwendt5f173cb2018-06-21 22:50:4058 std::unique_ptr<UpdateScheduler> scheduler,
Sorin Jianu49126332018-02-13 17:07:4259 scoped_refptr<UpdateClient> update_client)
Tibor Goldschwendt5f173cb2018-06-21 22:50:4060 : config_(config),
61 scheduler_(std::move(scheduler)),
62 update_client_(update_client) {
sorin7c717622015-05-26 19:59:0963 AddObserver(this);
[email protected]1ea21ad2013-09-02 04:20:3964}
[email protected]e8f96ff2011-08-03 05:07:3365
66CrxUpdateService::~CrxUpdateService() {
sorin7c717622015-05-26 19:59:0967 DCHECK(thread_checker_.CalledOnValidThread());
68
Sorin Jianua8ef73d2017-11-02 16:55:1769 for (auto& item : ready_callbacks_) {
70 std::move(item.second).Run();
sorin7c717622015-05-26 19:59:0971 }
72
73 RemoveObserver(this);
74
[email protected]e8f96ff2011-08-03 05:07:3375 Stop();
[email protected]1ea21ad2013-09-02 04:20:3976}
[email protected]e8f96ff2011-08-03 05:07:3377
[email protected]d3268fe2014-04-25 02:14:2378void CrxUpdateService::AddObserver(Observer* observer) {
[email protected]ed6fb982014-07-23 16:56:5279 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:0980 update_client_->AddObserver(observer);
[email protected]d3268fe2014-04-25 02:14:2381}
82
83void CrxUpdateService::RemoveObserver(Observer* observer) {
[email protected]ed6fb982014-07-23 16:56:5284 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:0985 update_client_->RemoveObserver(observer);
[email protected]d3268fe2014-04-25 02:14:2386}
87
sorin7c717622015-05-26 19:59:0988void CrxUpdateService::Start() {
89 DCHECK(thread_checker_.CalledOnValidThread());
90 VLOG(1) << "CrxUpdateService starting up. "
91 << "First update attempt will take place in "
92 << config_->InitialDelay() << " seconds. "
93 << "Next update attempt will take place in "
94 << config_->NextCheckDelay() << " seconds. ";
[email protected]e8f96ff2011-08-03 05:07:3395
Tibor Goldschwendt5f173cb2018-06-21 22:50:4096 scheduler_->Schedule(
sorin7c717622015-05-26 19:59:0997 base::TimeDelta::FromSeconds(config_->InitialDelay()),
98 base::TimeDelta::FromSeconds(config_->NextCheckDelay()),
99 base::Bind(base::IgnoreResult(&CrxUpdateService::CheckForUpdates),
Tibor Goldschwendt5f173cb2018-06-21 22:50:40100 base::Unretained(this)),
101 // TODO: Stop component update if requested.
102 base::DoNothing());
[email protected]e8f96ff2011-08-03 05:07:33103}
104
sorin7c717622015-05-26 19:59:09105// Stops the update loop. In flight operations will be completed.
106void CrxUpdateService::Stop() {
107 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]fb53e652014-04-30 11:27:19108 VLOG(1) << "CrxUpdateService stopping";
Tibor Goldschwendt5f173cb2018-06-21 22:50:40109 scheduler_->Stop();
sorinecaad3e2015-11-13 19:15:52110 update_client_->Stop();
[email protected]e8f96ff2011-08-03 05:07:33111}
112
113// Adds a component to be checked for upgrades. If the component exists it
sorin7c717622015-05-26 19:59:09114// it will be replaced.
115bool CrxUpdateService::RegisterComponent(const CrxComponent& component) {
[email protected]ed6fb982014-07-23 16:56:52116 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]d0c8b8b42014-05-06 05:11:45117 if (component.pk_hash.empty() || !component.version.IsValid() ||
sorin7c717622015-05-26 19:59:09118 !component.installer) {
119 return false;
[email protected]e8f96ff2011-08-03 05:07:33120 }
121
sorin7c717622015-05-26 19:59:09122 // Update the registration data if the component has been registered before.
123 const std::string id(GetCrxComponentID(component));
124 auto it = components_.find(id);
125 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
sorin7c717622015-05-26 19:59:09130 components_.insert(std::make_pair(id, component));
131 components_order_.push_back(id);
waffles77255cc2016-08-02 17:25:12132 for (const auto& mime_type : component.handled_mime_types)
133 component_ids_by_mime_type_[mime_type] = 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;
138 item.id = id;
139 item.component = component;
140 const auto inserted = component_states_.insert(std::make_pair(id, item));
141 DCHECK(inserted.second);
142
143 // Start the timer if this is the first component registered. The first timer
144 // event occurs after an interval defined by the component update
145 // configurator. The subsequent timer events are repeated with a period
146 // defined by the same configurator.
147 if (components_.size() == 1)
148 Start();
149
150 return true;
[email protected]e8f96ff2011-08-03 05:07:33151}
152
sorin7c717622015-05-26 19:59:09153bool CrxUpdateService::UnregisterComponent(const std::string& id) {
154 DCHECK(thread_checker_.CalledOnValidThread());
155 auto it = components_.find(id);
156 if (it == components_.end())
157 return false;
bauerb1f6657e72015-02-09 00:00:27158
sorin7c717622015-05-26 19:59:09159 DCHECK_EQ(id, it->first);
bauerb1f6657e72015-02-09 00:00:27160
sorin7c717622015-05-26 19:59:09161 // Delay the uninstall of the component if the component is being updated.
162 if (update_client_->IsUpdating(id)) {
163 components_pending_unregistration_.push_back(id);
164 return true;
165 }
166
167 return DoUnregisterComponent(it->second);
168}
169
170bool CrxUpdateService::DoUnregisterComponent(const CrxComponent& component) {
171 DCHECK(thread_checker_.CalledOnValidThread());
172
173 const auto id = GetCrxComponentID(component);
174 DCHECK(ready_callbacks_.find(id) == ready_callbacks_.end());
175
176 const bool result = component.installer->Uninstall();
177
178 const auto pos =
179 std::find(components_order_.begin(), components_order_.end(), id);
180 if (pos != components_order_.end())
181 components_order_.erase(pos);
182
183 components_.erase(id);
184 component_states_.erase(id);
185
186 return result;
bauerb1f6657e72015-02-09 00:00:27187}
188
[email protected]68bf09e2014-06-03 00:10:56189std::vector<std::string> CrxUpdateService::GetComponentIDs() const {
[email protected]ed6fb982014-07-23 16:56:52190 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:09191 std::vector<std::string> ids;
192 for (const auto& it : components_)
193 ids.push_back(it.first);
194 return ids;
[email protected]68bf09e2014-06-03 00:10:56195}
196
waffles77255cc2016-08-02 17:25:12197std::unique_ptr<ComponentInfo> CrxUpdateService::GetComponentForMimeType(
198 const std::string& mime_type) const {
199 DCHECK(thread_checker_.CalledOnValidThread());
200 const auto it = component_ids_by_mime_type_.find(mime_type);
201 if (it == component_ids_by_mime_type_.end())
202 return nullptr;
vmpstr6d9996c82017-02-23 00:43:25203 auto* const component = GetComponent(it->second);
waffles77255cc2016-08-02 17:25:12204 if (!component)
205 return nullptr;
Gyuyoung Kim6afb5082018-01-19 13:35:57206 return std::make_unique<ComponentInfo>(
Joshua Pawlicki0499ac82017-08-17 18:29:07207 GetCrxComponentID(*component), component->fingerprint,
208 base::UTF8ToUTF16(component->name), component->version);
209}
210
211std::vector<ComponentInfo> CrxUpdateService::GetComponents() const {
212 DCHECK(thread_checker_.CalledOnValidThread());
213 std::vector<ComponentInfo> result;
214 for (const auto& it : components_) {
215 result.push_back(ComponentInfo(it.first, it.second.fingerprint,
216 base::UTF8ToUTF16(it.second.name),
217 it.second.version));
218 }
219 return result;
waffles77255cc2016-08-02 17:25:12220}
221
[email protected]78efe2e92014-08-08 15:53:22222OnDemandUpdater& CrxUpdateService::GetOnDemandUpdater() {
sorin7c717622015-05-26 19:59:09223 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]78efe2e92014-08-08 15:53:22224 return *this;
225}
226
sorin7c717622015-05-26 19:59:09227const CrxComponent* CrxUpdateService::GetComponent(
228 const std::string& id) const {
229 DCHECK(thread_checker_.CalledOnValidThread());
230 const auto it(components_.find(id));
Ivan Kotenkov75b1c3a2017-10-24 14:47:24231 return it != components_.end() ? &(it->second) : nullptr;
sorin7c717622015-05-26 19:59:09232}
233
234const CrxUpdateItem* CrxUpdateService::GetComponentState(
235 const std::string& id) const {
236 DCHECK(thread_checker_.CalledOnValidThread());
237 const auto it(component_states_.find(id));
Ivan Kotenkov75b1c3a2017-10-24 14:47:24238 return it != component_states_.end() ? &it->second : nullptr;
sorin7c717622015-05-26 19:59:09239}
240
241void CrxUpdateService::MaybeThrottle(const std::string& id,
Sorin Jianua8ef73d2017-11-02 16:55:17242 base::OnceClosure callback) {
[email protected]78efe2e92014-08-08 15:53:22243 DCHECK(thread_checker_.CalledOnValidThread());
Sorin Jianua8ef73d2017-11-02 16:55:17244 const auto it = components_.find(id);
sorin7c717622015-05-26 19:59:09245 if (it != components_.end()) {
246 DCHECK_EQ(it->first, id);
247 if (OnDemandUpdateWithCooldown(id)) {
Sorin Jianua8ef73d2017-11-02 16:55:17248 ready_callbacks_.insert(std::make_pair(id, std::move(callback)));
sorin7c717622015-05-26 19:59:09249 return;
250 }
[email protected]78efe2e92014-08-08 15:53:22251 }
sorin7c717622015-05-26 19:59:09252
Sorin Jianua8ef73d2017-11-02 16:55:17253 // Unblock the request if the request can't be throttled.
254 std::move(callback).Run();
sorin7c717622015-05-26 19:59:09255}
256
sorin4c520182016-08-19 17:27:44257void CrxUpdateService::OnDemandUpdate(const std::string& id,
Sorin Jianud20ed8532018-06-28 17:24:31258 Priority priority,
Vladislav Kuzkokov12eca792017-10-20 12:45:38259 Callback callback) {
sorin7c717622015-05-26 19:59:09260 DCHECK(thread_checker_.CalledOnValidThread());
261
sorin4c520182016-08-19 17:27:44262 if (!GetComponent(id)) {
drbasic6d4d9ce2017-02-22 10:33:59263 if (!callback.is_null()) {
264 base::ThreadTaskRunnerHandle::Get()->PostTask(
Vladislav Kuzkokov12eca792017-10-20 12:45:38265 FROM_HERE, base::BindOnce(std::move(callback),
266 update_client::Error::INVALID_ARGUMENT));
drbasic6d4d9ce2017-02-22 10:33:59267 }
sorin4c520182016-08-19 17:27:44268 return;
269 }
sorin7c717622015-05-26 19:59:09270
Sorin Jianud20ed8532018-06-28 17:24:31271 OnDemandUpdateInternal(id, priority, std::move(callback));
sorin7c717622015-05-26 19:59:09272}
273
274bool CrxUpdateService::OnDemandUpdateWithCooldown(const std::string& id) {
275 DCHECK(thread_checker_.CalledOnValidThread());
276
277 DCHECK(GetComponent(id));
278
279 // Check if the request is too soon.
vmpstr2de366b2016-07-20 21:35:48280 const auto* component_state(GetComponentState(id));
Ivan Afanasyevec822ac2017-09-05 14:10:06281 if (component_state && !component_state->last_check.is_null()) {
sorin1827db12016-09-15 20:43:31282 base::TimeDelta delta =
283 base::TimeTicks::Now() - component_state->last_check;
sorin7c717622015-05-26 19:59:09284 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay()))
285 return false;
286 }
287
Sorin Jianud20ed8532018-06-28 17:24:31288 OnDemandUpdateInternal(id, Priority::FOREGROUND, Callback());
sorin4c520182016-08-19 17:27:44289 return true;
sorin7c717622015-05-26 19:59:09290}
291
sorin4c520182016-08-19 17:27:44292void CrxUpdateService::OnDemandUpdateInternal(const std::string& id,
Sorin Jianud20ed8532018-06-28 17:24:31293 Priority priority,
Vladislav Kuzkokov12eca792017-10-20 12:45:38294 Callback callback) {
sorin7c717622015-05-26 19:59:09295 DCHECK(thread_checker_.CalledOnValidThread());
296
sorin85953dc2016-03-10 00:32:48297 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.Calls", UPDATE_TYPE_MANUAL,
298 UPDATE_TYPE_COUNT);
Sorin Jianud20ed8532018-06-28 17:24:31299
300 auto crx_data_callback = base::BindOnce(&CrxUpdateService::GetCrxComponents,
301 base::Unretained(this));
302 auto update_complete_callback = base::BindOnce(
303 &CrxUpdateService::OnUpdateComplete, base::Unretained(this),
304 std::move(callback), base::TimeTicks::Now());
305
306 if (priority == Priority::FOREGROUND)
307 update_client_->Install(id, std::move(crx_data_callback),
308 std::move(update_complete_callback));
309 else if (priority == Priority::BACKGROUND)
310 update_client_->Update({id}, std::move(crx_data_callback), false,
311 std::move(update_complete_callback));
312 else
313 NOTREACHED();
sorin7c717622015-05-26 19:59:09314}
315
Tibor Goldschwendt5f173cb2018-06-21 22:50:40316bool CrxUpdateService::CheckForUpdates(
317 UpdateScheduler::OnFinishedCallback on_finished) {
sorin7c717622015-05-26 19:59:09318 DCHECK(thread_checker_.CalledOnValidThread());
sorin85953dc2016-03-10 00:32:48319
Xiaochu Liu6a62ebc9b2018-06-14 19:49:37320 // TODO(xiaochu): remove this log after https://crbug.com/851151 is fixed.
321 VLOG(1) << "CheckForUpdates: automatic updatecheck for components.";
322
sorin85953dc2016-03-10 00:32:48323 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.Calls", UPDATE_TYPE_AUTOMATIC,
324 UPDATE_TYPE_COUNT);
325
sorinfccbf2d2016-04-04 20:34:34326 std::vector<std::string> secure_ids; // Requires HTTPS for update checks.
327 std::vector<std::string> unsecure_ids; // Can fallback to HTTP.
sorin7c717622015-05-26 19:59:09328 for (const auto id : components_order_) {
329 DCHECK(components_.find(id) != components_.end());
sorinfccbf2d2016-04-04 20:34:34330
vmpstr2de366b2016-07-20 21:35:48331 auto* component(GetComponent(id));
sorinfccbf2d2016-04-04 20:34:34332 if (!component || component->requires_network_encryption)
333 secure_ids.push_back(id);
334 else
335 unsecure_ids.push_back(id);
sorin7c717622015-05-26 19:59:09336 }
337
Tibor Goldschwendt5f173cb2018-06-21 22:50:40338 if (unsecure_ids.empty() && secure_ids.empty()) {
339 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
340 std::move(on_finished));
341 return true;
342 }
343
344 Callback on_finished_callback = base::BindOnce(
345 [](UpdateScheduler::OnFinishedCallback on_finished,
346 update_client::Error error) { std::move(on_finished).Run(); },
347 std::move(on_finished));
348
sorinfccbf2d2016-04-04 20:34:34349 if (!unsecure_ids.empty()) {
Tibor Goldschwendt5f173cb2018-06-21 22:50:40350 update_client_->Update(
351 unsecure_ids,
352 base::BindOnce(&CrxUpdateService::GetCrxComponents,
353 base::Unretained(this)),
354 false,
355 base::BindOnce(
356 &CrxUpdateService::OnUpdateComplete, base::Unretained(this),
357 secure_ids.empty() ? std::move(on_finished_callback) : Callback(),
358 base::TimeTicks::Now()));
sorinfccbf2d2016-04-04 20:34:34359 }
360
361 if (!secure_ids.empty()) {
Tibor Goldschwendt5f173cb2018-06-21 22:50:40362 update_client_->Update(
363 secure_ids,
364 base::BindOnce(&CrxUpdateService::GetCrxComponents,
365 base::Unretained(this)),
366 false,
367 base::BindOnce(&CrxUpdateService::OnUpdateComplete,
368 base::Unretained(this), std::move(on_finished_callback),
369 base::TimeTicks::Now()));
sorinfccbf2d2016-04-04 20:34:34370 }
sorin7c717622015-05-26 19:59:09371
372 return true;
[email protected]78efe2e92014-08-08 15:53:22373}
374
sorin7c717622015-05-26 19:59:09375bool CrxUpdateService::GetComponentDetails(const std::string& id,
[email protected]f392e372014-06-12 07:25:57376 CrxUpdateItem* item) const {
[email protected]ed6fb982014-07-23 16:56:52377 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:09378
379 // First, if this component is currently being updated, return its state from
380 // the update client.
381 if (update_client_->GetCrxUpdateState(id, item))
382 return true;
383
384 // Otherwise, return the last seen state of the component, if such a
385 // state exists.
386 const auto component_states_it = component_states_.find(id);
387 if (component_states_it != component_states_.end()) {
388 *item = component_states_it->second;
389 return true;
390 }
391
392 return false;
[email protected]2e919ddd2013-08-21 05:05:17393}
394
Sorin Jianu7c22795b2018-04-26 22:16:52395std::vector<std::unique_ptr<CrxComponent>> CrxUpdateService::GetCrxComponents(
396 const std::vector<std::string>& ids) {
sorin7c717622015-05-26 19:59:09397 DCHECK(thread_checker_.CalledOnValidThread());
Sorin Jianu7c22795b2018-04-26 22:16:52398 std::vector<std::unique_ptr<CrxComponent>> components;
sorin7c717622015-05-26 19:59:09399 for (const auto& id : ids) {
Sorin Jianu7c22795b2018-04-26 22:16:52400 const auto* registered_component = GetComponent(id);
401 components.push_back(registered_component ? std::make_unique<CrxComponent>(
402 *registered_component)
403 : nullptr);
sorin7c717622015-05-26 19:59:09404 }
Sorin Jianu7c22795b2018-04-26 22:16:52405 return components;
[email protected]ed6fb982014-07-23 16:56:52406}
407
sorin842703b2016-11-02 23:59:23408void CrxUpdateService::OnUpdateComplete(Callback callback,
sorin4c520182016-08-19 17:27:44409 const base::TimeTicks& start_time,
sorin7b8650522016-11-02 18:23:41410 update_client::Error error) {
sorin7c717622015-05-26 19:59:09411 DCHECK(thread_checker_.CalledOnValidThread());
sorin7b8650522016-11-02 18:23:41412 VLOG(1) << "Update completed with error " << static_cast<int>(error);
sorin7c717622015-05-26 19:59:09413
sorin7b8650522016-11-02 18:23:41414 UMA_HISTOGRAM_BOOLEAN("ComponentUpdater.UpdateCompleteResult",
415 error != update_client::Error::NONE);
Joshua Pawlickida716cb2018-06-27 15:32:04416 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.UpdateCompleteError", error,
417 update_client::Error::MAX_VALUE);
sorin85953dc2016-03-10 00:32:48418 UMA_HISTOGRAM_LONG_TIMES_100("ComponentUpdater.UpdateCompleteTime",
419 base::TimeTicks::Now() - start_time);
420
sorin7c717622015-05-26 19:59:09421 for (const auto id : components_pending_unregistration_) {
422 if (!update_client_->IsUpdating(id)) {
vmpstr2de366b2016-07-20 21:35:48423 const auto* component = GetComponent(id);
sorin7c717622015-05-26 19:59:09424 if (component)
425 DoUnregisterComponent(*component);
426 }
427 }
sorin4c520182016-08-19 17:27:44428
429 if (!callback.is_null()) {
Sorin Jianuebd652462017-07-23 02:00:58430 base::ThreadTaskRunnerHandle::Get()->PostTask(
Vladislav Kuzkokov12eca792017-10-20 12:45:38431 FROM_HERE, base::BindOnce(std::move(callback), error));
sorin4c520182016-08-19 17:27:44432 }
sorin7c717622015-05-26 19:59:09433}
434
435void CrxUpdateService::OnEvent(Events event, const std::string& id) {
[email protected]ed6fb982014-07-23 16:56:52436 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]93e8e2c2014-01-04 12:29:23437
sorin7c717622015-05-26 19:59:09438 // Unblock all throttles for the component.
439 if (event == Observer::Events::COMPONENT_UPDATED ||
Sorin Jianucbb10e12018-01-23 18:01:44440 event == Observer::Events::COMPONENT_NOT_UPDATED ||
441 event == Observer::Events::COMPONENT_UPDATE_ERROR) {
sorin7c717622015-05-26 19:59:09442 auto callbacks = ready_callbacks_.equal_range(id);
443 for (auto it = callbacks.first; it != callbacks.second; ++it) {
Sorin Jianua8ef73d2017-11-02 16:55:17444 std::move(it->second).Run();
sorin7c717622015-05-26 19:59:09445 }
446 ready_callbacks_.erase(id);
447 }
448
449 CrxUpdateItem update_item;
450 if (!update_client_->GetCrxUpdateState(id, &update_item))
[email protected]e8f96ff2011-08-03 05:07:33451 return;
[email protected]93e8e2c2014-01-04 12:29:23452
sorin7c717622015-05-26 19:59:09453 // Update the state of the item.
454 auto it = component_states_.find(id);
455 DCHECK(it != component_states_.end());
456 it->second = update_item;
bauerb1f6657e72015-02-09 00:00:27457
sorin7c717622015-05-26 19:59:09458 // Update the component registration with the new version.
459 if (event == Observer::Events::COMPONENT_UPDATED) {
vmpstr2de366b2016-07-20 21:35:48460 auto* component(const_cast<CrxComponent*>(GetComponent(id)));
sorin7c717622015-05-26 19:59:09461 if (component) {
462 component->version = update_item.next_version;
463 component->fingerprint = update_item.next_fp;
bauerb1f6657e72015-02-09 00:00:27464 }
465 }
[email protected]68bf09e2014-06-03 00:10:56466}
467
[email protected]00a77fa2013-11-02 04:18:46468///////////////////////////////////////////////////////////////////////////////
469
[email protected]e8f96ff2011-08-03 05:07:33470// The component update factory. Using the component updater as a singleton
471// is the job of the browser process.
sorin7c717622015-05-26 19:59:09472// TODO(sorin): consider making this a singleton.
dchenga0ee5fb82016-04-26 02:46:55473std::unique_ptr<ComponentUpdateService> ComponentUpdateServiceFactory(
Tibor Goldschwendt5f173cb2018-06-21 22:50:40474 scoped_refptr<Configurator> config,
475 std::unique_ptr<UpdateScheduler> scheduler) {
[email protected]e8f96ff2011-08-03 05:07:33476 DCHECK(config);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40477 DCHECK(scheduler);
sorin7c717622015-05-26 19:59:09478 auto update_client = update_client::UpdateClientFactory(config);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40479 return std::make_unique<CrxUpdateService>(config, std::move(scheduler),
480 std::move(update_client));
[email protected]e8f96ff2011-08-03 05:07:33481}
[email protected]2cddef42013-11-22 08:23:22482
[email protected]055981f2014-01-17 20:22:32483} // namespace component_updater