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 Status
UnregisterComponent(const std::string
& crx_id
) override
;
104 std::vector
<std::string
> GetComponentIDs() const override
;
105 OnDemandUpdater
& GetOnDemandUpdater() override
;
106 void MaybeThrottle(const std::string
& crx_id
,
107 const base::Closure
& callback
) override
;
108 scoped_refptr
<base::SequencedTaskRunner
> GetSequencedTaskRunner() override
;
110 // Context for a crx download url request.
112 scoped_refptr
<ComponentInstaller
> installer
;
113 std::vector
<uint8_t> pk_hash
;
115 std::string fingerprint
;
116 CRXContext() : installer(NULL
) {}
127 enum StepDelayInterval
{
133 // Overrides for ComponentUpdateService.
134 bool GetComponentDetails(const std::string
& component_id
,
135 CrxUpdateItem
* item
) const override
;
137 // Overrides for OnDemandUpdater.
138 Status
OnDemandUpdate(const std::string
& component_id
) override
;
140 void UpdateCheckComplete(const GURL
& original_url
,
142 const std::string
& error_message
,
143 const UpdateResponse::Results
& results
);
144 void OnUpdateCheckSucceeded(const UpdateResponse::Results
& results
);
145 void OnUpdateCheckFailed(int error
, const std::string
& error_message
);
147 void DownloadProgress(const std::string
& component_id
,
148 const CrxDownloader::Result
& download_result
);
150 void DownloadComplete(scoped_ptr
<CRXContext
> crx_context
,
151 const CrxDownloader::Result
& download_result
);
153 Status
OnDemandUpdateInternal(CrxUpdateItem
* item
);
154 Status
OnDemandUpdateWithCooldown(CrxUpdateItem
* item
);
156 void ProcessPendingItems();
158 // Uninstall and remove all unregistered work items.
159 void UninstallUnregisteredItems();
161 // Find a component that is ready to update.
162 CrxUpdateItem
* FindReadyComponent() const;
164 // Prepares the components for an update check and initiates the request.
165 // Returns true if an update check request has been made. Returns false if
166 // no update check was needed or an error occured.
167 bool CheckForUpdates();
169 void UpdateComponent(CrxUpdateItem
* workitem
);
171 void ScheduleNextRun(StepDelayInterval step_delay
);
173 void ParseResponse(const std::string
& xml
);
175 void Install(scoped_ptr
<CRXContext
> context
, const base::FilePath
& crx_path
);
177 void EndUnpacking(const std::string
& component_id
,
178 const base::FilePath
& crx_path
,
179 ComponentUnpacker::Error error
,
182 void DoneInstalling(const std::string
& component_id
,
183 ComponentUnpacker::Error error
,
186 void ChangeItemState(CrxUpdateItem
* item
, CrxUpdateItem::Status to
);
188 size_t ChangeItemStatus(CrxUpdateItem::Status from
, CrxUpdateItem::Status to
);
190 CrxUpdateItem
* FindUpdateItemById(const std::string
& id
) const;
192 void NotifyObservers(Observer::Events event
, const std::string
& id
);
194 bool HasOnDemandItems() const;
196 Status
GetServiceStatus(const CrxUpdateItem::Status status
);
198 scoped_ptr
<Configurator
> config_
;
200 scoped_ptr
<UpdateChecker
> update_checker_
;
202 scoped_ptr
<PingManager
> ping_manager_
;
204 scoped_refptr
<ComponentUnpacker
> unpacker_
;
206 scoped_ptr
<CrxDownloader
> crx_downloader_
;
208 // A collection of every work item.
209 typedef std::vector
<CrxUpdateItem
*> UpdateItems
;
210 UpdateItems work_items_
;
212 base::OneShotTimer
<CrxUpdateService
> timer_
;
214 base::ThreadChecker thread_checker_
;
216 // Used to post responses back to the main thread.
217 scoped_refptr
<base::SingleThreadTaskRunner
> main_task_runner_
;
219 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner_
;
223 ObserverList
<Observer
> observer_list_
;
225 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService
);
228 //////////////////////////////////////////////////////////////////////////////
230 CrxUpdateService::CrxUpdateService(Configurator
* config
)
232 ping_manager_(new PingManager(*config
)),
233 main_task_runner_(base::MessageLoopProxy::current()),
234 blocking_task_runner_(config
->GetSequencedTaskRunner()),
238 CrxUpdateService::~CrxUpdateService() {
239 // Because we are a singleton, at this point only the main thread should be
240 // alive, this simplifies the management of the work that could be in
241 // flight in other threads.
243 STLDeleteElements(&work_items_
);
246 void CrxUpdateService::AddObserver(Observer
* observer
) {
247 DCHECK(thread_checker_
.CalledOnValidThread());
248 observer_list_
.AddObserver(observer
);
251 void CrxUpdateService::RemoveObserver(Observer
* observer
) {
252 DCHECK(thread_checker_
.CalledOnValidThread());
253 observer_list_
.RemoveObserver(observer
);
256 ComponentUpdateService::Status
CrxUpdateService::Start() {
257 // Note that RegisterComponent will call Start() when the first
258 // component is registered, so it can be called twice. This way
259 // we avoid scheduling the timer if there is no work to do.
260 VLOG(1) << "CrxUpdateService starting up";
262 if (work_items_
.empty())
265 NotifyObservers(Observer::COMPONENT_UPDATER_STARTED
, "");
267 VLOG(1) << "First update attempt will take place in "
268 << config_
->InitialDelay() << " seconds";
269 timer_
.Start(FROM_HERE
,
270 base::TimeDelta::FromSeconds(config_
->InitialDelay()),
272 &CrxUpdateService::ProcessPendingItems
);
276 // Stop the main check + update loop. In flight operations will be
278 ComponentUpdateService::Status
CrxUpdateService::Stop() {
279 VLOG(1) << "CrxUpdateService stopping";
285 bool CrxUpdateService::HasOnDemandItems() const {
288 static bool IsOnDemand(CrxUpdateItem
* item
) { return item
->on_demand
; }
290 return std::find_if(work_items_
.begin(),
292 Helper::IsOnDemand
) != work_items_
.end();
295 // This function sets the timer which will call ProcessPendingItems() or
296 // ProcessRequestedItem() if there is an on_demand item. There
297 // are three kinds of waits:
298 // - a short delay, when there is immediate work to be done.
299 // - a medium delay, when there are updates to be applied within the current
300 // update cycle, or there are components that are still unchecked.
301 // - a long delay when a full check/update cycle has completed for all
303 void CrxUpdateService::ScheduleNextRun(StepDelayInterval step_delay
) {
304 DCHECK(thread_checker_
.CalledOnValidThread());
305 DCHECK(!update_checker_
);
306 CHECK(!timer_
.IsRunning());
307 // It could be the case that Stop() had been called while a url request
308 // or unpacking was in flight, if so we arrive here but |running_| is
309 // false. In that case do not loop again.
313 // Keep the delay short if in the middle of an update (step_delay),
314 // or there are new requested_work_items_ that have not been processed yet.
315 int64_t delay_seconds
= 0;
316 if (!HasOnDemandItems()) {
317 switch (step_delay
) {
318 case kStepDelayShort
:
319 delay_seconds
= config_
->StepDelay();
321 case kStepDelayMedium
:
322 delay_seconds
= config_
->StepDelayMedium();
325 delay_seconds
= config_
->NextCheckDelay();
329 delay_seconds
= config_
->StepDelay();
332 if (step_delay
!= kStepDelayShort
) {
333 NotifyObservers(Observer::COMPONENT_UPDATER_SLEEPING
, "");
335 // Zero is only used for unit tests.
336 if (0 == delay_seconds
)
340 VLOG(1) << "Scheduling next run to occur in " << delay_seconds
<< " seconds";
341 timer_
.Start(FROM_HERE
,
342 base::TimeDelta::FromSeconds(delay_seconds
),
344 &CrxUpdateService::ProcessPendingItems
);
347 // Given a extension-like component id, find the associated component.
348 CrxUpdateItem
* CrxUpdateService::FindUpdateItemById(
349 const std::string
& id
) const {
350 DCHECK(thread_checker_
.CalledOnValidThread());
351 CrxUpdateItem::FindById
finder(id
);
352 UpdateItems::const_iterator it
=
353 std::find_if(work_items_
.begin(), work_items_
.end(), finder
);
354 return it
!= work_items_
.end() ? *it
: NULL
;
357 // Changes a component's status, clearing on_demand and firing notifications as
358 // necessary. By convention, this is the only function that can change a
359 // CrxUpdateItem's |status|.
360 // TODO(waffles): Do we want to add DCHECKS for valid state transitions here?
361 void CrxUpdateService::ChangeItemState(CrxUpdateItem
* item
,
362 CrxUpdateItem::Status to
) {
363 DCHECK(thread_checker_
.CalledOnValidThread());
364 if (to
== CrxUpdateItem::kNoUpdate
|| to
== CrxUpdateItem::kUpdated
||
365 to
== CrxUpdateItem::kUpToDate
) {
366 item
->on_demand
= false;
372 case CrxUpdateItem::kCanUpdate
:
373 NotifyObservers(Observer::COMPONENT_UPDATE_FOUND
, item
->id
);
375 case CrxUpdateItem::kUpdatingDiff
:
376 case CrxUpdateItem::kUpdating
:
377 NotifyObservers(Observer::COMPONENT_UPDATE_READY
, item
->id
);
379 case CrxUpdateItem::kUpdated
:
380 NotifyObservers(Observer::COMPONENT_UPDATED
, item
->id
);
382 case CrxUpdateItem::kUpToDate
:
383 case CrxUpdateItem::kNoUpdate
:
384 NotifyObservers(Observer::COMPONENT_NOT_UPDATED
, item
->id
);
386 case CrxUpdateItem::kNew
:
387 case CrxUpdateItem::kChecking
:
388 case CrxUpdateItem::kDownloading
:
389 case CrxUpdateItem::kDownloadingDiff
:
390 case CrxUpdateItem::kLastStatus
:
391 // No notification for these states.
395 // Free possible pending network requests.
396 if ((to
== CrxUpdateItem::kUpdated
) || (to
== CrxUpdateItem::kUpToDate
) ||
397 (to
== CrxUpdateItem::kNoUpdate
)) {
398 for (std::vector
<base::Closure
>::iterator it
=
399 item
->ready_callbacks
.begin();
400 it
!= item
->ready_callbacks
.end();
404 item
->ready_callbacks
.clear();
408 // Changes all the components in |work_items_| that have |from| status to
409 // |to| status and returns how many have been changed.
410 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from
,
411 CrxUpdateItem::Status to
) {
412 DCHECK(thread_checker_
.CalledOnValidThread());
414 for (UpdateItems::iterator it
= work_items_
.begin();
415 it
!= work_items_
.end();
417 CrxUpdateItem
* item
= *it
;
418 if (item
->status
== from
) {
419 ChangeItemState(item
, to
);
426 // Adds a component to be checked for upgrades. If the component exists it
427 // it will be replaced and the return code is kReplaced.
428 ComponentUpdateService::Status
CrxUpdateService::RegisterComponent(
429 const CrxComponent
& component
) {
430 DCHECK(thread_checker_
.CalledOnValidThread());
431 if (component
.pk_hash
.empty() || !component
.version
.IsValid() ||
432 !component
.installer
)
435 std::string
id(GetCrxComponentID(component
));
436 CrxUpdateItem
* uit
= FindUpdateItemById(id
);
438 uit
->component
= component
;
439 uit
->unregistered
= false;
443 uit
= new CrxUpdateItem
;
445 uit
->component
= component
;
447 work_items_
.push_back(uit
);
449 // If this is the first component registered we call Start to
450 // schedule the first timer. Otherwise, reset the timer to trigger another
451 // pass over the work items, if the component updater is sleeping, fact
452 // indicated by a running timer. If the timer is not running, it means that
453 // the service is busy updating something, and in that case, this component
454 // will be picked up at the next pass.
456 if (work_items_
.size() == 1) {
458 } else if (timer_
.IsRunning()) {
459 timer_
.Start(FROM_HERE
,
460 base::TimeDelta::FromSeconds(config_
->InitialDelay()),
462 &CrxUpdateService::ProcessPendingItems
);
469 ComponentUpdateService::Status
CrxUpdateService::UnregisterComponent(
470 const std::string
& crx_id
) {
471 auto it
= std::find_if(work_items_
.begin(), work_items_
.end(),
472 CrxUpdateItem::FindById(crx_id
));
473 if (it
== work_items_
.end())
476 (*it
)->unregistered
= true;
478 ScheduleNextRun(kStepDelayShort
);
482 std::vector
<std::string
> CrxUpdateService::GetComponentIDs() const {
483 DCHECK(thread_checker_
.CalledOnValidThread());
484 std::vector
<std::string
> component_ids
;
485 for (UpdateItems::const_iterator it
= work_items_
.begin();
486 it
!= work_items_
.end();
488 const CrxUpdateItem
* item
= *it
;
489 component_ids
.push_back(item
->id
);
491 return component_ids
;
494 OnDemandUpdater
& CrxUpdateService::GetOnDemandUpdater() {
498 void CrxUpdateService::MaybeThrottle(const std::string
& crx_id
,
499 const base::Closure
& callback
) {
500 DCHECK(thread_checker_
.CalledOnValidThread());
501 // Check if we can on-demand update, else unblock the request anyway.
502 CrxUpdateItem
* item
= FindUpdateItemById(crx_id
);
503 Status status
= OnDemandUpdateWithCooldown(item
);
504 if (status
== kOk
|| status
== kInProgress
) {
505 item
->ready_callbacks
.push_back(callback
);
511 scoped_refptr
<base::SequencedTaskRunner
>
512 CrxUpdateService::GetSequencedTaskRunner() {
513 return blocking_task_runner_
;
516 bool CrxUpdateService::GetComponentDetails(const std::string
& component_id
,
517 CrxUpdateItem
* item
) const {
518 DCHECK(thread_checker_
.CalledOnValidThread());
519 const CrxUpdateItem
* crx_update_item(FindUpdateItemById(component_id
));
521 *item
= *crx_update_item
;
522 return crx_update_item
!= NULL
;
525 // Start the process of checking for an update, for a particular component
526 // that was previously registered.
527 // |component_id| is a value returned from GetCrxComponentID().
528 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdate(
529 const std::string
& component_id
) {
530 return OnDemandUpdateInternal(FindUpdateItemById(component_id
));
533 // This is the main loop of the component updater. It updates one component
534 // at a time if updates are available. Otherwise, it does an update check or
535 // takes a long sleep until the loop runs again.
536 void CrxUpdateService::ProcessPendingItems() {
537 DCHECK(thread_checker_
.CalledOnValidThread());
539 CrxUpdateItem
* ready_upgrade
= FindReadyComponent();
541 UpdateComponent(ready_upgrade
);
545 UninstallUnregisteredItems();
547 if (!CheckForUpdates())
548 ScheduleNextRun(kStepDelayLong
);
551 void CrxUpdateService::UninstallUnregisteredItems() {
552 std::vector
<CrxUpdateItem
*> new_work_items
;
553 for (CrxUpdateItem
* item
: work_items_
) {
554 scoped_ptr
<CrxUpdateItem
> owned_item(item
);
555 if (owned_item
->unregistered
) {
556 const bool success
= owned_item
->component
.installer
->Uninstall();
559 new_work_items
.push_back(owned_item
.release());
562 new_work_items
.swap(work_items_
);
565 CrxUpdateItem
* CrxUpdateService::FindReadyComponent() const {
568 static bool IsReadyOnDemand(CrxUpdateItem
* item
) {
569 return item
->on_demand
&& IsReady(item
);
571 static bool IsReady(CrxUpdateItem
* item
) {
572 return item
->status
== CrxUpdateItem::kCanUpdate
;
576 std::vector
<CrxUpdateItem
*>::const_iterator it
= std::find_if(
577 work_items_
.begin(), work_items_
.end(), Helper::IsReadyOnDemand
);
578 if (it
!= work_items_
.end())
580 it
= std::find_if(work_items_
.begin(), work_items_
.end(), Helper::IsReady
);
581 if (it
!= work_items_
.end())
586 // Prepares the components for an update check and initiates the request.
587 // On demand components are always included in the update check request.
588 // Otherwise, only include components that have not been checked recently.
589 bool CrxUpdateService::CheckForUpdates() {
590 const base::TimeDelta minimum_recheck_wait_time
=
591 base::TimeDelta::FromSeconds(config_
->MinimumReCheckWait());
592 const base::Time
now(base::Time::Now());
594 std::vector
<CrxUpdateItem
*> items_to_check
;
595 for (size_t i
= 0; i
!= work_items_
.size(); ++i
) {
596 CrxUpdateItem
* item
= work_items_
[i
];
597 DCHECK(item
->status
== CrxUpdateItem::kNew
||
598 item
->status
== CrxUpdateItem::kNoUpdate
||
599 item
->status
== CrxUpdateItem::kUpToDate
||
600 item
->status
== CrxUpdateItem::kUpdated
);
602 const base::TimeDelta
time_since_last_checked(now
- item
->last_check
);
604 if (!item
->on_demand
&&
605 time_since_last_checked
< minimum_recheck_wait_time
) {
606 VLOG(1) << "Skipping check for component update: id=" << item
->id
607 << ", time_since_last_checked="
608 << time_since_last_checked
.InSeconds()
609 << " seconds: too soon to check for an update";
613 VLOG(1) << "Scheduling update check for component id=" << item
->id
614 << ", time_since_last_checked="
615 << time_since_last_checked
.InSeconds() << " seconds";
617 item
->last_check
= now
;
618 item
->crx_urls
.clear();
619 item
->crx_diffurls
.clear();
620 item
->previous_version
= item
->component
.version
;
621 item
->next_version
= Version();
622 item
->previous_fp
= item
->component
.fingerprint
;
623 item
->next_fp
.clear();
624 item
->diff_update_failed
= false;
625 item
->error_category
= 0;
626 item
->error_code
= 0;
627 item
->extra_code1
= 0;
628 item
->diff_error_category
= 0;
629 item
->diff_error_code
= 0;
630 item
->diff_extra_code1
= 0;
631 item
->download_metrics
.clear();
633 items_to_check
.push_back(item
);
635 ChangeItemState(item
, CrxUpdateItem::kChecking
);
638 if (items_to_check
.empty())
641 update_checker_
= UpdateChecker::Create(*config_
).Pass();
642 return update_checker_
->CheckForUpdates(
644 config_
->ExtraRequestParams(),
645 base::Bind(&CrxUpdateService::UpdateCheckComplete
,
646 base::Unretained(this)));
649 void CrxUpdateService::UpdateComponent(CrxUpdateItem
* workitem
) {
650 scoped_ptr
<CRXContext
> crx_context(new CRXContext
);
651 crx_context
->pk_hash
= workitem
->component
.pk_hash
;
652 crx_context
->id
= workitem
->id
;
653 crx_context
->installer
= workitem
->component
.installer
;
654 crx_context
->fingerprint
= workitem
->next_fp
;
655 const std::vector
<GURL
>* urls
= NULL
;
656 bool allow_background_download
= false;
657 if (CanTryDiffUpdate(workitem
, *config_
)) {
658 urls
= &workitem
->crx_diffurls
;
659 ChangeItemState(workitem
, CrxUpdateItem::kDownloadingDiff
);
661 // Background downloads are enabled only for selected components and
662 // only for full downloads (see issue 340448).
663 allow_background_download
= workitem
->component
.allow_background_download
;
664 urls
= &workitem
->crx_urls
;
665 ChangeItemState(workitem
, CrxUpdateItem::kDownloading
);
668 // On demand component updates are always downloaded in foreground.
669 const bool is_background_download
= !workitem
->on_demand
&&
670 allow_background_download
&&
671 config_
->UseBackgroundDownloader();
673 crx_downloader_
.reset(
674 CrxDownloader::Create(is_background_download
,
675 config_
->RequestContext(),
676 blocking_task_runner_
,
677 config_
->GetSingleThreadTaskRunner()));
678 crx_downloader_
->set_progress_callback(
679 base::Bind(&CrxUpdateService::DownloadProgress
,
680 base::Unretained(this),
682 crx_downloader_
->StartDownload(*urls
,
683 base::Bind(&CrxUpdateService::DownloadComplete
,
684 base::Unretained(this),
685 base::Passed(&crx_context
)));
688 void CrxUpdateService::UpdateCheckComplete(
689 const GURL
& original_url
,
691 const std::string
& error_message
,
692 const UpdateResponse::Results
& results
) {
693 DCHECK(thread_checker_
.CalledOnValidThread());
694 VLOG(1) << "Update check completed from: " << original_url
.spec();
695 update_checker_
.reset();
697 OnUpdateCheckSucceeded(results
);
699 OnUpdateCheckFailed(error
, error_message
);
702 // Handles a valid Omaha update check response by matching the results with
703 // the registered components which were checked for updates.
704 // If updates are found, prepare the components for the actual version upgrade.
705 // One of these components will be drafted for the upgrade next time
706 // ProcessPendingItems is called.
707 void CrxUpdateService::OnUpdateCheckSucceeded(
708 const UpdateResponse::Results
& results
) {
709 size_t num_updates_pending
= 0;
710 DCHECK(thread_checker_
.CalledOnValidThread());
711 VLOG(1) << "Update check succeeded.";
712 std::vector
<UpdateResponse::Result
>::const_iterator it
;
713 for (it
= results
.list
.begin(); it
!= results
.list
.end(); ++it
) {
714 CrxUpdateItem
* crx
= FindUpdateItemById(it
->extension_id
);
718 if (crx
->status
!= CrxUpdateItem::kChecking
) {
720 continue; // Not updating this component now.
723 if (it
->manifest
.version
.empty()) {
724 // No version means no update available.
725 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
726 VLOG(1) << "No update available for component: " << crx
->id
;
730 if (!IsVersionNewer(crx
->component
.version
, it
->manifest
.version
)) {
731 // The component is up to date.
732 ChangeItemState(crx
, CrxUpdateItem::kUpToDate
);
733 VLOG(1) << "Component already up-to-date: " << crx
->id
;
737 if (!it
->manifest
.browser_min_version
.empty()) {
738 if (IsVersionNewer(config_
->GetBrowserVersion(),
739 it
->manifest
.browser_min_version
)) {
740 // The component is not compatible with this Chrome version.
741 VLOG(1) << "Ignoring incompatible component: " << crx
->id
;
742 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
747 if (it
->manifest
.packages
.size() != 1) {
748 // Assume one and only one package per component.
749 VLOG(1) << "Ignoring multiple packages for component: " << crx
->id
;
750 ChangeItemState(crx
, CrxUpdateItem::kNoUpdate
);
754 // Parse the members of the result and queue an upgrade for this component.
755 crx
->next_version
= Version(it
->manifest
.version
);
757 VLOG(1) << "Update found for component: " << crx
->id
;
759 typedef UpdateResponse::Result::Manifest::Package Package
;
760 const Package
& package(it
->manifest
.packages
[0]);
761 crx
->next_fp
= package
.fingerprint
;
763 // Resolve the urls by combining the base urls with the package names.
764 for (size_t i
= 0; i
!= it
->crx_urls
.size(); ++i
) {
765 const GURL
url(it
->crx_urls
[i
].Resolve(package
.name
));
767 crx
->crx_urls
.push_back(url
);
769 for (size_t i
= 0; i
!= it
->crx_diffurls
.size(); ++i
) {
770 const GURL
url(it
->crx_diffurls
[i
].Resolve(package
.namediff
));
772 crx
->crx_diffurls
.push_back(url
);
775 ChangeItemState(crx
, CrxUpdateItem::kCanUpdate
);
776 ++num_updates_pending
;
779 // All components that are not included in the update response are
780 // considered up to date.
781 ChangeItemStatus(CrxUpdateItem::kChecking
, CrxUpdateItem::kUpToDate
);
783 // If there are updates pending we do a short wait, otherwise we take
784 // a longer delay until we check the components again.
785 ScheduleNextRun(num_updates_pending
> 0 ? kStepDelayShort
: kStepDelayLong
);
788 void CrxUpdateService::OnUpdateCheckFailed(int error
,
789 const std::string
& error_message
) {
790 DCHECK(thread_checker_
.CalledOnValidThread());
793 ChangeItemStatus(CrxUpdateItem::kChecking
, CrxUpdateItem::kNoUpdate
);
794 DCHECK_GT(count
, 0ul);
795 VLOG(1) << "Update check failed.";
796 ScheduleNextRun(kStepDelayLong
);
799 // Called when progress is being made downloading a CRX. The progress may
800 // not monotonically increase due to how the CRX downloader switches between
801 // different downloaders and fallback urls.
802 void CrxUpdateService::DownloadProgress(
803 const std::string
& component_id
,
804 const CrxDownloader::Result
& download_result
) {
805 DCHECK(thread_checker_
.CalledOnValidThread());
806 NotifyObservers(Observer::COMPONENT_UPDATE_DOWNLOADING
, component_id
);
809 // Called when the CRX package has been downloaded to a temporary location.
810 // Here we fire the notifications and schedule the component-specific installer
811 // to be called in the file thread.
812 void CrxUpdateService::DownloadComplete(
813 scoped_ptr
<CRXContext
> crx_context
,
814 const CrxDownloader::Result
& download_result
) {
815 DCHECK(thread_checker_
.CalledOnValidThread());
817 CrxUpdateItem
* crx
= FindUpdateItemById(crx_context
->id
);
819 DCHECK(crx
->status
== CrxUpdateItem::kDownloadingDiff
||
820 crx
->status
== CrxUpdateItem::kDownloading
);
822 AppendDownloadMetrics(crx_downloader_
->download_metrics(),
823 &crx
->download_metrics
);
825 crx_downloader_
.reset();
827 if (download_result
.error
) {
828 if (crx
->status
== CrxUpdateItem::kDownloadingDiff
) {
829 crx
->diff_error_category
= kNetworkError
;
830 crx
->diff_error_code
= download_result
.error
;
831 crx
->diff_update_failed
= true;
832 size_t count
= ChangeItemStatus(CrxUpdateItem::kDownloadingDiff
,
833 CrxUpdateItem::kCanUpdate
);
834 DCHECK_EQ(count
, 1ul);
836 ScheduleNextRun(kStepDelayShort
);
839 crx
->error_category
= kNetworkError
;
840 crx
->error_code
= download_result
.error
;
842 ChangeItemStatus(CrxUpdateItem::kDownloading
, CrxUpdateItem::kNoUpdate
);
843 DCHECK_EQ(count
, 1ul);
845 // At this point, since both the differential and the full downloads failed,
846 // the update for this component has finished with an error.
847 ping_manager_
->OnUpdateComplete(crx
);
849 // Move on to the next update, if there is one available.
850 ScheduleNextRun(kStepDelayMedium
);
853 if (crx
->status
== CrxUpdateItem::kDownloadingDiff
) {
854 count
= ChangeItemStatus(CrxUpdateItem::kDownloadingDiff
,
855 CrxUpdateItem::kUpdatingDiff
);
857 count
= ChangeItemStatus(CrxUpdateItem::kDownloading
,
858 CrxUpdateItem::kUpdating
);
860 DCHECK_EQ(count
, 1ul);
862 // Why unretained? See comment at top of file.
863 blocking_task_runner_
->PostDelayedTask(
865 base::Bind(&CrxUpdateService::Install
,
866 base::Unretained(this),
867 base::Passed(&crx_context
),
868 download_result
.response
),
869 base::TimeDelta::FromMilliseconds(config_
->StepDelay()));
873 // Install consists of digital signature verification, unpacking and then
874 // calling the component specific installer. All that is handled by the
875 // |unpacker_|. If there is an error this function is in charge of deleting
876 // the files created.
877 void CrxUpdateService::Install(scoped_ptr
<CRXContext
> context
,
878 const base::FilePath
& crx_path
) {
879 // This function owns the file at |crx_path| and the |context| object.
880 unpacker_
= new ComponentUnpacker(context
->pk_hash
,
882 context
->fingerprint
,
884 config_
->CreateOutOfProcessPatcher(),
885 blocking_task_runner_
);
886 unpacker_
->Unpack(base::Bind(&CrxUpdateService::EndUnpacking
,
887 base::Unretained(this),
892 void CrxUpdateService::EndUnpacking(const std::string
& component_id
,
893 const base::FilePath
& crx_path
,
894 ComponentUnpacker::Error error
,
895 int extended_error
) {
896 if (!update_client::DeleteFileAndEmptyParentDirectory(crx_path
))
897 NOTREACHED() << crx_path
.value();
898 main_task_runner_
->PostDelayedTask(
900 base::Bind(&CrxUpdateService::DoneInstalling
,
901 base::Unretained(this),
905 base::TimeDelta::FromMilliseconds(config_
->StepDelay()));
906 // Reset the unpacker last, otherwise we free our own arguments.
910 // Installation has been completed. Adjust the component status and
911 // schedule the next check. Schedule a short delay before trying the full
912 // update when the differential update failed.
913 void CrxUpdateService::DoneInstalling(const std::string
& component_id
,
914 ComponentUnpacker::Error error
,
916 DCHECK(thread_checker_
.CalledOnValidThread());
918 ErrorCategory error_category
= kErrorNone
;
920 case ComponentUnpacker::kNone
:
922 case ComponentUnpacker::kInstallerError
:
923 error_category
= kInstallError
;
926 error_category
= kUnpackError
;
930 const bool is_success
= error
== ComponentUnpacker::kNone
;
932 CrxUpdateItem
* item
= FindUpdateItemById(component_id
);
934 if (item
->status
== CrxUpdateItem::kUpdatingDiff
&& !is_success
) {
935 item
->diff_error_category
= error_category
;
936 item
->diff_error_code
= error
;
937 item
->diff_extra_code1
= extra_code
;
938 item
->diff_update_failed
= true;
939 size_t count
= ChangeItemStatus(CrxUpdateItem::kUpdatingDiff
,
940 CrxUpdateItem::kCanUpdate
);
941 DCHECK_EQ(count
, 1ul);
942 ScheduleNextRun(kStepDelayShort
);
947 item
->component
.version
= item
->next_version
;
948 item
->component
.fingerprint
= item
->next_fp
;
949 ChangeItemState(item
, CrxUpdateItem::kUpdated
);
951 item
->error_category
= error_category
;
952 item
->error_code
= error
;
953 item
->extra_code1
= extra_code
;
954 ChangeItemState(item
, CrxUpdateItem::kNoUpdate
);
957 ping_manager_
->OnUpdateComplete(item
);
959 // Move on to the next update, if there is one available.
960 ScheduleNextRun(kStepDelayMedium
);
963 void CrxUpdateService::NotifyObservers(Observer::Events event
,
964 const std::string
& id
) {
965 DCHECK(thread_checker_
.CalledOnValidThread());
966 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnEvent(event
, id
));
969 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdateWithCooldown(
970 CrxUpdateItem
* uit
) {
974 // Check if the request is too soon.
975 base::TimeDelta delta
= base::Time::Now() - uit
->last_check
;
976 if (delta
< base::TimeDelta::FromSeconds(config_
->OnDemandDelay()))
979 return OnDemandUpdateInternal(uit
);
982 ComponentUpdateService::Status
CrxUpdateService::OnDemandUpdateInternal(
983 CrxUpdateItem
* uit
) {
987 uit
->on_demand
= true;
989 // If there is an update available for this item, then continue processing
990 // the update. This is an artifact of how update checks are done: in addition
991 // to the on-demand item, the update check may include other items as well.
992 if (uit
->status
!= CrxUpdateItem::kCanUpdate
) {
993 Status service_status
= GetServiceStatus(uit
->status
);
994 // If the item is already in the process of being updated, there is
995 // no point in this call, so return kInProgress.
996 if (service_status
== kInProgress
)
997 return service_status
;
999 // Otherwise the item was already checked a while back (or it is new),
1000 // set its status to kNew to give it a slightly higher priority.
1001 ChangeItemState(uit
, CrxUpdateItem::kNew
);
1004 // In case the current delay is long, set the timer to a shorter value
1005 // to get the ball rolling.
1006 if (timer_
.IsRunning()) {
1008 timer_
.Start(FROM_HERE
,
1009 base::TimeDelta::FromSeconds(config_
->StepDelay()),
1011 &CrxUpdateService::ProcessPendingItems
);
1017 ComponentUpdateService::Status
CrxUpdateService::GetServiceStatus(
1018 CrxUpdateItem::Status status
) {
1020 case CrxUpdateItem::kChecking
:
1021 case CrxUpdateItem::kCanUpdate
:
1022 case CrxUpdateItem::kDownloadingDiff
:
1023 case CrxUpdateItem::kDownloading
:
1024 case CrxUpdateItem::kUpdatingDiff
:
1025 case CrxUpdateItem::kUpdating
:
1027 case CrxUpdateItem::kNew
:
1028 case CrxUpdateItem::kUpdated
:
1029 case CrxUpdateItem::kUpToDate
:
1030 case CrxUpdateItem::kNoUpdate
:
1032 case CrxUpdateItem::kLastStatus
:
1033 NOTREACHED() << status
;
1038 ///////////////////////////////////////////////////////////////////////////////
1040 // The component update factory. Using the component updater as a singleton
1041 // is the job of the browser process.
1042 ComponentUpdateService
* ComponentUpdateServiceFactory(Configurator
* config
) {
1044 return new CrxUpdateService(config
);
1047 } // namespace component_updater