blob: b684882da8c1232258c49a3a74fbc3c79dbc1412 [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"
26#include "components/component_updater/timer.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;
waffles77255cc2016-08-02 17:25:1256ComponentInfo::~ComponentInfo() {}
57
Sorin Jianu49126332018-02-13 17:07:4258CrxUpdateService::CrxUpdateService(scoped_refptr<Configurator> config,
59 scoped_refptr<UpdateClient> update_client)
Sorin Jianuebd652462017-07-23 02:00:5860 : config_(config), update_client_(update_client) {
sorin7c717622015-05-26 19:59:0961 AddObserver(this);
[email protected]1ea21ad2013-09-02 04:20:3962}
[email protected]e8f96ff2011-08-03 05:07:3363
64CrxUpdateService::~CrxUpdateService() {
sorin7c717622015-05-26 19:59:0965 DCHECK(thread_checker_.CalledOnValidThread());
66
Sorin Jianua8ef73d2017-11-02 16:55:1767 for (auto& item : ready_callbacks_) {
68 std::move(item.second).Run();
sorin7c717622015-05-26 19:59:0969 }
70
71 RemoveObserver(this);
72
[email protected]e8f96ff2011-08-03 05:07:3373 Stop();
[email protected]1ea21ad2013-09-02 04:20:3974}
[email protected]e8f96ff2011-08-03 05:07:3375
[email protected]d3268fe2014-04-25 02:14:2376void CrxUpdateService::AddObserver(Observer* observer) {
[email protected]ed6fb982014-07-23 16:56:5277 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:0978 update_client_->AddObserver(observer);
[email protected]d3268fe2014-04-25 02:14:2379}
80
81void CrxUpdateService::RemoveObserver(Observer* observer) {
[email protected]ed6fb982014-07-23 16:56:5282 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:0983 update_client_->RemoveObserver(observer);
[email protected]d3268fe2014-04-25 02:14:2384}
85
sorin7c717622015-05-26 19:59:0986void CrxUpdateService::Start() {
87 DCHECK(thread_checker_.CalledOnValidThread());
88 VLOG(1) << "CrxUpdateService starting up. "
89 << "First update attempt will take place in "
90 << config_->InitialDelay() << " seconds. "
91 << "Next update attempt will take place in "
92 << config_->NextCheckDelay() << " seconds. ";
[email protected]e8f96ff2011-08-03 05:07:3393
sorin7c717622015-05-26 19:59:0994 timer_.Start(
95 base::TimeDelta::FromSeconds(config_->InitialDelay()),
96 base::TimeDelta::FromSeconds(config_->NextCheckDelay()),
97 base::Bind(base::IgnoreResult(&CrxUpdateService::CheckForUpdates),
98 base::Unretained(this)));
[email protected]e8f96ff2011-08-03 05:07:3399}
100
sorin7c717622015-05-26 19:59:09101// Stops the update loop. In flight operations will be completed.
102void CrxUpdateService::Stop() {
103 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]fb53e652014-04-30 11:27:19104 VLOG(1) << "CrxUpdateService stopping";
[email protected]e8f96ff2011-08-03 05:07:33105 timer_.Stop();
sorinecaad3e2015-11-13 19:15:52106 update_client_->Stop();
[email protected]e8f96ff2011-08-03 05:07:33107}
108
109// Adds a component to be checked for upgrades. If the component exists it
sorin7c717622015-05-26 19:59:09110// it will be replaced.
111bool CrxUpdateService::RegisterComponent(const CrxComponent& component) {
[email protected]ed6fb982014-07-23 16:56:52112 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]d0c8b8b42014-05-06 05:11:45113 if (component.pk_hash.empty() || !component.version.IsValid() ||
sorin7c717622015-05-26 19:59:09114 !component.installer) {
115 return false;
[email protected]e8f96ff2011-08-03 05:07:33116 }
117
sorin7c717622015-05-26 19:59:09118 // Update the registration data if the component has been registered before.
119 const std::string id(GetCrxComponentID(component));
120 auto it = components_.find(id);
121 if (it != components_.end()) {
122 it->second = component;
123 return true;
[email protected]10bc0222014-06-11 13:44:38124 }
[email protected]e8f96ff2011-08-03 05:07:33125
sorin7c717622015-05-26 19:59:09126 components_.insert(std::make_pair(id, component));
127 components_order_.push_back(id);
waffles77255cc2016-08-02 17:25:12128 for (const auto& mime_type : component.handled_mime_types)
129 component_ids_by_mime_type_[mime_type] = id;
sorin7c717622015-05-26 19:59:09130
131 // Create an initial state for this component. The state is mutated in
132 // response to events from the UpdateClient instance.
133 CrxUpdateItem item;
134 item.id = id;
135 item.component = component;
136 const auto inserted = component_states_.insert(std::make_pair(id, item));
137 DCHECK(inserted.second);
138
139 // Start the timer if this is the first component registered. The first timer
140 // event occurs after an interval defined by the component update
141 // configurator. The subsequent timer events are repeated with a period
142 // defined by the same configurator.
143 if (components_.size() == 1)
144 Start();
145
146 return true;
[email protected]e8f96ff2011-08-03 05:07:33147}
148
sorin7c717622015-05-26 19:59:09149bool CrxUpdateService::UnregisterComponent(const std::string& id) {
150 DCHECK(thread_checker_.CalledOnValidThread());
151 auto it = components_.find(id);
152 if (it == components_.end())
153 return false;
bauerb1f6657e72015-02-09 00:00:27154
sorin7c717622015-05-26 19:59:09155 DCHECK_EQ(id, it->first);
bauerb1f6657e72015-02-09 00:00:27156
sorin7c717622015-05-26 19:59:09157 // Delay the uninstall of the component if the component is being updated.
158 if (update_client_->IsUpdating(id)) {
159 components_pending_unregistration_.push_back(id);
160 return true;
161 }
162
163 return DoUnregisterComponent(it->second);
164}
165
166bool CrxUpdateService::DoUnregisterComponent(const CrxComponent& component) {
167 DCHECK(thread_checker_.CalledOnValidThread());
168
169 const auto id = GetCrxComponentID(component);
170 DCHECK(ready_callbacks_.find(id) == ready_callbacks_.end());
171
172 const bool result = component.installer->Uninstall();
173
174 const auto pos =
175 std::find(components_order_.begin(), components_order_.end(), id);
176 if (pos != components_order_.end())
177 components_order_.erase(pos);
178
179 components_.erase(id);
180 component_states_.erase(id);
181
182 return result;
bauerb1f6657e72015-02-09 00:00:27183}
184
[email protected]68bf09e2014-06-03 00:10:56185std::vector<std::string> CrxUpdateService::GetComponentIDs() const {
[email protected]ed6fb982014-07-23 16:56:52186 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:09187 std::vector<std::string> ids;
188 for (const auto& it : components_)
189 ids.push_back(it.first);
190 return ids;
[email protected]68bf09e2014-06-03 00:10:56191}
192
waffles77255cc2016-08-02 17:25:12193std::unique_ptr<ComponentInfo> CrxUpdateService::GetComponentForMimeType(
194 const std::string& mime_type) const {
195 DCHECK(thread_checker_.CalledOnValidThread());
196 const auto it = component_ids_by_mime_type_.find(mime_type);
197 if (it == component_ids_by_mime_type_.end())
198 return nullptr;
vmpstr6d9996c82017-02-23 00:43:25199 auto* const component = GetComponent(it->second);
waffles77255cc2016-08-02 17:25:12200 if (!component)
201 return nullptr;
Gyuyoung Kim6afb5082018-01-19 13:35:57202 return std::make_unique<ComponentInfo>(
Joshua Pawlicki0499ac82017-08-17 18:29:07203 GetCrxComponentID(*component), component->fingerprint,
204 base::UTF8ToUTF16(component->name), component->version);
205}
206
207std::vector<ComponentInfo> CrxUpdateService::GetComponents() const {
208 DCHECK(thread_checker_.CalledOnValidThread());
209 std::vector<ComponentInfo> result;
210 for (const auto& it : components_) {
211 result.push_back(ComponentInfo(it.first, it.second.fingerprint,
212 base::UTF8ToUTF16(it.second.name),
213 it.second.version));
214 }
215 return result;
waffles77255cc2016-08-02 17:25:12216}
217
[email protected]78efe2e92014-08-08 15:53:22218OnDemandUpdater& CrxUpdateService::GetOnDemandUpdater() {
sorin7c717622015-05-26 19:59:09219 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]78efe2e92014-08-08 15:53:22220 return *this;
221}
222
sorin7c717622015-05-26 19:59:09223const CrxComponent* CrxUpdateService::GetComponent(
224 const std::string& id) const {
225 DCHECK(thread_checker_.CalledOnValidThread());
226 const auto it(components_.find(id));
Ivan Kotenkov75b1c3a2017-10-24 14:47:24227 return it != components_.end() ? &(it->second) : nullptr;
sorin7c717622015-05-26 19:59:09228}
229
230const CrxUpdateItem* CrxUpdateService::GetComponentState(
231 const std::string& id) const {
232 DCHECK(thread_checker_.CalledOnValidThread());
233 const auto it(component_states_.find(id));
Ivan Kotenkov75b1c3a2017-10-24 14:47:24234 return it != component_states_.end() ? &it->second : nullptr;
sorin7c717622015-05-26 19:59:09235}
236
237void CrxUpdateService::MaybeThrottle(const std::string& id,
Sorin Jianua8ef73d2017-11-02 16:55:17238 base::OnceClosure callback) {
[email protected]78efe2e92014-08-08 15:53:22239 DCHECK(thread_checker_.CalledOnValidThread());
Sorin Jianua8ef73d2017-11-02 16:55:17240 const auto it = components_.find(id);
sorin7c717622015-05-26 19:59:09241 if (it != components_.end()) {
242 DCHECK_EQ(it->first, id);
243 if (OnDemandUpdateWithCooldown(id)) {
Sorin Jianua8ef73d2017-11-02 16:55:17244 ready_callbacks_.insert(std::make_pair(id, std::move(callback)));
sorin7c717622015-05-26 19:59:09245 return;
246 }
[email protected]78efe2e92014-08-08 15:53:22247 }
sorin7c717622015-05-26 19:59:09248
Sorin Jianua8ef73d2017-11-02 16:55:17249 // Unblock the request if the request can't be throttled.
250 std::move(callback).Run();
sorin7c717622015-05-26 19:59:09251}
252
sorin4c520182016-08-19 17:27:44253void CrxUpdateService::OnDemandUpdate(const std::string& id,
Vladislav Kuzkokov12eca792017-10-20 12:45:38254 Callback callback) {
sorin7c717622015-05-26 19:59:09255 DCHECK(thread_checker_.CalledOnValidThread());
256
sorin4c520182016-08-19 17:27:44257 if (!GetComponent(id)) {
drbasic6d4d9ce2017-02-22 10:33:59258 if (!callback.is_null()) {
259 base::ThreadTaskRunnerHandle::Get()->PostTask(
Vladislav Kuzkokov12eca792017-10-20 12:45:38260 FROM_HERE, base::BindOnce(std::move(callback),
261 update_client::Error::INVALID_ARGUMENT));
drbasic6d4d9ce2017-02-22 10:33:59262 }
sorin4c520182016-08-19 17:27:44263 return;
264 }
sorin7c717622015-05-26 19:59:09265
Vladislav Kuzkokov12eca792017-10-20 12:45:38266 OnDemandUpdateInternal(id, std::move(callback));
sorin7c717622015-05-26 19:59:09267}
268
269bool CrxUpdateService::OnDemandUpdateWithCooldown(const std::string& id) {
270 DCHECK(thread_checker_.CalledOnValidThread());
271
272 DCHECK(GetComponent(id));
273
274 // Check if the request is too soon.
vmpstr2de366b2016-07-20 21:35:48275 const auto* component_state(GetComponentState(id));
Ivan Afanasyevec822ac2017-09-05 14:10:06276 if (component_state && !component_state->last_check.is_null()) {
sorin1827db12016-09-15 20:43:31277 base::TimeDelta delta =
278 base::TimeTicks::Now() - component_state->last_check;
sorin7c717622015-05-26 19:59:09279 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay()))
280 return false;
281 }
282
sorin842703b2016-11-02 23:59:23283 OnDemandUpdateInternal(id, Callback());
sorin4c520182016-08-19 17:27:44284 return true;
sorin7c717622015-05-26 19:59:09285}
286
sorin4c520182016-08-19 17:27:44287void CrxUpdateService::OnDemandUpdateInternal(const std::string& id,
Vladislav Kuzkokov12eca792017-10-20 12:45:38288 Callback callback) {
sorin7c717622015-05-26 19:59:09289 DCHECK(thread_checker_.CalledOnValidThread());
290
sorin85953dc2016-03-10 00:32:48291 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.Calls", UPDATE_TYPE_MANUAL,
292 UPDATE_TYPE_COUNT);
sorin7c717622015-05-26 19:59:09293 update_client_->Install(
Sorin Jianu7c22795b2018-04-26 22:16:52294 id,
295 base::BindOnce(&CrxUpdateService::GetCrxComponents,
296 base::Unretained(this)),
Vladislav Kuzkokov12eca792017-10-20 12:45:38297 base::BindOnce(&CrxUpdateService::OnUpdateComplete,
298 base::Unretained(this), std::move(callback),
299 base::TimeTicks::Now()));
sorin7c717622015-05-26 19:59:09300}
301
302bool CrxUpdateService::CheckForUpdates() {
303 DCHECK(thread_checker_.CalledOnValidThread());
sorin85953dc2016-03-10 00:32:48304
305 UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.Calls", UPDATE_TYPE_AUTOMATIC,
306 UPDATE_TYPE_COUNT);
307
sorinfccbf2d2016-04-04 20:34:34308 std::vector<std::string> secure_ids; // Requires HTTPS for update checks.
309 std::vector<std::string> unsecure_ids; // Can fallback to HTTP.
sorin7c717622015-05-26 19:59:09310 for (const auto id : components_order_) {
311 DCHECK(components_.find(id) != components_.end());
sorinfccbf2d2016-04-04 20:34:34312
vmpstr2de366b2016-07-20 21:35:48313 auto* component(GetComponent(id));
sorinfccbf2d2016-04-04 20:34:34314 if (!component || component->requires_network_encryption)
315 secure_ids.push_back(id);
316 else
317 unsecure_ids.push_back(id);
sorin7c717622015-05-26 19:59:09318 }
319
sorinfccbf2d2016-04-04 20:34:34320 if (!unsecure_ids.empty()) {
Sorin Jianu7c22795b2018-04-26 22:16:52321 update_client_->Update(unsecure_ids,
322 base::BindOnce(&CrxUpdateService::GetCrxComponents,
323 base::Unretained(this)),
324 false,
325 base::BindOnce(&CrxUpdateService::OnUpdateComplete,
326 base::Unretained(this), Callback(),
327 base::TimeTicks::Now()));
sorinfccbf2d2016-04-04 20:34:34328 }
329
330 if (!secure_ids.empty()) {
Sorin Jianu7c22795b2018-04-26 22:16:52331 update_client_->Update(secure_ids,
332 base::BindOnce(&CrxUpdateService::GetCrxComponents,
333 base::Unretained(this)),
334 false,
335 base::BindOnce(&CrxUpdateService::OnUpdateComplete,
336 base::Unretained(this), Callback(),
337 base::TimeTicks::Now()));
sorinfccbf2d2016-04-04 20:34:34338 }
sorin7c717622015-05-26 19:59:09339
340 return true;
[email protected]78efe2e92014-08-08 15:53:22341}
342
sorin7c717622015-05-26 19:59:09343bool CrxUpdateService::GetComponentDetails(const std::string& id,
[email protected]f392e372014-06-12 07:25:57344 CrxUpdateItem* item) const {
[email protected]ed6fb982014-07-23 16:56:52345 DCHECK(thread_checker_.CalledOnValidThread());
sorin7c717622015-05-26 19:59:09346
347 // First, if this component is currently being updated, return its state from
348 // the update client.
349 if (update_client_->GetCrxUpdateState(id, item))
350 return true;
351
352 // Otherwise, return the last seen state of the component, if such a
353 // state exists.
354 const auto component_states_it = component_states_.find(id);
355 if (component_states_it != component_states_.end()) {
356 *item = component_states_it->second;
357 return true;
358 }
359
360 return false;
[email protected]2e919ddd2013-08-21 05:05:17361}
362
Sorin Jianu7c22795b2018-04-26 22:16:52363std::vector<std::unique_ptr<CrxComponent>> CrxUpdateService::GetCrxComponents(
364 const std::vector<std::string>& ids) {
sorin7c717622015-05-26 19:59:09365 DCHECK(thread_checker_.CalledOnValidThread());
Sorin Jianu7c22795b2018-04-26 22:16:52366 std::vector<std::unique_ptr<CrxComponent>> components;
sorin7c717622015-05-26 19:59:09367 for (const auto& id : ids) {
Sorin Jianu7c22795b2018-04-26 22:16:52368 const auto* registered_component = GetComponent(id);
369 components.push_back(registered_component ? std::make_unique<CrxComponent>(
370 *registered_component)
371 : nullptr);
sorin7c717622015-05-26 19:59:09372 }
Sorin Jianu7c22795b2018-04-26 22:16:52373 return components;
[email protected]ed6fb982014-07-23 16:56:52374}
375
sorin842703b2016-11-02 23:59:23376void CrxUpdateService::OnUpdateComplete(Callback callback,
sorin4c520182016-08-19 17:27:44377 const base::TimeTicks& start_time,
sorin7b8650522016-11-02 18:23:41378 update_client::Error error) {
sorin7c717622015-05-26 19:59:09379 DCHECK(thread_checker_.CalledOnValidThread());
sorin7b8650522016-11-02 18:23:41380 VLOG(1) << "Update completed with error " << static_cast<int>(error);
sorin7c717622015-05-26 19:59:09381
sorin7b8650522016-11-02 18:23:41382 UMA_HISTOGRAM_BOOLEAN("ComponentUpdater.UpdateCompleteResult",
383 error != update_client::Error::NONE);
sorin85953dc2016-03-10 00:32:48384 UMA_HISTOGRAM_LONG_TIMES_100("ComponentUpdater.UpdateCompleteTime",
385 base::TimeTicks::Now() - start_time);
386
sorin7c717622015-05-26 19:59:09387 for (const auto id : components_pending_unregistration_) {
388 if (!update_client_->IsUpdating(id)) {
vmpstr2de366b2016-07-20 21:35:48389 const auto* component = GetComponent(id);
sorin7c717622015-05-26 19:59:09390 if (component)
391 DoUnregisterComponent(*component);
392 }
393 }
sorin4c520182016-08-19 17:27:44394
395 if (!callback.is_null()) {
Sorin Jianuebd652462017-07-23 02:00:58396 base::ThreadTaskRunnerHandle::Get()->PostTask(
Vladislav Kuzkokov12eca792017-10-20 12:45:38397 FROM_HERE, base::BindOnce(std::move(callback), error));
sorin4c520182016-08-19 17:27:44398 }
sorin7c717622015-05-26 19:59:09399}
400
401void CrxUpdateService::OnEvent(Events event, const std::string& id) {
[email protected]ed6fb982014-07-23 16:56:52402 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]93e8e2c2014-01-04 12:29:23403
sorin7c717622015-05-26 19:59:09404 // Unblock all throttles for the component.
405 if (event == Observer::Events::COMPONENT_UPDATED ||
Sorin Jianucbb10e12018-01-23 18:01:44406 event == Observer::Events::COMPONENT_NOT_UPDATED ||
407 event == Observer::Events::COMPONENT_UPDATE_ERROR) {
sorin7c717622015-05-26 19:59:09408 auto callbacks = ready_callbacks_.equal_range(id);
409 for (auto it = callbacks.first; it != callbacks.second; ++it) {
Sorin Jianua8ef73d2017-11-02 16:55:17410 std::move(it->second).Run();
sorin7c717622015-05-26 19:59:09411 }
412 ready_callbacks_.erase(id);
413 }
414
415 CrxUpdateItem update_item;
416 if (!update_client_->GetCrxUpdateState(id, &update_item))
[email protected]e8f96ff2011-08-03 05:07:33417 return;
[email protected]93e8e2c2014-01-04 12:29:23418
sorin7c717622015-05-26 19:59:09419 // Update the state of the item.
420 auto it = component_states_.find(id);
421 DCHECK(it != component_states_.end());
422 it->second = update_item;
bauerb1f6657e72015-02-09 00:00:27423
sorin7c717622015-05-26 19:59:09424 // Update the component registration with the new version.
425 if (event == Observer::Events::COMPONENT_UPDATED) {
vmpstr2de366b2016-07-20 21:35:48426 auto* component(const_cast<CrxComponent*>(GetComponent(id)));
sorin7c717622015-05-26 19:59:09427 if (component) {
428 component->version = update_item.next_version;
429 component->fingerprint = update_item.next_fp;
bauerb1f6657e72015-02-09 00:00:27430 }
431 }
[email protected]68bf09e2014-06-03 00:10:56432}
433
[email protected]00a77fa2013-11-02 04:18:46434///////////////////////////////////////////////////////////////////////////////
435
[email protected]e8f96ff2011-08-03 05:07:33436// The component update factory. Using the component updater as a singleton
437// is the job of the browser process.
sorin7c717622015-05-26 19:59:09438// TODO(sorin): consider making this a singleton.
dchenga0ee5fb82016-04-26 02:46:55439std::unique_ptr<ComponentUpdateService> ComponentUpdateServiceFactory(
Sorin Jianu49126332018-02-13 17:07:42440 scoped_refptr<Configurator> config) {
[email protected]e8f96ff2011-08-03 05:07:33441 DCHECK(config);
sorin7c717622015-05-26 19:59:09442 auto update_client = update_client::UpdateClientFactory(config);
Gyuyoung Kim6afb5082018-01-19 13:35:57443 return std::make_unique<CrxUpdateService>(config, std::move(update_client));
[email protected]e8f96ff2011-08-03 05:07:33444}
[email protected]2cddef42013-11-22 08:23:22445
[email protected]055981f2014-01-17 20:22:32446} // namespace component_updater