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/callback.h"
14 #include "base/compiler_specific.h"
15 #include "base/file_util.h"
16 #include "base/files/file_path.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/message_loop/message_loop_proxy.h"
20 #include "base/observer_list.h"
21 #include "base/sequenced_task_runner.h"
22 #include "base/stl_util.h"
23 #include "base/threading/sequenced_worker_pool.h"
24 #include "base/threading/thread_checker.h"
25 #include "base/timer/timer.h"
26 #include "components/component_updater/component_patcher_operation.h"
27 #include "components/component_updater/component_unpacker.h"
28 #include "components/component_updater/component_updater_configurator.h"
29 #include "components/component_updater/component_updater_ping_manager.h"
30 #include "components/component_updater/component_updater_utils.h"
31 #include "components/component_updater/crx_downloader.h"
32 #include "components/component_updater/crx_update_item.h"
33 #include "components/component_updater/update_checker.h"
34 #include "components/component_updater/update_response.h"
37 namespace component_updater
{
39 // The component updater is designed to live until process shutdown, so
40 // base::Bind() calls are not refcounted.
44 // Returns true if the |proposed| version is newer than |current| version.
45 bool IsVersionNewer(const Version
& current
, const std::string
& proposed
) {
46 Version
proposed_ver(proposed
);
47 return proposed_ver
.IsValid() && current
.CompareTo(proposed_ver
) < 0;
50 // Returns true if a differential update is available, it has not failed yet,
51 // and the configuration allows it.
52 bool CanTryDiffUpdate(const CrxUpdateItem
* update_item
,
53 const Configurator
& config
) {
54 return HasDiffUpdate(update_item
) && !update_item
->diff_update_failed
&&
55 config
.DeltasEnabled();
58 void AppendDownloadMetrics(
59 const std::vector
<CrxDownloader::DownloadMetrics
>& source
,
60 std::vector
<CrxDownloader::DownloadMetrics
>* destination
) {
61 destination
->insert(destination
->end(), source
.begin(), source
.end());
66 CrxUpdateItem::CrxUpdateItem()
69 diff_update_failed(false),
73 diff_error_category(0),
78 CrxUpdateItem::~CrxUpdateItem() {
81 CrxComponent::CrxComponent()
82 : installer(NULL
), allow_background_download(true) {
85 CrxComponent::~CrxComponent() {
88 //////////////////////////////////////////////////////////////////////////////
89 // The one and only implementation of the ComponentUpdateService interface. In
90 // charge of running the show. The main method is ProcessPendingItems() which
91 // is called periodically to do the upgrades/installs or the update checks.
92 // An important consideration here is to be as "low impact" as we can to the
93 // rest of the browser, so even if we have many components registered and
94 // eligible for update, we only do one thing at a time with pauses in between
95 // the tasks. Also when we do network requests there is only one |url_fetcher_|
96 // in flight at a time.
97 // There are no locks in this code, the main structure |work_items_| is mutated
98 // only from the main thread. The unpack and installation is done in a blocking
99 // pool thread. The network requests are done in the IO thread or in the file
101 class CrxUpdateService
: public ComponentUpdateService
, public OnDemandUpdater
{
103 explicit CrxUpdateService(Configurator
* config
);
104 virtual ~CrxUpdateService();
106 // Overrides for ComponentUpdateService.
107 virtual void AddObserver(Observer
* observer
) OVERRIDE
;
108 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
;
109 virtual Status
Start() OVERRIDE
;
110 virtual Status
Stop() OVERRIDE
;
111 virtual Status
RegisterComponent(const CrxComponent
& component
) OVERRIDE
;
112 virtual std::vector
<std::string
> GetComponentIDs() const OVERRIDE
;
113 virtual OnDemandUpdater
& GetOnDemandUpdater() OVERRIDE
;
114 virtual void MaybeThrottle(const std::string
& crx_id
,
115 const base::Closure
& callback
) OVERRIDE
;
116 virtual scoped_refptr
<base::SequencedTaskRunner
> GetSequencedTaskRunner()
119 // Context for a crx download url request.
121 ComponentInstaller
* installer
;
122 std::vector
<uint8
> pk_hash
;
124 std::string fingerprint
;
125 CRXContext() : installer(NULL
) {}
136 enum StepDelayInterval
{
142 // Overrides for ComponentUpdateService.
143 virtual bool GetComponentDetails(const std::string
& component_id
,
144 CrxUpdateItem
* item
) const OVERRIDE
;
146 // Overrides for OnDemandUpdater.
147 virtual Status
OnDemandUpdate(const std::string
& component_id
) OVERRIDE
;
149 void UpdateCheckComplete(int error
,
150 const std::string
& error_message
,
151 const UpdateResponse::Results
& results
);
152 void OnUpdateCheckSucceeded(const UpdateResponse::Results
& results
);
153 void OnUpdateCheckFailed(int error
, const std::string
& error_message
);
155 void DownloadProgress(const std::string
& component_id
,
156 const CrxDownloader::Result
& download_result
);
158 void DownloadComplete(scoped_ptr
<CRXContext
> crx_context
,
159 const CrxDownloader::Result
& download_result
);
161 Status
OnDemandUpdateInternal(CrxUpdateItem
* item
);
162 Status
OnDemandUpdateWithCooldown(CrxUpdateItem
* item
);
164 void ProcessPendingItems();
166 // Find a component that is ready to update.
167 CrxUpdateItem
* FindReadyComponent() const;
169 // Prepares the components for an update check and initiates the request.
170 // Returns true if an update check request has been made. Returns false if
171 // no update check was needed or an error occured.
172 bool CheckForUpdates();
174 void UpdateComponent(CrxUpdateItem
* workitem
);
176 void ScheduleNextRun(StepDelayInterval step_delay
);
178 void ParseResponse(const std::string
& xml
);
180 void Install(scoped_ptr
<CRXContext
> context
, const base::FilePath
& crx_path
);
182 void EndUnpacking(const std::string
& component_id
,
183 const base::FilePath
& crx_path
,
184 ComponentUnpacker::Error error
,
187 void DoneInstalling(const std::string
& component_id
,
188 ComponentUnpacker::Error error
,
191 void ChangeItemState(CrxUpdateItem
* item
, CrxUpdateItem::Status to
);
193 size_t ChangeItemStatus(CrxUpdateItem::Status from
, CrxUpdateItem::Status to
);
195 CrxUpdateItem
* FindUpdateItemById(const std::string
& id
) const;
197 void NotifyObservers(Observer::Events event
, const std::string
& id
);
199 bool HasOnDemandItems() const;
201 Status
GetServiceStatus(const CrxUpdateItem::Status status
);
203 scoped_ptr
<Configurator
> config_
;
205 scoped_ptr
<UpdateChecker
> update_checker_
;
207 scoped_ptr
<PingManager
> ping_manager_
;
209 scoped_refptr
<ComponentUnpacker
> unpacker_
;
211 scoped_ptr
<CrxDownloader
> crx_downloader_
;
213 // A collection of every work item.
214 typedef std::vector
<CrxUpdateItem
*> UpdateItems
;
215 UpdateItems work_items_
;
217 base::OneShotTimer
<CrxUpdateService
> timer_
;
219 base::ThreadChecker thread_checker_
;
221 // Used to post responses back to the main thread.
222 scoped_refptr
<base::SingleThreadTaskRunner
> main_task_runner_
;
224 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner_
;
228 ObserverList
<Observer
> observer_list_
;
230 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService
);
233 //////////////////////////////////////////////////////////////////////////////
235 CrxUpdateService::CrxUpdateService(Configurator
* config
)
237 ping_manager_(new PingManager(*config
)),
238 main_task_runner_(base::MessageLoopProxy::current()),
239 blocking_task_runner_(config
->GetSequencedTaskRunner()),
243 CrxUpdateService::~CrxUpdateService() {
244 // Because we are a singleton, at this point only the main thread should be
245 // alive, this simplifies the management of the work that could be in
246 // flight in other threads.
248 STLDeleteElements(&work_items_
);
251 void CrxUpdateService::AddObserver(Observer
* observer
) {
252 DCHECK(thread_checker_
.CalledOnValidThread());
253 observer_list_
.AddObserver(observer
);
256 void CrxUpdateService::RemoveObserver(Observer
* observer
) {
257 DCHECK(thread_checker_
.CalledOnValidThread());
258 observer_list_
.RemoveObserver(observer
);
261 ComponentUpdateService::Status
CrxUpdateService::Start() {
262 // Note that RegisterComponent will call Start() when the first
263 // component is registered, so it can be called twice. This way
264 // we avoid scheduling the timer if there is no work to do.
265 VLOG(1) << "CrxUpdateService starting up";
267 if (work_items_
.empty())
270 NotifyObservers(Observer::COMPONENT_UPDATER_STARTED
, "");
272 VLOG(1) << "First update attempt will take place in "
273 << config_
->InitialDelay() << " seconds";
274 timer_
.Start(FROM_HERE
,
275 base::TimeDelta::FromSeconds(config_
->InitialDelay()),
277 &CrxUpdateService::ProcessPendingItems
);
281 // Stop the main check + update loop. In flight operations will be
283 ComponentUpdateService::Status
CrxUpdateService::Stop() {
284 VLOG(1) << "CrxUpdateService stopping";
290 bool CrxUpdateService::HasOnDemandItems() const {
293 static bool IsOnDemand(CrxUpdateItem
* item
) { return item
->on_demand
; }
295 return std::find_if(work_items_
.begin(),
297 Helper::IsOnDemand
) != work_items_
.end();
300 // This function sets the timer which will call ProcessPendingItems() or
301 // ProcessRequestedItem() if there is an on_demand item. There
302 // are three kinds of waits:
303 // - a short delay, when there is immediate work to be done.
304 // - a medium delay, when there are updates to be applied within the current
305 // update cycle, or there are components that are still unchecked.
306 // - a long delay when a full check/update cycle has completed for all
308 void CrxUpdateService::ScheduleNextRun(StepDelayInterval step_delay
) {
309 DCHECK(thread_checker_
.CalledOnValidThread());
310 DCHECK(!update_checker_
);
311 CHECK(!timer_
.IsRunning());
312 // It could be the case that Stop() had been called while a url request
313 // or unpacking was in flight, if so we arrive here but |running_| is
314 // false. In that case do not loop again.
318 // Keep the delay short if in the middle of an update (step_delay),
319 // or there are new requested_work_items_ that have not been processed yet.
320 int64 delay_seconds
= 0;
321 if (!HasOnDemandItems()) {
322 switch (step_delay
) {
323 case kStepDelayShort
:
324 delay_seconds
= config_
->StepDelay();
326 case kStepDelayMedium
:
327 delay_seconds
= config_
->StepDelayMedium();
330 delay_seconds
= config_
->NextCheckDelay();
334 delay_seconds
= config_
->StepDelay();
337 if (step_delay
!= kStepDelayShort
) {
338 NotifyObservers(Observer::COMPONENT_UPDATER_SLEEPING
, "");
340 // Zero is only used for unit tests.
341 if (0 == delay_seconds
)
345 VLOG(1) << "Scheduling next run to occur in " << delay_seconds
<< " seconds";
346 timer_
.Start(FROM_HERE
,
347 base::TimeDelta::FromSeconds(delay_seconds
),
349 &CrxUpdateService::ProcessPendingItems
);
352 // Given a extension-like component id, find the associated component.
353 CrxUpdateItem
* CrxUpdateService::FindUpdateItemById(
354 const std::string
& id
) const {
355 DCHECK(thread_checker_
.CalledOnValidThread());
356 CrxUpdateItem::FindById
finder(id
);
357 UpdateItems::const_iterator it
=
358 std::find_if(work_items_
.begin(), work_items_
.end(), finder
);
359 return it
!= work_items_
.end() ? *it
: NULL
;
362 // Changes a component's status, clearing on_demand and firing notifications as
363 // necessary. By convention, this is the only function that can change a
364 // CrxUpdateItem's |status|.
365 // TODO(waffles): Do we want to add DCHECKS for valid state transitions here?
366 void CrxUpdateService::ChangeItemState(CrxUpdateItem
* item
,
367 CrxUpdateItem::Status to
) {
368 DCHECK(thread_checker_
.CalledOnValidThread());
369 if (to
== CrxUpdateItem::kNoUpdate
|| to
== CrxUpdateItem::kUpdated
||
370 to
== CrxUpdateItem::kUpToDate
) {
371 item
->on_demand
= false;
377 case CrxUpdateItem::kCanUpdate
:
378 NotifyObservers(Observer::COMPONENT_UPDATE_FOUND
, item
->id
);
380 case CrxUpdateItem::kUpdatingDiff
:
381 case CrxUpdateItem::kUpdating
:
382 NotifyObservers(Observer::COMPONENT_UPDATE_READY
, item
->id
);
384 case CrxUpdateItem::kUpdated
:
385 NotifyObservers(Observer::COMPONENT_UPDATED
, item
->id
);
387 case CrxUpdateItem::kUpToDate
:
388 case CrxUpdateItem::kNoUpdate
:
389 NotifyObservers(Observer::COMPONENT_NOT_UPDATED
, item
->id
);
391 case CrxUpdateItem::kNew
:
392 case CrxUpdateItem::kChecking
:
393 case CrxUpdateItem::kDownloading
:
394 case CrxUpdateItem::kDownloadingDiff
:
395 case CrxUpdateItem::kLastStatus
:
396 // No notification for these states.
400 // Free possible pending network requests.
401 if ((to
== CrxUpdateItem::kUpdated
) || (to
== CrxUpdateItem::kUpToDate
) ||
402 (to
== CrxUpdateItem::kNoUpdate
)) {
403 for (std::vector
<base::Closure
>::iterator it
=
404 item
->ready_callbacks
.begin();
405 it
!= item
->ready_callbacks
.end();
409 item
->ready_callbacks
.clear();
413 // Changes all the components in |work_items_| that have |from| status to
414 // |to| status and returns how many have been changed.
415 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from
,
416 CrxUpdateItem::Status to
) {
417 DCHECK(thread_checker_
.CalledOnValidThread());
419 for (UpdateItems::iterator it
= work_items_
.begin();
420 it
!= work_items_
.end();
422 CrxUpdateItem
* item
= *it
;
423 if (item
->status
== from
) {
424 ChangeItemState(item
, to
);
431 // Adds a component to be checked for upgrades. If the component exists it
432 // it will be replaced and the return code is kReplaced.
433 ComponentUpdateService::Status
CrxUpdateService::RegisterComponent(
434 const CrxComponent
& component
) {
435 DCHECK(thread_checker_
.CalledOnValidThread());
436 if (component
.pk_hash
.empty() || !component
.version
.IsValid() ||
437 !component
.installer
)
440 std::string
id(GetCrxComponentID(component
));
441 CrxUpdateItem
* uit
= FindUpdateItemById(id
);
443 uit
->component
= component
;
447 uit
= new CrxUpdateItem
;
449 uit
->component
= component
;
451 work_items_
.push_back(uit
);
453 // If this is the first component registered we call Start to
454 // schedule the first timer. Otherwise, reset the timer to trigger another
455 // pass over the work items, if the component updater is sleeping, fact
456 // indicated by a running timer. If the timer is not running, it means that
457 // the service is busy updating something, and in that case, this component
458 // will be picked up at the next pass.
460 if (work_items_
.size() == 1) {
462 } else if (timer_
.IsRunning()) {
463 timer_
.Start(FROM_HERE
,
464 base::TimeDelta::FromSeconds(config_
->InitialDelay()),
466 &CrxUpdateService::ProcessPendingItems
);
473 std::vector
<std::string
> CrxUpdateService::GetComponentIDs() const {
474 DCHECK(thread_checker_
.CalledOnValidThread());
475 std::vector
<std::string
> component_ids
;
476 for (UpdateItems::const_iterator it
= work_items_
.begin();
477 it
!= work_items_
.end();
479 const CrxUpdateItem
* item
= *it
;
480 component_ids
.push_back(item
->id
);
482 return component_ids
;
485 OnDemandUpdater
& CrxUpdateService::GetOnDemandUpdater() {
489 void CrxUpdateService::MaybeThrottle(const std::string
& crx_id
,
490 const base::Closure
& callback
) {
491 DCHECK(thread_checker_
.CalledOnValidThread());
492 // Check if we can on-demand update, else unblock the request anyway.
493 CrxUpdateItem
* item
= FindUpdateItemById(crx_id
);
494 Status status
= OnDemandUpdateWithCooldown(item
);
495 if (status
== kOk
|| status
== kInProgress
) {
496 item
->ready_callbacks
.push_back(callback
);
502 scoped_refptr
<base::SequencedTaskRunner
>
503 CrxUpdateService::GetSequencedTaskRunner() {
504 return config_
->GetSequencedTaskRunner();
507 bool CrxUpdateService::GetComponentDetails(const std::string
& component_id
,
508 CrxUpdateItem
* item
) const {
509 DCHECK(thread_checker_
.CalledOnValidThread());
510 const CrxUpdateItem
* crx_update_item(FindUpdateItemById(component_id
));
512 *item
= *crx_update_item
;
513 return crx_update_item
!= NULL
;
516 // Start the process of checking for an update, for a particular component
517 // that was previously registered.
518 // |component_id| is a value returned from GetCrxComponentID().
519 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdate(
520 const std::string
& component_id
) {
521 return OnDemandUpdateInternal(FindUpdateItemById(component_id
));
524 // This is the main loop of the component updater. It updates one component
525 // at a time if updates are available. Otherwise, it does an update check or
526 // takes a long sleep until the loop runs again.
527 void CrxUpdateService::ProcessPendingItems() {
528 DCHECK(thread_checker_
.CalledOnValidThread());
530 CrxUpdateItem
* ready_upgrade
= FindReadyComponent();
532 UpdateComponent(ready_upgrade
);
536 if (!CheckForUpdates())
537 ScheduleNextRun(kStepDelayLong
);
540 CrxUpdateItem
* CrxUpdateService::FindReadyComponent() const {
543 static bool IsReadyOnDemand(CrxUpdateItem
* item
) {
544 return item
->on_demand
&& IsReady(item
);
546 static bool IsReady(CrxUpdateItem
* item
) {
547 return item
->status
== CrxUpdateItem::kCanUpdate
;
551 std::vector
<CrxUpdateItem
*>::const_iterator it
= std::find_if(
552 work_items_
.begin(), work_items_
.end(), Helper::IsReadyOnDemand
);
553 if (it
!= work_items_
.end())
555 it
= std::find_if(work_items_
.begin(), work_items_
.end(), Helper::IsReady
);
556 if (it
!= work_items_
.end())
561 // Prepares the components for an update check and initiates the request.
562 // On demand components are always included in the update check request.
563 // Otherwise, only include components that have not been checked recently.
564 bool CrxUpdateService::CheckForUpdates() {
565 const base::TimeDelta minimum_recheck_wait_time
=
566 base::TimeDelta::FromSeconds(config_
->MinimumReCheckWait());
567 const base::Time
now(base::Time::Now());
569 std::vector
<CrxUpdateItem
*> items_to_check
;
570 for (size_t i
= 0; i
!= work_items_
.size(); ++i
) {
571 CrxUpdateItem
* item
= work_items_
[i
];
572 DCHECK(item
->status
== CrxUpdateItem::kNew
||
573 item
->status
== CrxUpdateItem::kNoUpdate
||
574 item
->status
== CrxUpdateItem::kUpToDate
||
575 item
->status
== CrxUpdateItem::kUpdated
);
577 const base::TimeDelta
time_since_last_checked(now
- item
->last_check
);
579 if (!item
->on_demand
&&
580 time_since_last_checked
< minimum_recheck_wait_time
) {
581 VLOG(1) << "Skipping check for component update: id=" << item
->id
582 << ", time_since_last_checked="
583 << time_since_last_checked
.InSeconds()
584 << " seconds: too soon to check for an update";
588 VLOG(1) << "Scheduling update check for component id=" << item
->id
589 << ", time_since_last_checked="
590 << time_since_last_checked
.InSeconds() << " seconds";
592 item
->last_check
= now
;
593 item
->crx_urls
.clear();
594 item
->crx_diffurls
.clear();
595 item
->previous_version
= item
->component
.version
;
596 item
->next_version
= Version();
597 item
->previous_fp
= item
->component
.fingerprint
;
598 item
->next_fp
.clear();
599 item
->diff_update_failed
= false;
600 item
->error_category
= 0;
601 item
->error_code
= 0;
602 item
->extra_code1
= 0;
603 item
->diff_error_category
= 0;
604 item
->diff_error_code
= 0;
605 item
->diff_extra_code1
= 0;
606 item
->download_metrics
.clear();
608 items_to_check
.push_back(item
);
610 ChangeItemState(item
, CrxUpdateItem::kChecking
);
613 if (items_to_check
.empty())
617 UpdateChecker::Create(*config_
,
618 base::Bind(&CrxUpdateService::UpdateCheckComplete
,
619 base::Unretained(this))).Pass();
620 return update_checker_
->CheckForUpdates(items_to_check
,
621 config_
->ExtraRequestParams());
624 void CrxUpdateService::UpdateComponent(CrxUpdateItem
* workitem
) {
625 scoped_ptr
<CRXContext
> crx_context(new CRXContext
);
626 crx_context
->pk_hash
= workitem
->component
.pk_hash
;
627 crx_context
->id
= workitem
->id
;
628 crx_context
->installer
= workitem
->component
.installer
;
629 crx_context
->fingerprint
= workitem
->next_fp
;
630 const std::vector
<GURL
>* urls
= NULL
;
631 bool allow_background_download
= false;
632 if (CanTryDiffUpdate(workitem
, *config_
)) {
633 urls
= &workitem
->crx_diffurls
;
634 ChangeItemState(workitem
, CrxUpdateItem::kDownloadingDiff
);
636 // Background downloads are enabled only for selected components and
637 // only for full downloads (see issue 340448).
638 allow_background_download
= workitem
->component
.allow_background_download
;
639 urls
= &workitem
->crx_urls
;
640 ChangeItemState(workitem
, CrxUpdateItem::kDownloading
);
643 // On demand component updates are always downloaded in foreground.
644 const bool is_background_download
= !workitem
->on_demand
&&
645 allow_background_download
&&
646 config_
->UseBackgroundDownloader();
648 crx_downloader_
.reset(
649 CrxDownloader::Create(is_background_download
,
650 config_
->RequestContext(),
651 blocking_task_runner_
,
652 config_
->GetSingleThreadTaskRunner()));
653 crx_downloader_
->set_progress_callback(
654 base::Bind(&CrxUpdateService::DownloadProgress
,
655 base::Unretained(this),
657 crx_downloader_
->StartDownload(*urls
,
658 base::Bind(&CrxUpdateService::DownloadComplete
,
659 base::Unretained(this),
660 base::Passed(&crx_context
)));
663 void CrxUpdateService::UpdateCheckComplete(
665 const std::string
& error_message
,
666 const UpdateResponse::Results
& results
) {
667 DCHECK(thread_checker_
.CalledOnValidThread());
668 update_checker_
.reset();
670 OnUpdateCheckSucceeded(results
);
672 OnUpdateCheckFailed(error
, error_message
);
675 // Handles a valid Omaha update check response by matching the results with
676 // the registered components which were checked for updates.
677 // If updates are found, prepare the components for the actual version upgrade.
678 // One of these components will be drafted for the upgrade next time
679 // ProcessPendingItems is called.
680 void CrxUpdateService::OnUpdateCheckSucceeded(
681 const UpdateResponse::Results
& results
) {
682 size_t num_updates_pending
= 0;
683 DCHECK(thread_checker_
.CalledOnValidThread());
684 VLOG(1) << "Update check succeeded.";
685 std::vector
<UpdateResponse::Result
>::const_iterator it
;
686 for (it
= results
.list
.begin(); it
!= results
.list
.end(); ++it
) {
687 CrxUpdateItem
* crx
= FindUpdateItemById(it
->extension_id
);
691 if (crx
->status
!= CrxUpdateItem::kChecking
) {
693 continue; // Not updating this component now.
696 if (it
->manifest
.version
.empty()) {
697 // No version means no update available.
698 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
699 VLOG(1) << "No update available for component: " << crx
->id
;
703 if (!IsVersionNewer(crx
->component
.version
, it
->manifest
.version
)) {
704 // The component is up to date.
705 ChangeItemState(crx
, CrxUpdateItem::kUpToDate
);
706 VLOG(1) << "Component already up-to-date: " << crx
->id
;
710 if (!it
->manifest
.browser_min_version
.empty()) {
711 if (IsVersionNewer(config_
->GetBrowserVersion(),
712 it
->manifest
.browser_min_version
)) {
713 // The component is not compatible with this Chrome version.
714 VLOG(1) << "Ignoring incompatible component: " << crx
->id
;
715 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
720 if (it
->manifest
.packages
.size() != 1) {
721 // Assume one and only one package per component.
722 VLOG(1) << "Ignoring multiple packages for component: " << crx
->id
;
723 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
727 // Parse the members of the result and queue an upgrade for this component.
728 crx
->next_version
= Version(it
->manifest
.version
);
730 VLOG(1) << "Update found for component: " << crx
->id
;
732 typedef UpdateResponse::Result::Manifest::Package Package
;
733 const Package
& package(it
->manifest
.packages
[0]);
734 crx
->next_fp
= package
.fingerprint
;
736 // Resolve the urls by combining the base urls with the package names.
737 for (size_t i
= 0; i
!= it
->crx_urls
.size(); ++i
) {
738 const GURL
url(it
->crx_urls
[i
].Resolve(package
.name
));
740 crx
->crx_urls
.push_back(url
);
742 for (size_t i
= 0; i
!= it
->crx_diffurls
.size(); ++i
) {
743 const GURL
url(it
->crx_diffurls
[i
].Resolve(package
.namediff
));
745 crx
->crx_diffurls
.push_back(url
);
748 ChangeItemState(crx
, CrxUpdateItem::kCanUpdate
);
749 ++num_updates_pending
;
752 // All components that are not included in the update response are
753 // considered up to date.
754 ChangeItemStatus(CrxUpdateItem::kChecking
, CrxUpdateItem::kUpToDate
);
756 // If there are updates pending we do a short wait, otherwise we take
757 // a longer delay until we check the components again.
758 ScheduleNextRun(num_updates_pending
> 0 ? kStepDelayShort
: kStepDelayLong
);
761 void CrxUpdateService::OnUpdateCheckFailed(int error
,
762 const std::string
& error_message
) {
763 DCHECK(thread_checker_
.CalledOnValidThread());
766 ChangeItemStatus(CrxUpdateItem::kChecking
, CrxUpdateItem::kNoUpdate
);
767 DCHECK_GT(count
, 0ul);
768 VLOG(1) << "Update check failed.";
769 ScheduleNextRun(kStepDelayLong
);
772 // Called when progress is being made downloading a CRX. The progress may
773 // not monotonically increase due to how the CRX downloader switches between
774 // different downloaders and fallback urls.
775 void CrxUpdateService::DownloadProgress(
776 const std::string
& component_id
,
777 const CrxDownloader::Result
& download_result
) {
778 DCHECK(thread_checker_
.CalledOnValidThread());
779 NotifyObservers(Observer::COMPONENT_UPDATE_DOWNLOADING
, component_id
);
782 // Called when the CRX package has been downloaded to a temporary location.
783 // Here we fire the notifications and schedule the component-specific installer
784 // to be called in the file thread.
785 void CrxUpdateService::DownloadComplete(
786 scoped_ptr
<CRXContext
> crx_context
,
787 const CrxDownloader::Result
& download_result
) {
788 DCHECK(thread_checker_
.CalledOnValidThread());
790 CrxUpdateItem
* crx
= FindUpdateItemById(crx_context
->id
);
791 DCHECK(crx
->status
== CrxUpdateItem::kDownloadingDiff
||
792 crx
->status
== CrxUpdateItem::kDownloading
);
794 AppendDownloadMetrics(crx_downloader_
->download_metrics(),
795 &crx
->download_metrics
);
797 crx_downloader_
.reset();
799 if (download_result
.error
) {
800 if (crx
->status
== CrxUpdateItem::kDownloadingDiff
) {
801 crx
->diff_error_category
= kNetworkError
;
802 crx
->diff_error_code
= download_result
.error
;
803 crx
->diff_update_failed
= true;
804 size_t count
= ChangeItemStatus(CrxUpdateItem::kDownloadingDiff
,
805 CrxUpdateItem::kCanUpdate
);
806 DCHECK_EQ(count
, 1ul);
808 ScheduleNextRun(kStepDelayShort
);
811 crx
->error_category
= kNetworkError
;
812 crx
->error_code
= download_result
.error
;
814 ChangeItemStatus(CrxUpdateItem::kDownloading
, CrxUpdateItem::kNoUpdate
);
815 DCHECK_EQ(count
, 1ul);
817 // At this point, since both the differential and the full downloads failed,
818 // the update for this component has finished with an error.
819 ping_manager_
->OnUpdateComplete(crx
);
821 // Move on to the next update, if there is one available.
822 ScheduleNextRun(kStepDelayMedium
);
825 if (crx
->status
== CrxUpdateItem::kDownloadingDiff
) {
826 count
= ChangeItemStatus(CrxUpdateItem::kDownloadingDiff
,
827 CrxUpdateItem::kUpdatingDiff
);
829 count
= ChangeItemStatus(CrxUpdateItem::kDownloading
,
830 CrxUpdateItem::kUpdating
);
832 DCHECK_EQ(count
, 1ul);
834 // Why unretained? See comment at top of file.
835 blocking_task_runner_
->PostDelayedTask(
837 base::Bind(&CrxUpdateService::Install
,
838 base::Unretained(this),
839 base::Passed(&crx_context
),
840 download_result
.response
),
841 base::TimeDelta::FromMilliseconds(config_
->StepDelay()));
845 // Install consists of digital signature verification, unpacking and then
846 // calling the component specific installer. All that is handled by the
847 // |unpacker_|. If there is an error this function is in charge of deleting
848 // the files created.
849 void CrxUpdateService::Install(scoped_ptr
<CRXContext
> context
,
850 const base::FilePath
& crx_path
) {
851 // This function owns the file at |crx_path| and the |context| object.
852 unpacker_
= new ComponentUnpacker(context
->pk_hash
,
854 context
->fingerprint
,
856 config_
->CreateOutOfProcessPatcher(),
857 blocking_task_runner_
);
858 unpacker_
->Unpack(base::Bind(&CrxUpdateService::EndUnpacking
,
859 base::Unretained(this),
864 void CrxUpdateService::EndUnpacking(const std::string
& component_id
,
865 const base::FilePath
& crx_path
,
866 ComponentUnpacker::Error error
,
867 int extended_error
) {
868 if (!DeleteFileAndEmptyParentDirectory(crx_path
))
869 NOTREACHED() << crx_path
.value();
870 main_task_runner_
->PostDelayedTask(
872 base::Bind(&CrxUpdateService::DoneInstalling
,
873 base::Unretained(this),
877 base::TimeDelta::FromMilliseconds(config_
->StepDelay()));
878 // Reset the unpacker last, otherwise we free our own arguments.
882 // Installation has been completed. Adjust the component status and
883 // schedule the next check. Schedule a short delay before trying the full
884 // update when the differential update failed.
885 void CrxUpdateService::DoneInstalling(const std::string
& component_id
,
886 ComponentUnpacker::Error error
,
888 DCHECK(thread_checker_
.CalledOnValidThread());
890 ErrorCategory error_category
= kErrorNone
;
892 case ComponentUnpacker::kNone
:
894 case ComponentUnpacker::kInstallerError
:
895 error_category
= kInstallError
;
898 error_category
= kUnpackError
;
902 const bool is_success
= error
== ComponentUnpacker::kNone
;
904 CrxUpdateItem
* item
= FindUpdateItemById(component_id
);
905 if (item
->status
== CrxUpdateItem::kUpdatingDiff
&& !is_success
) {
906 item
->diff_error_category
= error_category
;
907 item
->diff_error_code
= error
;
908 item
->diff_extra_code1
= extra_code
;
909 item
->diff_update_failed
= true;
910 size_t count
= ChangeItemStatus(CrxUpdateItem::kUpdatingDiff
,
911 CrxUpdateItem::kCanUpdate
);
912 DCHECK_EQ(count
, 1ul);
913 ScheduleNextRun(kStepDelayShort
);
918 item
->component
.version
= item
->next_version
;
919 item
->component
.fingerprint
= item
->next_fp
;
920 ChangeItemState(item
, CrxUpdateItem::kUpdated
);
922 item
->error_category
= error_category
;
923 item
->error_code
= error
;
924 item
->extra_code1
= extra_code
;
925 ChangeItemState(item
, CrxUpdateItem::kNoUpdate
);
928 ping_manager_
->OnUpdateComplete(item
);
930 // Move on to the next update, if there is one available.
931 ScheduleNextRun(kStepDelayMedium
);
934 void CrxUpdateService::NotifyObservers(Observer::Events event
,
935 const std::string
& id
) {
936 DCHECK(thread_checker_
.CalledOnValidThread());
937 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnEvent(event
, id
));
940 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdateWithCooldown(
941 CrxUpdateItem
* uit
) {
945 // Check if the request is too soon.
946 base::TimeDelta delta
= base::Time::Now() - uit
->last_check
;
947 if (delta
< base::TimeDelta::FromSeconds(config_
->OnDemandDelay()))
950 return OnDemandUpdateInternal(uit
);
953 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdateInternal(
954 CrxUpdateItem
* uit
) {
958 uit
->on_demand
= true;
960 // If there is an update available for this item, then continue processing
961 // the update. This is an artifact of how update checks are done: in addition
962 // to the on-demand item, the update check may include other items as well.
963 if (uit
->status
!= CrxUpdateItem::kCanUpdate
) {
964 Status service_status
= GetServiceStatus(uit
->status
);
965 // If the item is already in the process of being updated, there is
966 // no point in this call, so return kInProgress.
967 if (service_status
== kInProgress
)
968 return service_status
;
970 // Otherwise the item was already checked a while back (or it is new),
971 // set its status to kNew to give it a slightly higher priority.
972 ChangeItemState(uit
, CrxUpdateItem::kNew
);
975 // In case the current delay is long, set the timer to a shorter value
976 // to get the ball rolling.
977 if (timer_
.IsRunning()) {
979 timer_
.Start(FROM_HERE
,
980 base::TimeDelta::FromSeconds(config_
->StepDelay()),
982 &CrxUpdateService::ProcessPendingItems
);
988 ComponentUpdateService::Status
CrxUpdateService::GetServiceStatus(
989 CrxUpdateItem::Status status
) {
991 case CrxUpdateItem::kChecking
:
992 case CrxUpdateItem::kCanUpdate
:
993 case CrxUpdateItem::kDownloadingDiff
:
994 case CrxUpdateItem::kDownloading
:
995 case CrxUpdateItem::kUpdatingDiff
:
996 case CrxUpdateItem::kUpdating
:
998 case CrxUpdateItem::kNew
:
999 case CrxUpdateItem::kUpdated
:
1000 case CrxUpdateItem::kUpToDate
:
1001 case CrxUpdateItem::kNoUpdate
:
1003 case CrxUpdateItem::kLastStatus
:
1004 NOTREACHED() << status
;
1009 ///////////////////////////////////////////////////////////////////////////////
1011 // The component update factory. Using the component updater as a singleton
1012 // is the job of the browser process.
1013 ComponentUpdateService
* ComponentUpdateServiceFactory(Configurator
* config
) {
1015 return new CrxUpdateService(config
);
1018 } // namespace component_updater