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_check.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/version.h"
15 #include "components/update_client/action_update.h"
16 #include "components/update_client/configurator.h"
17 #include "components/update_client/update_checker.h"
18 #include "components/update_client/update_client.h"
19 #include "components/update_client/utils.h"
24 namespace update_client
{
28 // Returns true if the |proposed| version is newer than |current| version.
29 bool IsVersionNewer(const Version
& current
, const std::string
& proposed
) {
30 Version
proposed_ver(proposed
);
31 return proposed_ver
.IsValid() && current
.CompareTo(proposed_ver
) < 0;
36 ActionUpdateCheck::ActionUpdateCheck(
37 scoped_ptr
<UpdateChecker
> update_checker
,
38 const base::Version
& browser_version
,
39 const std::string
& extra_request_parameters
)
40 : update_checker_(update_checker
.Pass()),
41 browser_version_(browser_version
),
42 extra_request_parameters_(extra_request_parameters
) {
45 ActionUpdateCheck::~ActionUpdateCheck() {
46 DCHECK(thread_checker_
.CalledOnValidThread());
49 void ActionUpdateCheck::Run(UpdateContext
* update_context
, Callback callback
) {
50 DCHECK(thread_checker_
.CalledOnValidThread());
52 ActionImpl::Run(update_context
, callback
);
54 // Calls out to get the corresponding CrxComponent data for the CRXs in this
56 vector
<CrxComponent
> crx_components
;
57 update_context_
->crx_data_callback
.Run(update_context_
->ids
, &crx_components
);
59 update_context_
->update_items
.reserve(crx_components
.size());
61 for (size_t i
= 0; i
!= crx_components
.size(); ++i
) {
62 scoped_ptr
<CrxUpdateItem
> item(new CrxUpdateItem
);
63 const CrxComponent
& crx_component
= crx_components
[i
];
65 item
->id
= GetCrxComponentID(crx_component
);
66 item
->component
= crx_component
;
67 item
->last_check
= base::Time::Now();
68 item
->crx_urls
.clear();
69 item
->crx_diffurls
.clear();
70 item
->previous_version
= crx_component
.version
;
71 item
->next_version
= Version();
72 item
->previous_fp
= crx_component
.fingerprint
;
73 item
->next_fp
.clear();
74 item
->on_demand
= update_context
->is_foreground
;
75 item
->diff_update_failed
= false;
76 item
->error_category
= 0;
78 item
->extra_code1
= 0;
79 item
->diff_error_category
= 0;
80 item
->diff_error_code
= 0;
81 item
->diff_extra_code1
= 0;
82 item
->download_metrics
.clear();
84 update_context_
->update_items
.push_back(item
.get());
86 ChangeItemState(item
.get(), CrxUpdateItem::State::kChecking
);
87 ignore_result(item
.release());
90 update_checker_
->CheckForUpdates(
91 update_context_
->update_items
, extra_request_parameters_
,
92 base::Bind(&ActionUpdateCheck::UpdateCheckComplete
,
93 base::Unretained(this)));
96 void ActionUpdateCheck::UpdateCheckComplete(
97 const GURL
& original_url
,
99 const std::string
& error_message
,
100 const UpdateResponse::Results
& results
) {
101 DCHECK(thread_checker_
.CalledOnValidThread());
103 VLOG(1) << "Update check completed from: " << original_url
.spec();
106 OnUpdateCheckSucceeded(results
);
108 OnUpdateCheckFailed(error
, error_message
);
111 void ActionUpdateCheck::OnUpdateCheckSucceeded(
112 const UpdateResponse::Results
& results
) {
113 DCHECK(thread_checker_
.CalledOnValidThread());
114 VLOG(1) << "Update check succeeded.";
115 std::vector
<UpdateResponse::Result
>::const_iterator it
;
116 for (it
= results
.list
.begin(); it
!= results
.list
.end(); ++it
) {
117 CrxUpdateItem
* crx
= FindUpdateItemById(it
->extension_id
);
121 if (crx
->state
!= CrxUpdateItem::State::kChecking
) {
123 continue; // Not updating this CRX now.
126 if (it
->manifest
.version
.empty()) {
127 // No version means no update available.
128 ChangeItemState(crx
, CrxUpdateItem::State::kNoUpdate
);
129 VLOG(1) << "No update available for CRX: " << crx
->id
;
133 if (!IsVersionNewer(crx
->component
.version
, it
->manifest
.version
)) {
134 // The CRX is up to date.
135 ChangeItemState(crx
, CrxUpdateItem::State::kUpToDate
);
136 VLOG(1) << "Component already up-to-date: " << crx
->id
;
140 if (!it
->manifest
.browser_min_version
.empty()) {
141 if (IsVersionNewer(browser_version_
, it
->manifest
.browser_min_version
)) {
142 // The CRX is not compatible with this Chrome version.
143 VLOG(1) << "Ignoring incompatible CRX: " << crx
->id
;
144 ChangeItemState(crx
, CrxUpdateItem::State::kNoUpdate
);
149 if (it
->manifest
.packages
.size() != 1) {
150 // Assume one and only one package per CRX.
151 VLOG(1) << "Ignoring multiple packages for CRX: " << crx
->id
;
152 ChangeItemState(crx
, CrxUpdateItem::State::kNoUpdate
);
156 // Parse the members of the result and queue an upgrade for this CRX.
157 crx
->next_version
= Version(it
->manifest
.version
);
159 VLOG(1) << "Update found for CRX: " << crx
->id
;
161 const auto& package(it
->manifest
.packages
[0]);
162 crx
->next_fp
= package
.fingerprint
;
164 // Resolve the urls by combining the base urls with the package names.
165 for (size_t i
= 0; i
!= it
->crx_urls
.size(); ++i
) {
166 const GURL
url(it
->crx_urls
[i
].Resolve(package
.name
));
168 crx
->crx_urls
.push_back(url
);
170 for (size_t i
= 0; i
!= it
->crx_diffurls
.size(); ++i
) {
171 const GURL
url(it
->crx_diffurls
[i
].Resolve(package
.namediff
));
173 crx
->crx_diffurls
.push_back(url
);
176 ChangeItemState(crx
, CrxUpdateItem::State::kCanUpdate
);
178 update_context_
->queue
.push(crx
->id
);
181 // All components that are not included in the update response are
182 // considered up to date.
183 ChangeAllItemsState(CrxUpdateItem::State::kChecking
,
184 CrxUpdateItem::State::kUpToDate
);
186 if (update_context_
->queue
.empty()) {
187 VLOG(1) << "Update check completed but no update is needed.";
192 // Starts the execution flow of updating the CRXs in this context.
196 void ActionUpdateCheck::OnUpdateCheckFailed(int error
,
197 const std::string
& error_message
) {
198 DCHECK(thread_checker_
.CalledOnValidThread());
201 VLOG(1) << "Update check failed." << error
;
203 UpdateComplete(error
);
206 } // namespace update_client