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_update.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/time/time.h"
17 #include "base/version.h"
18 #include "components/update_client/configurator.h"
19 #include "components/update_client/utils.h"
24 namespace update_client
{
28 void AppendDownloadMetrics(
29 const std::vector
<CrxDownloader::DownloadMetrics
>& source
,
30 std::vector
<CrxDownloader::DownloadMetrics
>* destination
) {
31 destination
->insert(destination
->end(), source
.begin(), source
.end());
34 Action::ErrorCategory
UnpackerErrorToErrorCategory(
35 ComponentUnpacker::Error error
) {
36 Action::ErrorCategory error_category
= Action::ErrorCategory::kErrorNone
;
38 case ComponentUnpacker::kNone
:
40 case ComponentUnpacker::kInstallerError
:
41 error_category
= Action::ErrorCategory::kInstallError
;
44 error_category
= Action::ErrorCategory::kUnpackError
;
47 return error_category
;
52 ActionUpdate::ActionUpdate() {
55 ActionUpdate::~ActionUpdate() {
56 DCHECK(thread_checker_
.CalledOnValidThread());
59 void ActionUpdate::Run(UpdateContext
* update_context
, Callback callback
) {
60 DCHECK(thread_checker_
.CalledOnValidThread());
61 ActionImpl::Run(update_context
, callback
);
63 DCHECK(!update_context_
->queue
.empty());
65 const std::string
& id
= update_context_
->queue
.front();
66 CrxUpdateItem
* item
= FindUpdateItemById(id
);
69 const bool is_background_download(IsBackgroundDownload(item
));
71 crx_downloader_
.reset(
72 (*update_context_
->crx_downloader_factory
)(
73 is_background_download
, update_context_
->config
->RequestContext(),
74 update_context_
->blocking_task_runner
,
75 update_context_
->single_thread_task_runner
).release());
76 crx_downloader_
->set_progress_callback(
77 base::Bind(&ActionUpdate::DownloadProgress
, base::Unretained(this), id
));
79 OnDownloadStart(item
);
81 crx_downloader_
->StartDownload(
83 base::Bind(&ActionUpdate::DownloadComplete
, base::Unretained(this), id
));
86 void ActionUpdate::DownloadProgress(
87 const std::string
& id
,
88 const CrxDownloader::Result
& download_result
) {
89 DCHECK(thread_checker_
.CalledOnValidThread());
90 DCHECK(id
== update_context_
->queue
.front());
92 using Events
= UpdateClient::Observer::Events
;
93 NotifyObservers(Events::COMPONENT_UPDATE_DOWNLOADING
, id
);
96 void ActionUpdate::DownloadComplete(
97 const std::string
& id
,
98 const CrxDownloader::Result
& download_result
) {
99 DCHECK(thread_checker_
.CalledOnValidThread());
100 DCHECK(id
== update_context_
->queue
.front());
102 CrxUpdateItem
* item
= FindUpdateItemById(id
);
105 AppendDownloadMetrics(crx_downloader_
->download_metrics(),
106 &item
->download_metrics
);
108 crx_downloader_
.reset();
110 if (download_result
.error
) {
111 OnDownloadError(item
, download_result
);
113 OnDownloadSuccess(item
, download_result
);
114 update_context_
->main_task_runner
->PostDelayedTask(
115 FROM_HERE
, base::Bind(&ActionUpdate::Install
, base::Unretained(this),
116 id
, download_result
.response
),
117 base::TimeDelta::FromMilliseconds(
118 update_context_
->config
->StepDelay()));
122 void ActionUpdate::Install(const std::string
& id
,
123 const base::FilePath
& crx_path
) {
124 DCHECK(thread_checker_
.CalledOnValidThread());
125 DCHECK(id
== update_context_
->queue
.front());
127 CrxUpdateItem
* item
= FindUpdateItemById(id
);
130 OnInstallStart(item
);
132 update_context_
->blocking_task_runner
->PostTask(
134 base::Bind(&ActionUpdate::DoInstallOnBlockingTaskRunner
,
135 base::Unretained(this), update_context_
, item
, crx_path
));
138 void ActionUpdate::DoInstallOnBlockingTaskRunner(
139 UpdateContext
* update_context
,
141 const base::FilePath
& crx_path
) {
142 unpacker_
= new ComponentUnpacker(
143 item
->component
.pk_hash
, crx_path
, item
->component
.fingerprint
,
144 item
->component
.installer
,
145 update_context
->config
->CreateOutOfProcessPatcher(),
146 update_context
->blocking_task_runner
);
147 unpacker_
->Unpack(base::Bind(&ActionUpdate::EndUnpackingOnBlockingTaskRunner
,
148 base::Unretained(this), update_context
, item
,
152 void ActionUpdate::EndUnpackingOnBlockingTaskRunner(
153 UpdateContext
* update_context
,
155 const base::FilePath
& crx_path
,
156 ComponentUnpacker::Error error
,
157 int extended_error
) {
159 update_client::DeleteFileAndEmptyParentDirectory(crx_path
);
160 update_context
->main_task_runner
->PostDelayedTask(
162 base::Bind(&ActionUpdate::DoneInstalling
, base::Unretained(this),
163 item
->id
, error
, extended_error
),
164 base::TimeDelta::FromMilliseconds(update_context
->config
->StepDelay()));
167 void ActionUpdate::DoneInstalling(const std::string
& id
,
168 ComponentUnpacker::Error error
,
169 int extended_error
) {
170 DCHECK(thread_checker_
.CalledOnValidThread());
171 DCHECK(id
== update_context_
->queue
.front());
173 CrxUpdateItem
* item
= FindUpdateItemById(id
);
176 if (error
== ComponentUnpacker::kNone
)
177 OnInstallSuccess(item
);
179 OnInstallError(item
, error
, extended_error
);
182 ActionUpdateDiff::ActionUpdateDiff() {
185 ActionUpdateDiff::~ActionUpdateDiff() {
186 DCHECK(thread_checker_
.CalledOnValidThread());
189 scoped_ptr
<Action
> ActionUpdateDiff::Create() {
190 return scoped_ptr
<Action
>(new ActionUpdateDiff
);
193 void ActionUpdateDiff::TryUpdateFull() {
194 DCHECK(thread_checker_
.CalledOnValidThread());
195 scoped_ptr
<Action
> update_action(ActionUpdateFull::Create());
197 base::ThreadTaskRunnerHandle::Get()->PostTask(
198 FROM_HERE
, base::Bind(&Action::Run
, base::Unretained(update_action
.get()),
199 update_context_
, callback_
));
201 update_context_
->current_action
.reset(update_action
.release());
204 bool ActionUpdateDiff::IsBackgroundDownload(const CrxUpdateItem
* item
) {
205 DCHECK(thread_checker_
.CalledOnValidThread());
209 std::vector
<GURL
> ActionUpdateDiff::GetUrls(const CrxUpdateItem
* item
) {
210 DCHECK(thread_checker_
.CalledOnValidThread());
211 return item
->crx_diffurls
;
214 void ActionUpdateDiff::OnDownloadStart(CrxUpdateItem
* item
) {
215 DCHECK(thread_checker_
.CalledOnValidThread());
216 DCHECK(item
->state
== CrxUpdateItem::State::kCanUpdate
);
218 ChangeItemState(item
, CrxUpdateItem::State::kDownloadingDiff
);
221 void ActionUpdateDiff::OnDownloadSuccess(
223 const CrxDownloader::Result
& download_result
) {
224 DCHECK(thread_checker_
.CalledOnValidThread());
225 DCHECK(item
->state
== CrxUpdateItem::State::kDownloadingDiff
);
227 ChangeItemState(item
, CrxUpdateItem::State::kDownloaded
);
230 void ActionUpdateDiff::OnDownloadError(
232 const CrxDownloader::Result
& download_result
) {
233 DCHECK(thread_checker_
.CalledOnValidThread());
234 DCHECK(item
->state
== CrxUpdateItem::State::kDownloadingDiff
);
236 item
->diff_error_category
= static_cast<int>(ErrorCategory::kNetworkError
);
237 item
->diff_error_code
= download_result
.error
;
238 item
->diff_update_failed
= true;
240 base::ThreadTaskRunnerHandle::Get()->PostTask(
242 base::Bind(&ActionUpdateDiff::TryUpdateFull
, base::Unretained(this)));
245 void ActionUpdateDiff::OnInstallStart(CrxUpdateItem
* item
) {
246 DCHECK(thread_checker_
.CalledOnValidThread());
248 ChangeItemState(item
, CrxUpdateItem::State::kUpdatingDiff
);
251 void ActionUpdateDiff::OnInstallSuccess(CrxUpdateItem
* item
) {
252 DCHECK(thread_checker_
.CalledOnValidThread());
253 DCHECK(item
->state
== CrxUpdateItem::State::kUpdatingDiff
);
255 item
->component
.version
= item
->next_version
;
256 item
->component
.fingerprint
= item
->next_fp
;
257 ChangeItemState(item
, CrxUpdateItem::State::kUpdated
);
259 UpdateCrxComplete(item
);
262 void ActionUpdateDiff::OnInstallError(CrxUpdateItem
* item
,
263 ComponentUnpacker::Error error
,
264 int extended_error
) {
265 DCHECK(thread_checker_
.CalledOnValidThread());
267 item
->diff_error_category
=
268 static_cast<int>(UnpackerErrorToErrorCategory(error
));
269 item
->diff_error_code
= error
;
270 item
->diff_extra_code1
= extended_error
;
271 item
->diff_update_failed
= true;
273 base::ThreadTaskRunnerHandle::Get()->PostTask(
275 base::Bind(&ActionUpdateDiff::TryUpdateFull
, base::Unretained(this)));
278 ActionUpdateFull::ActionUpdateFull() {
281 ActionUpdateFull::~ActionUpdateFull() {
282 DCHECK(thread_checker_
.CalledOnValidThread());
285 scoped_ptr
<Action
> ActionUpdateFull::Create() {
286 return scoped_ptr
<Action
>(new ActionUpdateFull
);
289 bool ActionUpdateFull::IsBackgroundDownload(const CrxUpdateItem
* item
) {
290 DCHECK(thread_checker_
.CalledOnValidThread());
292 // On demand component updates are always downloaded in foreground.
293 return !item
->on_demand
&& item
->component
.allow_background_download
&&
294 update_context_
->config
->UseBackgroundDownloader();
297 std::vector
<GURL
> ActionUpdateFull::GetUrls(const CrxUpdateItem
* item
) {
298 DCHECK(thread_checker_
.CalledOnValidThread());
299 return item
->crx_urls
;
302 void ActionUpdateFull::OnDownloadStart(CrxUpdateItem
* item
) {
303 DCHECK(thread_checker_
.CalledOnValidThread());
304 DCHECK(item
->state
== CrxUpdateItem::State::kCanUpdate
||
305 item
->diff_update_failed
);
307 ChangeItemState(item
, CrxUpdateItem::State::kDownloading
);
310 void ActionUpdateFull::OnDownloadSuccess(
312 const CrxDownloader::Result
& download_result
) {
313 DCHECK(thread_checker_
.CalledOnValidThread());
314 DCHECK(item
->state
== CrxUpdateItem::State::kDownloading
);
316 ChangeItemState(item
, CrxUpdateItem::State::kDownloaded
);
319 void ActionUpdateFull::OnDownloadError(
321 const CrxDownloader::Result
& download_result
) {
322 DCHECK(thread_checker_
.CalledOnValidThread());
323 DCHECK(item
->state
== CrxUpdateItem::State::kDownloading
);
325 item
->error_category
= static_cast<int>(ErrorCategory::kNetworkError
);
326 item
->error_code
= download_result
.error
;
327 ChangeItemState(item
, CrxUpdateItem::State::kNoUpdate
);
329 UpdateCrxComplete(item
);
332 void ActionUpdateFull::OnInstallStart(CrxUpdateItem
* item
) {
333 DCHECK(thread_checker_
.CalledOnValidThread());
334 DCHECK(item
->state
== CrxUpdateItem::State::kDownloaded
);
336 ChangeItemState(item
, CrxUpdateItem::State::kUpdating
);
339 void ActionUpdateFull::OnInstallSuccess(CrxUpdateItem
* item
) {
340 DCHECK(thread_checker_
.CalledOnValidThread());
341 DCHECK(item
->state
== CrxUpdateItem::State::kUpdating
);
343 item
->component
.version
= item
->next_version
;
344 item
->component
.fingerprint
= item
->next_fp
;
345 ChangeItemState(item
, CrxUpdateItem::State::kUpdated
);
347 UpdateCrxComplete(item
);
350 void ActionUpdateFull::OnInstallError(CrxUpdateItem
* item
,
351 ComponentUnpacker::Error error
,
352 int extended_error
) {
353 DCHECK(thread_checker_
.CalledOnValidThread());
354 DCHECK(item
->state
== CrxUpdateItem::State::kUpdating
);
356 item
->error_category
= static_cast<int>(UnpackerErrorToErrorCategory(error
));
357 item
->error_code
= error
;
358 item
->extra_code1
= extended_error
;
359 ChangeItemState(item
, CrxUpdateItem::State::kNoUpdate
);
361 UpdateCrxComplete(item
);
364 } // namespace update_client