1 // Copyright 2015 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/update_client/action.h"
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11 #include "base/location.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/update_client/action_update.h"
16 #include "components/update_client/action_wait.h"
17 #include "components/update_client/configurator.h"
18 #include "components/update_client/update_engine.h"
19 #include "components/update_client/utils.h"
21 namespace update_client
{
25 // Returns true if a differential update is available, it has not failed yet,
26 // and the configuration allows this update.
27 bool CanTryDiffUpdate(const CrxUpdateItem
* update_item
,
28 const scoped_refptr
<Configurator
>& config
) {
29 return HasDiffUpdate(update_item
) && !update_item
->diff_update_failed
&&
30 config
->DeltasEnabled();
35 ActionImpl::ActionImpl() : update_context_(nullptr) {
38 ActionImpl::~ActionImpl() {
39 DCHECK(thread_checker_
.CalledOnValidThread());
42 void ActionImpl::Run(UpdateContext
* update_context
, Action::Callback callback
) {
43 DCHECK(thread_checker_
.CalledOnValidThread());
45 update_context_
= update_context
;
49 CrxUpdateItem
* ActionImpl::FindUpdateItemById(const std::string
& id
) const {
50 DCHECK(thread_checker_
.CalledOnValidThread());
52 const auto it(std::find_if(
53 update_context_
->update_items
.begin(),
54 update_context_
->update_items
.end(),
55 [&id
](const CrxUpdateItem
* item
) { return item
->id
== id
; }));
57 return it
!= update_context_
->update_items
.end() ? *it
: nullptr;
60 void ActionImpl::ChangeItemState(CrxUpdateItem
* item
, CrxUpdateItem::State to
) {
61 DCHECK(thread_checker_
.CalledOnValidThread());
65 using Events
= UpdateClient::Observer::Events
;
67 const std::string
& id(item
->id
);
69 case CrxUpdateItem::State::kChecking
:
70 NotifyObservers(Events::COMPONENT_CHECKING_FOR_UPDATES
, id
);
72 case CrxUpdateItem::State::kCanUpdate
:
73 NotifyObservers(Events::COMPONENT_UPDATE_FOUND
, id
);
75 case CrxUpdateItem::State::kUpdatingDiff
:
76 case CrxUpdateItem::State::kUpdating
:
77 NotifyObservers(Events::COMPONENT_UPDATE_READY
, id
);
79 case CrxUpdateItem::State::kUpdated
:
80 NotifyObservers(Events::COMPONENT_UPDATED
, id
);
82 case CrxUpdateItem::State::kUpToDate
:
83 case CrxUpdateItem::State::kNoUpdate
:
84 NotifyObservers(Events::COMPONENT_NOT_UPDATED
, id
);
86 case CrxUpdateItem::State::kNew
:
87 case CrxUpdateItem::State::kDownloading
:
88 case CrxUpdateItem::State::kDownloadingDiff
:
89 case CrxUpdateItem::State::kDownloaded
:
90 case CrxUpdateItem::State::kLastStatus
:
91 // No notification for these states.
96 size_t ActionImpl::ChangeAllItemsState(CrxUpdateItem::State from
,
97 CrxUpdateItem::State to
) {
98 DCHECK(thread_checker_
.CalledOnValidThread());
100 for (auto item
: update_context_
->update_items
) {
101 if (item
->state
== from
) {
102 ChangeItemState(item
, to
);
109 void ActionImpl::NotifyObservers(UpdateClient::Observer::Events event
,
110 const std::string
& id
) {
111 DCHECK(thread_checker_
.CalledOnValidThread());
112 update_context_
->notify_observers_callback
.Run(event
, id
);
115 void ActionImpl::UpdateCrx() {
116 DCHECK(thread_checker_
.CalledOnValidThread());
117 DCHECK(!update_context_
->queue
.empty());
119 const std::string
& id
= update_context_
->queue
.front();
120 CrxUpdateItem
* item
= FindUpdateItemById(id
);
123 scoped_ptr
<Action
> update_action(
124 CanTryDiffUpdate(item
, update_context_
->config
)
125 ? ActionUpdateDiff::Create()
126 : ActionUpdateFull::Create());
128 base::ThreadTaskRunnerHandle::Get()->PostTask(
129 FROM_HERE
, base::Bind(&Action::Run
, base::Unretained(update_action
.get()),
130 update_context_
, callback_
));
132 update_context_
->current_action
.reset(update_action
.release());
135 void ActionImpl::UpdateCrxComplete(CrxUpdateItem
* item
) {
136 update_context_
->ping_manager
->OnUpdateComplete(item
);
138 update_context_
->queue
.pop();
140 if (update_context_
->queue
.empty()) {
143 // TODO(sorin): the value of timing interval between CRX updates might have
144 // to be injected at the call site of update_client::UpdateClient::Update.
145 const int wait_sec
= update_context_
->config
->UpdateDelay();
147 scoped_ptr
<ActionWait
> action_wait(
148 new ActionWait(base::TimeDelta::FromSeconds(wait_sec
)));
150 base::ThreadTaskRunnerHandle::Get()->PostTask(
151 FROM_HERE
, base::Bind(&Action::Run
, base::Unretained(action_wait
.get()),
152 update_context_
, callback_
));
154 update_context_
->current_action
.reset(action_wait
.release());
158 void ActionImpl::UpdateComplete(int error
) {
159 DCHECK(thread_checker_
.CalledOnValidThread());
161 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
162 base::Bind(callback_
, error
));
165 } // namespace update_client