1 // Copyright 2014 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.
5 #include "components/component_updater/component_updater_service.h"
11 #include "base/at_exit.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/callback.h"
15 #include "base/compiler_specific.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/logging.h"
19 #include "base/macros.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop/message_loop_proxy.h"
22 #include "base/observer_list.h"
23 #include "base/sequenced_task_runner.h"
24 #include "base/stl_util.h"
25 #include "base/threading/sequenced_worker_pool.h"
26 #include "base/threading/thread_checker.h"
27 #include "base/timer/timer.h"
28 #include "components/update_client/component_patcher_operation.h"
29 #include "components/update_client/component_unpacker.h"
30 #include "components/update_client/configurator.h"
31 #include "components/update_client/crx_downloader.h"
32 #include "components/update_client/crx_update_item.h"
33 #include "components/update_client/ping_manager.h"
34 #include "components/update_client/update_checker.h"
35 #include "components/update_client/update_client.h"
36 #include "components/update_client/update_response.h"
37 #include "components/update_client/utils.h"
40 using update_client::ComponentInstaller
;
41 using update_client::ComponentUnpacker
;
42 using update_client::Configurator
;
43 using update_client::CrxComponent
;
44 using update_client::CrxDownloader
;
45 using update_client::CrxUpdateItem
;
46 using update_client::PingManager
;
47 using update_client::UpdateChecker
;
48 using update_client::UpdateResponse
;
50 namespace component_updater
{
52 // The component updater is designed to live until process shutdown, so
53 // base::Bind() calls are not refcounted.
57 // Returns true if the |proposed| version is newer than |current| version.
58 bool IsVersionNewer(const Version
& current
, const std::string
& proposed
) {
59 Version
proposed_ver(proposed
);
60 return proposed_ver
.IsValid() && current
.CompareTo(proposed_ver
) < 0;
63 // Returns true if a differential update is available, it has not failed yet,
64 // and the configuration allows it.
65 bool CanTryDiffUpdate(const CrxUpdateItem
* update_item
,
66 const Configurator
& config
) {
67 return HasDiffUpdate(update_item
) && !update_item
->diff_update_failed
&&
68 config
.DeltasEnabled();
71 void AppendDownloadMetrics(
72 const std::vector
<CrxDownloader::DownloadMetrics
>& source
,
73 std::vector
<CrxDownloader::DownloadMetrics
>* destination
) {
74 destination
->insert(destination
->end(), source
.begin(), source
.end());
79 //////////////////////////////////////////////////////////////////////////////
80 // The one and only implementation of the ComponentUpdateService interface. In
81 // charge of running the show. The main method is ProcessPendingItems() which
82 // is called periodically to do the upgrades/installs or the update checks.
83 // An important consideration here is to be as "low impact" as we can to the
84 // rest of the browser, so even if we have many components registered and
85 // eligible for update, we only do one thing at a time with pauses in between
86 // the tasks. Also when we do network requests there is only one |url_fetcher_|
87 // in flight at a time.
88 // There are no locks in this code, the main structure |work_items_| is mutated
89 // only from the main thread. The unpack and installation is done in a blocking
90 // pool thread. The network requests are done in the IO thread or in the file
92 class CrxUpdateService
: public ComponentUpdateService
, public OnDemandUpdater
{
94 explicit CrxUpdateService(Configurator
* config
);
95 ~CrxUpdateService() override
;
97 // Overrides for ComponentUpdateService.
98 void AddObserver(Observer
* observer
) override
;
99 void RemoveObserver(Observer
* observer
) override
;
100 Status
Start() override
;
101 Status
Stop() override
;
102 Status
RegisterComponent(const CrxComponent
& component
) override
;
103 std::vector
<std::string
> GetComponentIDs() const override
;
104 OnDemandUpdater
& GetOnDemandUpdater() override
;
105 void MaybeThrottle(const std::string
& crx_id
,
106 const base::Closure
& callback
) override
;
107 scoped_refptr
<base::SequencedTaskRunner
> GetSequencedTaskRunner() override
;
109 // Context for a crx download url request.
111 ComponentInstaller
* installer
;
112 std::vector
<uint8_t> pk_hash
;
114 std::string fingerprint
;
115 CRXContext() : installer(NULL
) {}
126 enum StepDelayInterval
{
132 // Overrides for ComponentUpdateService.
133 bool GetComponentDetails(const std::string
& component_id
,
134 CrxUpdateItem
* item
) const override
;
136 // Overrides for OnDemandUpdater.
137 Status
OnDemandUpdate(const std::string
& component_id
) override
;
139 void UpdateCheckComplete(const GURL
& original_url
,
141 const std::string
& error_message
,
142 const UpdateResponse::Results
& results
);
143 void OnUpdateCheckSucceeded(const UpdateResponse::Results
& results
);
144 void OnUpdateCheckFailed(int error
, const std::string
& error_message
);
146 void DownloadProgress(const std::string
& component_id
,
147 const CrxDownloader::Result
& download_result
);
149 void DownloadComplete(scoped_ptr
<CRXContext
> crx_context
,
150 const CrxDownloader::Result
& download_result
);
152 Status
OnDemandUpdateInternal(CrxUpdateItem
* item
);
153 Status
OnDemandUpdateWithCooldown(CrxUpdateItem
* item
);
155 void ProcessPendingItems();
157 // Find a component that is ready to update.
158 CrxUpdateItem
* FindReadyComponent() const;
160 // Prepares the components for an update check and initiates the request.
161 // Returns true if an update check request has been made. Returns false if
162 // no update check was needed or an error occured.
163 bool CheckForUpdates();
165 void UpdateComponent(CrxUpdateItem
* workitem
);
167 void ScheduleNextRun(StepDelayInterval step_delay
);
169 void ParseResponse(const std::string
& xml
);
171 void Install(scoped_ptr
<CRXContext
> context
, const base::FilePath
& crx_path
);
173 void EndUnpacking(const std::string
& component_id
,
174 const base::FilePath
& crx_path
,
175 ComponentUnpacker::Error error
,
178 void DoneInstalling(const std::string
& component_id
,
179 ComponentUnpacker::Error error
,
182 void ChangeItemState(CrxUpdateItem
* item
, CrxUpdateItem::Status to
);
184 size_t ChangeItemStatus(CrxUpdateItem::Status from
, CrxUpdateItem::Status to
);
186 CrxUpdateItem
* FindUpdateItemById(const std::string
& id
) const;
188 void NotifyObservers(Observer::Events event
, const std::string
& id
);
190 bool HasOnDemandItems() const;
192 Status
GetServiceStatus(const CrxUpdateItem::Status status
);
194 scoped_ptr
<Configurator
> config_
;
196 scoped_ptr
<UpdateChecker
> update_checker_
;
198 scoped_ptr
<PingManager
> ping_manager_
;
200 scoped_refptr
<ComponentUnpacker
> unpacker_
;
202 scoped_ptr
<CrxDownloader
> crx_downloader_
;
204 // A collection of every work item.
205 typedef std::vector
<CrxUpdateItem
*> UpdateItems
;
206 UpdateItems work_items_
;
208 base::OneShotTimer
<CrxUpdateService
> timer_
;
210 base::ThreadChecker thread_checker_
;
212 // Used to post responses back to the main thread.
213 scoped_refptr
<base::SingleThreadTaskRunner
> main_task_runner_
;
215 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner_
;
219 ObserverList
<Observer
> observer_list_
;
221 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService
);
224 //////////////////////////////////////////////////////////////////////////////
226 CrxUpdateService::CrxUpdateService(Configurator
* config
)
228 ping_manager_(new PingManager(*config
)),
229 main_task_runner_(base::MessageLoopProxy::current()),
230 blocking_task_runner_(config
->GetSequencedTaskRunner()),
234 CrxUpdateService::~CrxUpdateService() {
235 // Because we are a singleton, at this point only the main thread should be
236 // alive, this simplifies the management of the work that could be in
237 // flight in other threads.
239 STLDeleteElements(&work_items_
);
242 void CrxUpdateService::AddObserver(Observer
* observer
) {
243 DCHECK(thread_checker_
.CalledOnValidThread());
244 observer_list_
.AddObserver(observer
);
247 void CrxUpdateService::RemoveObserver(Observer
* observer
) {
248 DCHECK(thread_checker_
.CalledOnValidThread());
249 observer_list_
.RemoveObserver(observer
);
252 ComponentUpdateService::Status
CrxUpdateService::Start() {
253 // Note that RegisterComponent will call Start() when the first
254 // component is registered, so it can be called twice. This way
255 // we avoid scheduling the timer if there is no work to do.
256 VLOG(1) << "CrxUpdateService starting up";
258 if (work_items_
.empty())
261 NotifyObservers(Observer::COMPONENT_UPDATER_STARTED
, "");
263 VLOG(1) << "First update attempt will take place in "
264 << config_
->InitialDelay() << " seconds";
265 timer_
.Start(FROM_HERE
,
266 base::TimeDelta::FromSeconds(config_
->InitialDelay()),
268 &CrxUpdateService::ProcessPendingItems
);
272 // Stop the main check + update loop. In flight operations will be
274 ComponentUpdateService::Status
CrxUpdateService::Stop() {
275 VLOG(1) << "CrxUpdateService stopping";
281 bool CrxUpdateService::HasOnDemandItems() const {
284 static bool IsOnDemand(CrxUpdateItem
* item
) { return item
->on_demand
; }
286 return std::find_if(work_items_
.begin(),
288 Helper::IsOnDemand
) != work_items_
.end();
291 // This function sets the timer which will call ProcessPendingItems() or
292 // ProcessRequestedItem() if there is an on_demand item. There
293 // are three kinds of waits:
294 // - a short delay, when there is immediate work to be done.
295 // - a medium delay, when there are updates to be applied within the current
296 // update cycle, or there are components that are still unchecked.
297 // - a long delay when a full check/update cycle has completed for all
299 void CrxUpdateService::ScheduleNextRun(StepDelayInterval step_delay
) {
300 DCHECK(thread_checker_
.CalledOnValidThread());
301 DCHECK(!update_checker_
);
302 CHECK(!timer_
.IsRunning());
303 // It could be the case that Stop() had been called while a url request
304 // or unpacking was in flight, if so we arrive here but |running_| is
305 // false. In that case do not loop again.
309 // Keep the delay short if in the middle of an update (step_delay),
310 // or there are new requested_work_items_ that have not been processed yet.
311 int64_t delay_seconds
= 0;
312 if (!HasOnDemandItems()) {
313 switch (step_delay
) {
314 case kStepDelayShort
:
315 delay_seconds
= config_
->StepDelay();
317 case kStepDelayMedium
:
318 delay_seconds
= config_
->StepDelayMedium();
321 delay_seconds
= config_
->NextCheckDelay();
325 delay_seconds
= config_
->StepDelay();
328 if (step_delay
!= kStepDelayShort
) {
329 NotifyObservers(Observer::COMPONENT_UPDATER_SLEEPING
, "");
331 // Zero is only used for unit tests.
332 if (0 == delay_seconds
)
336 VLOG(1) << "Scheduling next run to occur in " << delay_seconds
<< " seconds";
337 timer_
.Start(FROM_HERE
,
338 base::TimeDelta::FromSeconds(delay_seconds
),
340 &CrxUpdateService::ProcessPendingItems
);
343 // Given a extension-like component id, find the associated component.
344 CrxUpdateItem
* CrxUpdateService::FindUpdateItemById(
345 const std::string
& id
) const {
346 DCHECK(thread_checker_
.CalledOnValidThread());
347 CrxUpdateItem::FindById
finder(id
);
348 UpdateItems::const_iterator it
=
349 std::find_if(work_items_
.begin(), work_items_
.end(), finder
);
350 return it
!= work_items_
.end() ? *it
: NULL
;
353 // Changes a component's status, clearing on_demand and firing notifications as
354 // necessary. By convention, this is the only function that can change a
355 // CrxUpdateItem's |status|.
356 // TODO(waffles): Do we want to add DCHECKS for valid state transitions here?
357 void CrxUpdateService::ChangeItemState(CrxUpdateItem
* item
,
358 CrxUpdateItem::Status to
) {
359 DCHECK(thread_checker_
.CalledOnValidThread());
360 if (to
== CrxUpdateItem::kNoUpdate
|| to
== CrxUpdateItem::kUpdated
||
361 to
== CrxUpdateItem::kUpToDate
) {
362 item
->on_demand
= false;
368 case CrxUpdateItem::kCanUpdate
:
369 NotifyObservers(Observer::COMPONENT_UPDATE_FOUND
, item
->id
);
371 case CrxUpdateItem::kUpdatingDiff
:
372 case CrxUpdateItem::kUpdating
:
373 NotifyObservers(Observer::COMPONENT_UPDATE_READY
, item
->id
);
375 case CrxUpdateItem::kUpdated
:
376 NotifyObservers(Observer::COMPONENT_UPDATED
, item
->id
);
378 case CrxUpdateItem::kUpToDate
:
379 case CrxUpdateItem::kNoUpdate
:
380 NotifyObservers(Observer::COMPONENT_NOT_UPDATED
, item
->id
);
382 case CrxUpdateItem::kNew
:
383 case CrxUpdateItem::kChecking
:
384 case CrxUpdateItem::kDownloading
:
385 case CrxUpdateItem::kDownloadingDiff
:
386 case CrxUpdateItem::kLastStatus
:
387 // No notification for these states.
391 // Free possible pending network requests.
392 if ((to
== CrxUpdateItem::kUpdated
) || (to
== CrxUpdateItem::kUpToDate
) ||
393 (to
== CrxUpdateItem::kNoUpdate
)) {
394 for (std::vector
<base::Closure
>::iterator it
=
395 item
->ready_callbacks
.begin();
396 it
!= item
->ready_callbacks
.end();
400 item
->ready_callbacks
.clear();
404 // Changes all the components in |work_items_| that have |from| status to
405 // |to| status and returns how many have been changed.
406 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from
,
407 CrxUpdateItem::Status to
) {
408 DCHECK(thread_checker_
.CalledOnValidThread());
410 for (UpdateItems::iterator it
= work_items_
.begin();
411 it
!= work_items_
.end();
413 CrxUpdateItem
* item
= *it
;
414 if (item
->status
== from
) {
415 ChangeItemState(item
, to
);
422 // Adds a component to be checked for upgrades. If the component exists it
423 // it will be replaced and the return code is kReplaced.
424 ComponentUpdateService::Status
CrxUpdateService::RegisterComponent(
425 const CrxComponent
& component
) {
426 DCHECK(thread_checker_
.CalledOnValidThread());
427 if (component
.pk_hash
.empty() || !component
.version
.IsValid() ||
428 !component
.installer
)
431 std::string
id(GetCrxComponentID(component
));
432 CrxUpdateItem
* uit
= FindUpdateItemById(id
);
434 uit
->component
= component
;
438 uit
= new CrxUpdateItem
;
440 uit
->component
= component
;
442 work_items_
.push_back(uit
);
444 // If this is the first component registered we call Start to
445 // schedule the first timer. Otherwise, reset the timer to trigger another
446 // pass over the work items, if the component updater is sleeping, fact
447 // indicated by a running timer. If the timer is not running, it means that
448 // the service is busy updating something, and in that case, this component
449 // will be picked up at the next pass.
451 if (work_items_
.size() == 1) {
453 } else if (timer_
.IsRunning()) {
454 timer_
.Start(FROM_HERE
,
455 base::TimeDelta::FromSeconds(config_
->InitialDelay()),
457 &CrxUpdateService::ProcessPendingItems
);
464 std::vector
<std::string
> CrxUpdateService::GetComponentIDs() const {
465 DCHECK(thread_checker_
.CalledOnValidThread());
466 std::vector
<std::string
> component_ids
;
467 for (UpdateItems::const_iterator it
= work_items_
.begin();
468 it
!= work_items_
.end();
470 const CrxUpdateItem
* item
= *it
;
471 component_ids
.push_back(item
->id
);
473 return component_ids
;
476 OnDemandUpdater
& CrxUpdateService::GetOnDemandUpdater() {
480 void CrxUpdateService::MaybeThrottle(const std::string
& crx_id
,
481 const base::Closure
& callback
) {
482 DCHECK(thread_checker_
.CalledOnValidThread());
483 // Check if we can on-demand update, else unblock the request anyway.
484 CrxUpdateItem
* item
= FindUpdateItemById(crx_id
);
485 Status status
= OnDemandUpdateWithCooldown(item
);
486 if (status
== kOk
|| status
== kInProgress
) {
487 item
->ready_callbacks
.push_back(callback
);
493 scoped_refptr
<base::SequencedTaskRunner
>
494 CrxUpdateService::GetSequencedTaskRunner() {
495 return config_
->GetSequencedTaskRunner();
498 bool CrxUpdateService::GetComponentDetails(const std::string
& component_id
,
499 CrxUpdateItem
* item
) const {
500 DCHECK(thread_checker_
.CalledOnValidThread());
501 const CrxUpdateItem
* crx_update_item(FindUpdateItemById(component_id
));
503 *item
= *crx_update_item
;
504 return crx_update_item
!= NULL
;
507 // Start the process of checking for an update, for a particular component
508 // that was previously registered.
509 // |component_id| is a value returned from GetCrxComponentID().
510 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdate(
511 const std::string
& component_id
) {
512 return OnDemandUpdateInternal(FindUpdateItemById(component_id
));
515 // This is the main loop of the component updater. It updates one component
516 // at a time if updates are available. Otherwise, it does an update check or
517 // takes a long sleep until the loop runs again.
518 void CrxUpdateService::ProcessPendingItems() {
519 DCHECK(thread_checker_
.CalledOnValidThread());
521 CrxUpdateItem
* ready_upgrade
= FindReadyComponent();
523 UpdateComponent(ready_upgrade
);
527 if (!CheckForUpdates())
528 ScheduleNextRun(kStepDelayLong
);
531 CrxUpdateItem
* CrxUpdateService::FindReadyComponent() const {
534 static bool IsReadyOnDemand(CrxUpdateItem
* item
) {
535 return item
->on_demand
&& IsReady(item
);
537 static bool IsReady(CrxUpdateItem
* item
) {
538 return item
->status
== CrxUpdateItem::kCanUpdate
;
542 std::vector
<CrxUpdateItem
*>::const_iterator it
= std::find_if(
543 work_items_
.begin(), work_items_
.end(), Helper::IsReadyOnDemand
);
544 if (it
!= work_items_
.end())
546 it
= std::find_if(work_items_
.begin(), work_items_
.end(), Helper::IsReady
);
547 if (it
!= work_items_
.end())
552 // Prepares the components for an update check and initiates the request.
553 // On demand components are always included in the update check request.
554 // Otherwise, only include components that have not been checked recently.
555 bool CrxUpdateService::CheckForUpdates() {
556 const base::TimeDelta minimum_recheck_wait_time
=
557 base::TimeDelta::FromSeconds(config_
->MinimumReCheckWait());
558 const base::Time
now(base::Time::Now());
560 std::vector
<CrxUpdateItem
*> items_to_check
;
561 for (size_t i
= 0; i
!= work_items_
.size(); ++i
) {
562 CrxUpdateItem
* item
= work_items_
[i
];
563 DCHECK(item
->status
== CrxUpdateItem::kNew
||
564 item
->status
== CrxUpdateItem::kNoUpdate
||
565 item
->status
== CrxUpdateItem::kUpToDate
||
566 item
->status
== CrxUpdateItem::kUpdated
);
568 const base::TimeDelta
time_since_last_checked(now
- item
->last_check
);
570 if (!item
->on_demand
&&
571 time_since_last_checked
< minimum_recheck_wait_time
) {
572 VLOG(1) << "Skipping check for component update: id=" << item
->id
573 << ", time_since_last_checked="
574 << time_since_last_checked
.InSeconds()
575 << " seconds: too soon to check for an update";
579 VLOG(1) << "Scheduling update check for component id=" << item
->id
580 << ", time_since_last_checked="
581 << time_since_last_checked
.InSeconds() << " seconds";
583 item
->last_check
= now
;
584 item
->crx_urls
.clear();
585 item
->crx_diffurls
.clear();
586 item
->previous_version
= item
->component
.version
;
587 item
->next_version
= Version();
588 item
->previous_fp
= item
->component
.fingerprint
;
589 item
->next_fp
.clear();
590 item
->diff_update_failed
= false;
591 item
->error_category
= 0;
592 item
->error_code
= 0;
593 item
->extra_code1
= 0;
594 item
->diff_error_category
= 0;
595 item
->diff_error_code
= 0;
596 item
->diff_extra_code1
= 0;
597 item
->download_metrics
.clear();
599 items_to_check
.push_back(item
);
601 ChangeItemState(item
, CrxUpdateItem::kChecking
);
604 if (items_to_check
.empty())
607 update_checker_
= UpdateChecker::Create(*config_
).Pass();
608 return update_checker_
->CheckForUpdates(
610 config_
->ExtraRequestParams(),
611 base::Bind(&CrxUpdateService::UpdateCheckComplete
,
612 base::Unretained(this)));
615 void CrxUpdateService::UpdateComponent(CrxUpdateItem
* workitem
) {
616 scoped_ptr
<CRXContext
> crx_context(new CRXContext
);
617 crx_context
->pk_hash
= workitem
->component
.pk_hash
;
618 crx_context
->id
= workitem
->id
;
619 crx_context
->installer
= workitem
->component
.installer
;
620 crx_context
->fingerprint
= workitem
->next_fp
;
621 const std::vector
<GURL
>* urls
= NULL
;
622 bool allow_background_download
= false;
623 if (CanTryDiffUpdate(workitem
, *config_
)) {
624 urls
= &workitem
->crx_diffurls
;
625 ChangeItemState(workitem
, CrxUpdateItem::kDownloadingDiff
);
627 // Background downloads are enabled only for selected components and
628 // only for full downloads (see issue 340448).
629 allow_background_download
= workitem
->component
.allow_background_download
;
630 urls
= &workitem
->crx_urls
;
631 ChangeItemState(workitem
, CrxUpdateItem::kDownloading
);
634 // On demand component updates are always downloaded in foreground.
635 const bool is_background_download
= !workitem
->on_demand
&&
636 allow_background_download
&&
637 config_
->UseBackgroundDownloader();
639 crx_downloader_
.reset(
640 CrxDownloader::Create(is_background_download
,
641 config_
->RequestContext(),
642 blocking_task_runner_
,
643 config_
->GetSingleThreadTaskRunner()));
644 crx_downloader_
->set_progress_callback(
645 base::Bind(&CrxUpdateService::DownloadProgress
,
646 base::Unretained(this),
648 crx_downloader_
->StartDownload(*urls
,
649 base::Bind(&CrxUpdateService::DownloadComplete
,
650 base::Unretained(this),
651 base::Passed(&crx_context
)));
654 void CrxUpdateService::UpdateCheckComplete(
655 const GURL
& original_url
,
657 const std::string
& error_message
,
658 const UpdateResponse::Results
& results
) {
659 DCHECK(thread_checker_
.CalledOnValidThread());
660 VLOG(1) << "Update check completed from: " << original_url
.spec();
661 update_checker_
.reset();
663 OnUpdateCheckSucceeded(results
);
665 OnUpdateCheckFailed(error
, error_message
);
668 // Handles a valid Omaha update check response by matching the results with
669 // the registered components which were checked for updates.
670 // If updates are found, prepare the components for the actual version upgrade.
671 // One of these components will be drafted for the upgrade next time
672 // ProcessPendingItems is called.
673 void CrxUpdateService::OnUpdateCheckSucceeded(
674 const UpdateResponse::Results
& results
) {
675 size_t num_updates_pending
= 0;
676 DCHECK(thread_checker_
.CalledOnValidThread());
677 VLOG(1) << "Update check succeeded.";
678 std::vector
<UpdateResponse::Result
>::const_iterator it
;
679 for (it
= results
.list
.begin(); it
!= results
.list
.end(); ++it
) {
680 CrxUpdateItem
* crx
= FindUpdateItemById(it
->extension_id
);
684 if (crx
->status
!= CrxUpdateItem::kChecking
) {
686 continue; // Not updating this component now.
689 if (it
->manifest
.version
.empty()) {
690 // No version means no update available.
691 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
692 VLOG(1) << "No update available for component: " << crx
->id
;
696 if (!IsVersionNewer(crx
->component
.version
, it
->manifest
.version
)) {
697 // The component is up to date.
698 ChangeItemState(crx
, CrxUpdateItem::kUpToDate
);
699 VLOG(1) << "Component already up-to-date: " << crx
->id
;
703 if (!it
->manifest
.browser_min_version
.empty()) {
704 if (IsVersionNewer(config_
->GetBrowserVersion(),
705 it
->manifest
.browser_min_version
)) {
706 // The component is not compatible with this Chrome version.
707 VLOG(1) << "Ignoring incompatible component: " << crx
->id
;
708 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
713 if (it
->manifest
.packages
.size() != 1) {
714 // Assume one and only one package per component.
715 VLOG(1) << "Ignoring multiple packages for component: " << crx
->id
;
716 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
720 // Parse the members of the result and queue an upgrade for this component.
721 crx
->next_version
= Version(it
->manifest
.version
);
723 VLOG(1) << "Update found for component: " << crx
->id
;
725 typedef UpdateResponse::Result::Manifest::Package Package
;
726 const Package
& package(it
->manifest
.packages
[0]);
727 crx
->next_fp
= package
.fingerprint
;
729 // Resolve the urls by combining the base urls with the package names.
730 for (size_t i
= 0; i
!= it
->crx_urls
.size(); ++i
) {
731 const GURL
url(it
->crx_urls
[i
].Resolve(package
.name
));
733 crx
->crx_urls
.push_back(url
);
735 for (size_t i
= 0; i
!= it
->crx_diffurls
.size(); ++i
) {
736 const GURL
url(it
->crx_diffurls
[i
].Resolve(package
.namediff
));
738 crx
->crx_diffurls
.push_back(url
);
741 ChangeItemState(crx
, CrxUpdateItem::kCanUpdate
);
742 ++num_updates_pending
;
745 // All components that are not included in the update response are
746 // considered up to date.
747 ChangeItemStatus(CrxUpdateItem::kChecking
, CrxUpdateItem::kUpToDate
);
749 // If there are updates pending we do a short wait, otherwise we take
750 // a longer delay until we check the components again.
751 ScheduleNextRun(num_updates_pending
> 0 ? kStepDelayShort
: kStepDelayLong
);
754 void CrxUpdateService::OnUpdateCheckFailed(int error
,
755 const std::string
& error_message
) {
756 DCHECK(thread_checker_
.CalledOnValidThread());
759 ChangeItemStatus(CrxUpdateItem::kChecking
, CrxUpdateItem::kNoUpdate
);
760 DCHECK_GT(count
, 0ul);
761 VLOG(1) << "Update check failed.";
762 ScheduleNextRun(kStepDelayLong
);
765 // Called when progress is being made downloading a CRX. The progress may
766 // not monotonically increase due to how the CRX downloader switches between
767 // different downloaders and fallback urls.
768 void CrxUpdateService::DownloadProgress(
769 const std::string
& component_id
,
770 const CrxDownloader::Result
& download_result
) {
771 DCHECK(thread_checker_
.CalledOnValidThread());
772 NotifyObservers(Observer::COMPONENT_UPDATE_DOWNLOADING
, component_id
);
775 // Called when the CRX package has been downloaded to a temporary location.
776 // Here we fire the notifications and schedule the component-specific installer
777 // to be called in the file thread.
778 void CrxUpdateService::DownloadComplete(
779 scoped_ptr
<CRXContext
> crx_context
,
780 const CrxDownloader::Result
& download_result
) {
781 DCHECK(thread_checker_
.CalledOnValidThread());
783 CrxUpdateItem
* crx
= FindUpdateItemById(crx_context
->id
);
784 DCHECK(crx
->status
== CrxUpdateItem::kDownloadingDiff
||
785 crx
->status
== CrxUpdateItem::kDownloading
);
787 AppendDownloadMetrics(crx_downloader_
->download_metrics(),
788 &crx
->download_metrics
);
790 crx_downloader_
.reset();
792 if (download_result
.error
) {
793 if (crx
->status
== CrxUpdateItem::kDownloadingDiff
) {
794 crx
->diff_error_category
= kNetworkError
;
795 crx
->diff_error_code
= download_result
.error
;
796 crx
->diff_update_failed
= true;
797 size_t count
= ChangeItemStatus(CrxUpdateItem::kDownloadingDiff
,
798 CrxUpdateItem::kCanUpdate
);
799 DCHECK_EQ(count
, 1ul);
801 ScheduleNextRun(kStepDelayShort
);
804 crx
->error_category
= kNetworkError
;
805 crx
->error_code
= download_result
.error
;
807 ChangeItemStatus(CrxUpdateItem::kDownloading
, CrxUpdateItem::kNoUpdate
);
808 DCHECK_EQ(count
, 1ul);
810 // At this point, since both the differential and the full downloads failed,
811 // the update for this component has finished with an error.
812 ping_manager_
->OnUpdateComplete(crx
);
814 // Move on to the next update, if there is one available.
815 ScheduleNextRun(kStepDelayMedium
);
818 if (crx
->status
== CrxUpdateItem::kDownloadingDiff
) {
819 count
= ChangeItemStatus(CrxUpdateItem::kDownloadingDiff
,
820 CrxUpdateItem::kUpdatingDiff
);
822 count
= ChangeItemStatus(CrxUpdateItem::kDownloading
,
823 CrxUpdateItem::kUpdating
);
825 DCHECK_EQ(count
, 1ul);
827 // Why unretained? See comment at top of file.
828 blocking_task_runner_
->PostDelayedTask(
830 base::Bind(&CrxUpdateService::Install
,
831 base::Unretained(this),
832 base::Passed(&crx_context
),
833 download_result
.response
),
834 base::TimeDelta::FromMilliseconds(config_
->StepDelay()));
838 // Install consists of digital signature verification, unpacking and then
839 // calling the component specific installer. All that is handled by the
840 // |unpacker_|. If there is an error this function is in charge of deleting
841 // the files created.
842 void CrxUpdateService::Install(scoped_ptr
<CRXContext
> context
,
843 const base::FilePath
& crx_path
) {
844 // This function owns the file at |crx_path| and the |context| object.
845 unpacker_
= new ComponentUnpacker(context
->pk_hash
,
847 context
->fingerprint
,
849 config_
->CreateOutOfProcessPatcher(),
850 blocking_task_runner_
);
851 unpacker_
->Unpack(base::Bind(&CrxUpdateService::EndUnpacking
,
852 base::Unretained(this),
857 void CrxUpdateService::EndUnpacking(const std::string
& component_id
,
858 const base::FilePath
& crx_path
,
859 ComponentUnpacker::Error error
,
860 int extended_error
) {
861 if (!update_client::DeleteFileAndEmptyParentDirectory(crx_path
))
862 NOTREACHED() << crx_path
.value();
863 main_task_runner_
->PostDelayedTask(
865 base::Bind(&CrxUpdateService::DoneInstalling
,
866 base::Unretained(this),
870 base::TimeDelta::FromMilliseconds(config_
->StepDelay()));
871 // Reset the unpacker last, otherwise we free our own arguments.
875 // Installation has been completed. Adjust the component status and
876 // schedule the next check. Schedule a short delay before trying the full
877 // update when the differential update failed.
878 void CrxUpdateService::DoneInstalling(const std::string
& component_id
,
879 ComponentUnpacker::Error error
,
881 DCHECK(thread_checker_
.CalledOnValidThread());
883 ErrorCategory error_category
= kErrorNone
;
885 case ComponentUnpacker::kNone
:
887 case ComponentUnpacker::kInstallerError
:
888 error_category
= kInstallError
;
891 error_category
= kUnpackError
;
895 const bool is_success
= error
== ComponentUnpacker::kNone
;
897 CrxUpdateItem
* item
= FindUpdateItemById(component_id
);
898 if (item
->status
== CrxUpdateItem::kUpdatingDiff
&& !is_success
) {
899 item
->diff_error_category
= error_category
;
900 item
->diff_error_code
= error
;
901 item
->diff_extra_code1
= extra_code
;
902 item
->diff_update_failed
= true;
903 size_t count
= ChangeItemStatus(CrxUpdateItem::kUpdatingDiff
,
904 CrxUpdateItem::kCanUpdate
);
905 DCHECK_EQ(count
, 1ul);
906 ScheduleNextRun(kStepDelayShort
);
911 item
->component
.version
= item
->next_version
;
912 item
->component
.fingerprint
= item
->next_fp
;
913 ChangeItemState(item
, CrxUpdateItem::kUpdated
);
915 item
->error_category
= error_category
;
916 item
->error_code
= error
;
917 item
->extra_code1
= extra_code
;
918 ChangeItemState(item
, CrxUpdateItem::kNoUpdate
);
921 ping_manager_
->OnUpdateComplete(item
);
923 // Move on to the next update, if there is one available.
924 ScheduleNextRun(kStepDelayMedium
);
927 void CrxUpdateService::NotifyObservers(Observer::Events event
,
928 const std::string
& id
) {
929 DCHECK(thread_checker_
.CalledOnValidThread());
930 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnEvent(event
, id
));
933 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdateWithCooldown(
934 CrxUpdateItem
* uit
) {
938 // Check if the request is too soon.
939 base::TimeDelta delta
= base::Time::Now() - uit
->last_check
;
940 if (delta
< base::TimeDelta::FromSeconds(config_
->OnDemandDelay()))
943 return OnDemandUpdateInternal(uit
);
946 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdateInternal(
947 CrxUpdateItem
* uit
) {
951 uit
->on_demand
= true;
953 // If there is an update available for this item, then continue processing
954 // the update. This is an artifact of how update checks are done: in addition
955 // to the on-demand item, the update check may include other items as well.
956 if (uit
->status
!= CrxUpdateItem::kCanUpdate
) {
957 Status service_status
= GetServiceStatus(uit
->status
);
958 // If the item is already in the process of being updated, there is
959 // no point in this call, so return kInProgress.
960 if (service_status
== kInProgress
)
961 return service_status
;
963 // Otherwise the item was already checked a while back (or it is new),
964 // set its status to kNew to give it a slightly higher priority.
965 ChangeItemState(uit
, CrxUpdateItem::kNew
);
968 // In case the current delay is long, set the timer to a shorter value
969 // to get the ball rolling.
970 if (timer_
.IsRunning()) {
972 timer_
.Start(FROM_HERE
,
973 base::TimeDelta::FromSeconds(config_
->StepDelay()),
975 &CrxUpdateService::ProcessPendingItems
);
981 ComponentUpdateService::Status
CrxUpdateService::GetServiceStatus(
982 CrxUpdateItem::Status status
) {
984 case CrxUpdateItem::kChecking
:
985 case CrxUpdateItem::kCanUpdate
:
986 case CrxUpdateItem::kDownloadingDiff
:
987 case CrxUpdateItem::kDownloading
:
988 case CrxUpdateItem::kUpdatingDiff
:
989 case CrxUpdateItem::kUpdating
:
991 case CrxUpdateItem::kNew
:
992 case CrxUpdateItem::kUpdated
:
993 case CrxUpdateItem::kUpToDate
:
994 case CrxUpdateItem::kNoUpdate
:
996 case CrxUpdateItem::kLastStatus
:
997 NOTREACHED() << status
;
1002 ///////////////////////////////////////////////////////////////////////////////
1004 // The component update factory. Using the component updater as a singleton
1005 // is the job of the browser process.
1006 ComponentUpdateService
* ComponentUpdateServiceFactory(Configurator
* config
) {
1008 return new CrxUpdateService(config
);
1011 } // namespace component_updater