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/crx_downloader.h"
20 #include "components/update_client/update_client.h"
21 #include "components/update_client/utils.h"
26 namespace update_client
{
30 void AppendDownloadMetrics(
31 const std::vector
<CrxDownloader::DownloadMetrics
>& source
,
32 std::vector
<CrxDownloader::DownloadMetrics
>* destination
) {
33 destination
->insert(destination
->end(), source
.begin(), source
.end());
36 Action::ErrorCategory
UnpackerErrorToErrorCategory(
37 ComponentUnpacker::Error error
) {
38 Action::ErrorCategory error_category
= Action::ErrorCategory::kErrorNone
;
40 case ComponentUnpacker::kNone
:
42 case ComponentUnpacker::kInstallerError
:
43 error_category
= Action::ErrorCategory::kInstallError
;
46 error_category
= Action::ErrorCategory::kUnpackError
;
49 return error_category
;
54 ActionUpdate::ActionUpdate() {
57 ActionUpdate::~ActionUpdate() {
58 DCHECK(thread_checker_
.CalledOnValidThread());
61 void ActionUpdate::Run(UpdateContext
* update_context
, Callback callback
) {
62 DCHECK(thread_checker_
.CalledOnValidThread());
63 ActionImpl::Run(update_context
, callback
);
65 DCHECK(!update_context_
->queue
.empty());
67 const std::string
& id
= update_context_
->queue
.front();
68 CrxUpdateItem
* item
= FindUpdateItemById(id
);
71 const bool is_background_download(IsBackgroundDownload(item
));
73 scoped_ptr
<CrxDownloader
> crx_downloader(
74 (*update_context_
->crx_downloader_factory
)(
75 is_background_download
, update_context_
->config
->RequestContext(),
76 update_context_
->blocking_task_runner
,
77 update_context_
->single_thread_task_runner
));
78 crx_downloader
->set_progress_callback(
79 base::Bind(&ActionUpdate::DownloadProgress
, base::Unretained(this), id
));
80 update_context_
->crx_downloader
.reset(crx_downloader
.release());
82 const std::vector
<GURL
> urls(GetUrls(item
));
83 OnDownloadStart(item
);
85 update_context_
->crx_downloader
->StartDownload(
87 base::Bind(&ActionUpdate::DownloadComplete
, base::Unretained(this), id
));
90 void ActionUpdate::DownloadProgress(
91 const std::string
& crx_id
,
92 const CrxDownloader::Result
& download_result
) {
93 DCHECK(thread_checker_
.CalledOnValidThread());
94 DCHECK(crx_id
== update_context_
->queue
.front());
96 using Events
= UpdateClient::Observer::Events
;
97 NotifyObservers(Events::COMPONENT_UPDATE_DOWNLOADING
, crx_id
);
100 void ActionUpdate::DownloadComplete(
101 const std::string
& crx_id
,
102 const CrxDownloader::Result
& download_result
) {
103 DCHECK(thread_checker_
.CalledOnValidThread());
104 DCHECK(crx_id
== update_context_
->queue
.front());
106 CrxUpdateItem
* item
= FindUpdateItemById(crx_id
);
109 AppendDownloadMetrics(update_context_
->crx_downloader
->download_metrics(),
110 &item
->download_metrics
);
112 if (download_result
.error
) {
113 OnDownloadError(item
, download_result
);
115 OnDownloadSuccess(item
, download_result
);
116 update_context_
->main_task_runner
->PostDelayedTask(
117 FROM_HERE
, base::Bind(&ActionUpdate::Install
, base::Unretained(this),
118 crx_id
, download_result
.response
),
119 base::TimeDelta::FromMilliseconds(
120 update_context_
->config
->StepDelay()));
123 update_context_
->crx_downloader
.reset();
126 void ActionUpdate::Install(const std::string
& crx_id
,
127 const base::FilePath
& crx_path
) {
128 DCHECK(thread_checker_
.CalledOnValidThread());
129 DCHECK(crx_id
== update_context_
->queue
.front());
131 CrxUpdateItem
* item
= FindUpdateItemById(crx_id
);
134 OnInstallStart(item
);
136 update_context_
->blocking_task_runner
->PostTask(
138 base::Bind(&ActionUpdate::DoInstallOnBlockingTaskRunner
,
139 base::Unretained(this), update_context_
, item
, crx_path
));
142 void ActionUpdate::DoInstallOnBlockingTaskRunner(
143 UpdateContext
* update_context
,
145 const base::FilePath
& crx_path
) {
146 update_context
->unpacker
= new ComponentUnpacker(
147 item
->component
.pk_hash
, crx_path
, item
->component
.fingerprint
,
148 item
->component
.installer
,
149 update_context
->config
->CreateOutOfProcessPatcher(),
150 update_context
->blocking_task_runner
);
151 update_context
->unpacker
->Unpack(
152 base::Bind(&ActionUpdate::EndUnpackingOnBlockingTaskRunner
,
153 base::Unretained(this), update_context
, item
, crx_path
));
156 void ActionUpdate::EndUnpackingOnBlockingTaskRunner(
157 UpdateContext
* update_context
,
159 const base::FilePath
& crx_path
,
160 ComponentUnpacker::Error error
,
161 int extended_error
) {
162 update_context
->unpacker
= nullptr;
163 update_client::DeleteFileAndEmptyParentDirectory(crx_path
);
164 update_context
->main_task_runner
->PostDelayedTask(
166 base::Bind(&ActionUpdate::DoneInstalling
, base::Unretained(this),
167 item
->id
, error
, extended_error
),
168 base::TimeDelta::FromMilliseconds(update_context
->config
->StepDelay()));
171 void ActionUpdate::DoneInstalling(const std::string
& crx_id
,
172 ComponentUnpacker::Error error
,
173 int extended_error
) {
174 DCHECK(thread_checker_
.CalledOnValidThread());
175 DCHECK(crx_id
== update_context_
->queue
.front());
177 CrxUpdateItem
* item
= FindUpdateItemById(crx_id
);
180 if (error
== ComponentUnpacker::kNone
)
181 OnInstallSuccess(item
);
183 OnInstallError(item
, error
, extended_error
);
186 ActionUpdateDiff::ActionUpdateDiff() {
189 ActionUpdateDiff::~ActionUpdateDiff() {
190 DCHECK(thread_checker_
.CalledOnValidThread());
193 scoped_ptr
<Action
> ActionUpdateDiff::Create() {
194 return scoped_ptr
<Action
>(new ActionUpdateDiff
);
197 void ActionUpdateDiff::TryUpdateFull() {
198 DCHECK(thread_checker_
.CalledOnValidThread());
199 scoped_ptr
<Action
> update_action(ActionUpdateFull::Create());
201 base::ThreadTaskRunnerHandle::Get()->PostTask(
202 FROM_HERE
, base::Bind(&Action::Run
, base::Unretained(update_action
.get()),
203 update_context_
, callback_
));
205 update_context_
->current_action
.reset(update_action
.release());
208 bool ActionUpdateDiff::IsBackgroundDownload(const CrxUpdateItem
* item
) {
209 DCHECK(thread_checker_
.CalledOnValidThread());
213 std::vector
<GURL
> ActionUpdateDiff::GetUrls(const CrxUpdateItem
* item
) {
214 DCHECK(thread_checker_
.CalledOnValidThread());
215 return item
->crx_diffurls
;
218 void ActionUpdateDiff::OnDownloadStart(CrxUpdateItem
* item
) {
219 DCHECK(thread_checker_
.CalledOnValidThread());
220 DCHECK(item
->state
== CrxUpdateItem::State::kCanUpdate
);
222 ChangeItemState(item
, CrxUpdateItem::State::kDownloadingDiff
);
225 void ActionUpdateDiff::OnDownloadSuccess(
227 const CrxDownloader::Result
& download_result
) {
228 DCHECK(thread_checker_
.CalledOnValidThread());
229 DCHECK(item
->state
== CrxUpdateItem::State::kDownloadingDiff
);
231 ChangeItemState(item
, CrxUpdateItem::State::kDownloaded
);
234 void ActionUpdateDiff::OnDownloadError(
236 const CrxDownloader::Result
& download_result
) {
237 DCHECK(thread_checker_
.CalledOnValidThread());
238 DCHECK(item
->state
== CrxUpdateItem::State::kDownloadingDiff
);
240 item
->diff_error_category
= static_cast<int>(ErrorCategory::kNetworkError
);
241 item
->diff_error_code
= download_result
.error
;
242 item
->diff_update_failed
= true;
244 base::ThreadTaskRunnerHandle::Get()->PostTask(
246 base::Bind(&ActionUpdateDiff::TryUpdateFull
, base::Unretained(this)));
249 void ActionUpdateDiff::OnInstallStart(CrxUpdateItem
* item
) {
250 DCHECK(thread_checker_
.CalledOnValidThread());
252 ChangeItemState(item
, CrxUpdateItem::State::kUpdatingDiff
);
255 void ActionUpdateDiff::OnInstallSuccess(CrxUpdateItem
* item
) {
256 DCHECK(thread_checker_
.CalledOnValidThread());
257 DCHECK(item
->state
== CrxUpdateItem::State::kUpdatingDiff
);
259 item
->component
.version
= item
->next_version
;
260 item
->component
.fingerprint
= item
->next_fp
;
261 ChangeItemState(item
, CrxUpdateItem::State::kUpdated
);
263 UpdateCrxComplete(item
);
266 void ActionUpdateDiff::OnInstallError(CrxUpdateItem
* item
,
267 ComponentUnpacker::Error error
,
268 int extended_error
) {
269 DCHECK(thread_checker_
.CalledOnValidThread());
271 item
->diff_error_category
=
272 static_cast<int>(UnpackerErrorToErrorCategory(error
));
273 item
->diff_error_code
= error
;
274 item
->diff_extra_code1
= extended_error
;
275 item
->diff_update_failed
= true;
277 base::ThreadTaskRunnerHandle::Get()->PostTask(
279 base::Bind(&ActionUpdateDiff::TryUpdateFull
, base::Unretained(this)));
282 ActionUpdateFull::ActionUpdateFull() {
285 ActionUpdateFull::~ActionUpdateFull() {
286 DCHECK(thread_checker_
.CalledOnValidThread());
289 scoped_ptr
<Action
> ActionUpdateFull::Create() {
290 return scoped_ptr
<Action
>(new ActionUpdateFull
);
293 bool ActionUpdateFull::IsBackgroundDownload(const CrxUpdateItem
* item
) {
294 DCHECK(thread_checker_
.CalledOnValidThread());
296 // On demand component updates are always downloaded in foreground.
297 return !item
->on_demand
&& item
->component
.allow_background_download
&&
298 update_context_
->config
->UseBackgroundDownloader();
301 std::vector
<GURL
> ActionUpdateFull::GetUrls(const CrxUpdateItem
* item
) {
302 DCHECK(thread_checker_
.CalledOnValidThread());
303 return item
->crx_urls
;
306 void ActionUpdateFull::OnDownloadStart(CrxUpdateItem
* item
) {
307 DCHECK(thread_checker_
.CalledOnValidThread());
308 DCHECK(item
->state
== CrxUpdateItem::State::kCanUpdate
||
309 item
->diff_update_failed
);
311 ChangeItemState(item
, CrxUpdateItem::State::kDownloading
);
314 void ActionUpdateFull::OnDownloadSuccess(
316 const CrxDownloader::Result
& download_result
) {
317 DCHECK(thread_checker_
.CalledOnValidThread());
318 DCHECK(item
->state
== CrxUpdateItem::State::kDownloading
);
320 ChangeItemState(item
, CrxUpdateItem::State::kDownloaded
);
323 void ActionUpdateFull::OnDownloadError(
325 const CrxDownloader::Result
& download_result
) {
326 DCHECK(thread_checker_
.CalledOnValidThread());
327 DCHECK(item
->state
== CrxUpdateItem::State::kDownloading
);
329 item
->error_category
= static_cast<int>(ErrorCategory::kNetworkError
);
330 item
->error_code
= download_result
.error
;
331 ChangeItemState(item
, CrxUpdateItem::State::kNoUpdate
);
333 UpdateCrxComplete(item
);
336 void ActionUpdateFull::OnInstallStart(CrxUpdateItem
* item
) {
337 DCHECK(thread_checker_
.CalledOnValidThread());
338 DCHECK(item
->state
== CrxUpdateItem::State::kDownloaded
);
340 ChangeItemState(item
, CrxUpdateItem::State::kUpdating
);
343 void ActionUpdateFull::OnInstallSuccess(CrxUpdateItem
* item
) {
344 DCHECK(thread_checker_
.CalledOnValidThread());
345 DCHECK(item
->state
== CrxUpdateItem::State::kUpdating
);
347 item
->component
.version
= item
->next_version
;
348 item
->component
.fingerprint
= item
->next_fp
;
349 ChangeItemState(item
, CrxUpdateItem::State::kUpdated
);
351 UpdateCrxComplete(item
);
354 void ActionUpdateFull::OnInstallError(CrxUpdateItem
* item
,
355 ComponentUnpacker::Error error
,
356 int extended_error
) {
357 DCHECK(thread_checker_
.CalledOnValidThread());
358 DCHECK(item
->state
== CrxUpdateItem::State::kUpdating
);
360 item
->error_category
= static_cast<int>(UnpackerErrorToErrorCategory(error
));
361 item
->error_code
= error
;
362 item
->extra_code1
= extended_error
;
363 ChangeItemState(item
, CrxUpdateItem::State::kNoUpdate
);
365 UpdateCrxComplete(item
);
368 } // namespace update_client