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
{
23 using Events
= UpdateClient::Observer::Events
;
27 // Returns true if a differential update is available, it has not failed yet,
28 // and the configuration allows this update.
29 bool CanTryDiffUpdate(const CrxUpdateItem
* update_item
,
30 const scoped_refptr
<Configurator
>& config
) {
31 return HasDiffUpdate(update_item
) && !update_item
->diff_update_failed
&&
32 config
->DeltasEnabled();
37 ActionImpl::ActionImpl() : update_context_(nullptr) {
40 ActionImpl::~ActionImpl() {
41 DCHECK(thread_checker_
.CalledOnValidThread());
44 void ActionImpl::Run(UpdateContext
* update_context
, Action::Callback callback
) {
45 DCHECK(thread_checker_
.CalledOnValidThread());
47 update_context_
= update_context
;
51 CrxUpdateItem
* ActionImpl::FindUpdateItemById(const std::string
& id
) const {
52 DCHECK(thread_checker_
.CalledOnValidThread());
54 const auto it(std::find_if(
55 update_context_
->update_items
.begin(),
56 update_context_
->update_items
.end(),
57 [&id
](const CrxUpdateItem
* item
) { return item
->id
== id
; }));
59 return it
!= update_context_
->update_items
.end() ? *it
: nullptr;
62 void ActionImpl::ChangeItemState(CrxUpdateItem
* item
, CrxUpdateItem::State to
) {
63 DCHECK(thread_checker_
.CalledOnValidThread());
67 using Events
= UpdateClient::Observer::Events
;
69 const std::string
& id(item
->id
);
71 case CrxUpdateItem::State::kChecking
:
72 NotifyObservers(Events::COMPONENT_CHECKING_FOR_UPDATES
, id
);
74 case CrxUpdateItem::State::kCanUpdate
:
75 NotifyObservers(Events::COMPONENT_UPDATE_FOUND
, id
);
77 case CrxUpdateItem::State::kUpdatingDiff
:
78 case CrxUpdateItem::State::kUpdating
:
79 NotifyObservers(Events::COMPONENT_UPDATE_READY
, id
);
81 case CrxUpdateItem::State::kUpdated
:
82 NotifyObservers(Events::COMPONENT_UPDATED
, id
);
84 case CrxUpdateItem::State::kUpToDate
:
85 case CrxUpdateItem::State::kNoUpdate
:
86 NotifyObservers(Events::COMPONENT_NOT_UPDATED
, id
);
88 case CrxUpdateItem::State::kNew
:
89 case CrxUpdateItem::State::kDownloading
:
90 case CrxUpdateItem::State::kDownloadingDiff
:
91 case CrxUpdateItem::State::kDownloaded
:
92 case CrxUpdateItem::State::kLastStatus
:
93 // No notification for these states.
98 size_t ActionImpl::ChangeAllItemsState(CrxUpdateItem::State from
,
99 CrxUpdateItem::State to
) {
100 DCHECK(thread_checker_
.CalledOnValidThread());
102 for (auto item
: update_context_
->update_items
) {
103 if (item
->state
== from
) {
104 ChangeItemState(item
, to
);
111 void ActionImpl::NotifyObservers(UpdateClient::Observer::Events event
,
112 const std::string
& id
) {
113 DCHECK(thread_checker_
.CalledOnValidThread());
114 update_context_
->notify_observers_callback
.Run(event
, id
);
117 void ActionImpl::UpdateCrx() {
118 DCHECK(thread_checker_
.CalledOnValidThread());
119 DCHECK(!update_context_
->queue
.empty());
121 const std::string
& id
= update_context_
->queue
.front();
122 CrxUpdateItem
* item
= FindUpdateItemById(id
);
125 scoped_ptr
<Action
> update_action(
126 CanTryDiffUpdate(item
, update_context_
->config
)
127 ? ActionUpdateDiff::Create()
128 : ActionUpdateFull::Create());
130 base::ThreadTaskRunnerHandle::Get()->PostTask(
131 FROM_HERE
, base::Bind(&Action::Run
, base::Unretained(update_action
.get()),
132 update_context_
, callback_
));
134 update_context_
->current_action
.reset(update_action
.release());
137 void ActionImpl::UpdateCrxComplete(CrxUpdateItem
* item
) {
138 update_context_
->ping_manager
->OnUpdateComplete(item
);
140 update_context_
->queue
.pop();
142 if (update_context_
->queue
.empty()) {
145 // TODO(sorin): the value of timing interval between CRX updates might have
146 // to be injected at the call site of update_client::UpdateClient::Update.
147 const int wait_sec
= update_context_
->config
->UpdateDelay();
149 scoped_ptr
<ActionWait
> action_wait(
150 new ActionWait(base::TimeDelta::FromSeconds(wait_sec
)));
152 base::ThreadTaskRunnerHandle::Get()->PostTask(
153 FROM_HERE
, base::Bind(&Action::Run
, base::Unretained(action_wait
.get()),
154 update_context_
, callback_
));
156 update_context_
->current_action
.reset(action_wait
.release());
160 void ActionImpl::UpdateComplete(int error
) {
161 DCHECK(thread_checker_
.CalledOnValidThread());
163 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
164 base::Bind(callback_
, error
));
167 } // namespace update_client