| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "components/update_client/action_update_check.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/bind_helpers.h" | |
| 12 #include "base/callback.h" | |
| 13 #include "base/location.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/memory/ptr_util.h" | |
| 16 #include "base/single_thread_task_runner.h" | |
| 17 #include "base/threading/thread_task_runner_handle.h" | |
| 18 #include "base/version.h" | |
| 19 #include "components/update_client/action_update.h" | |
| 20 #include "components/update_client/configurator.h" | |
| 21 #include "components/update_client/update_checker.h" | |
| 22 #include "components/update_client/update_client.h" | |
| 23 #include "components/update_client/update_client_errors.h" | |
| 24 #include "components/update_client/utils.h" | |
| 25 | |
| 26 using std::string; | |
| 27 using std::vector; | |
| 28 | |
| 29 namespace update_client { | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 // Returns true if the |proposed| version is newer than |current| version. | |
| 34 bool IsVersionNewer(const base::Version& current, const std::string& proposed) { | |
| 35 base::Version proposed_ver(proposed); | |
| 36 return proposed_ver.IsValid() && current.CompareTo(proposed_ver) < 0; | |
| 37 } | |
| 38 | |
| 39 } // namespace | |
| 40 | |
| 41 ActionUpdateCheck::ActionUpdateCheck( | |
| 42 std::unique_ptr<UpdateChecker> update_checker, | |
| 43 const base::Version& browser_version, | |
| 44 const std::string& extra_request_parameters) | |
| 45 : update_checker_(std::move(update_checker)), | |
| 46 browser_version_(browser_version), | |
| 47 extra_request_parameters_(extra_request_parameters) {} | |
| 48 | |
| 49 ActionUpdateCheck::~ActionUpdateCheck() { | |
| 50 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 51 } | |
| 52 | |
| 53 void ActionUpdateCheck::Run(UpdateContext* update_context, Callback callback) { | |
| 54 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 55 | |
| 56 ActionImpl::Run(update_context, callback); | |
| 57 | |
| 58 // Calls out to get the corresponding CrxComponent data for the CRXs in this | |
| 59 // update context. | |
| 60 vector<CrxComponent> crx_components; | |
| 61 update_context_->crx_data_callback.Run(update_context_->ids, &crx_components); | |
| 62 | |
| 63 for (size_t i = 0; i != crx_components.size(); ++i) { | |
| 64 std::unique_ptr<CrxUpdateItem> item = base::MakeUnique<CrxUpdateItem>(); | |
| 65 const CrxComponent& crx_component = crx_components[i]; | |
| 66 | |
| 67 item->id = GetCrxComponentID(crx_component); | |
| 68 item->component = crx_component; | |
| 69 item->last_check = base::TimeTicks::Now(); | |
| 70 item->crx_urls.clear(); | |
| 71 item->crx_diffurls.clear(); | |
| 72 item->previous_version = crx_component.version; | |
| 73 item->next_version = base::Version(); | |
| 74 item->previous_fp = crx_component.fingerprint; | |
| 75 item->next_fp.clear(); | |
| 76 item->on_demand = update_context->is_foreground; | |
| 77 item->diff_update_failed = false; | |
| 78 item->error_category = 0; | |
| 79 item->error_code = 0; | |
| 80 item->extra_code1 = 0; | |
| 81 item->diff_error_category = 0; | |
| 82 item->diff_error_code = 0; | |
| 83 item->diff_extra_code1 = 0; | |
| 84 item->download_metrics.clear(); | |
| 85 | |
| 86 CrxUpdateItem* item_ptr = item.get(); | |
| 87 update_context_->update_items[item_ptr->id] = std::move(item); | |
| 88 | |
| 89 ChangeItemState(item_ptr, CrxUpdateItem::State::kChecking); | |
| 90 } | |
| 91 | |
| 92 update_checker_->CheckForUpdates( | |
| 93 update_context_->update_items, extra_request_parameters_, | |
| 94 update_context_->enabled_component_updates, | |
| 95 base::Bind(&ActionUpdateCheck::UpdateCheckComplete, | |
| 96 base::Unretained(this))); | |
| 97 } | |
| 98 | |
| 99 void ActionUpdateCheck::UpdateCheckComplete( | |
| 100 int error, | |
| 101 const UpdateResponse::Results& results, | |
| 102 int retry_after_sec) { | |
| 103 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 104 | |
| 105 update_context_->retry_after_sec = retry_after_sec; | |
| 106 | |
| 107 if (!error) | |
| 108 OnUpdateCheckSucceeded(results); | |
| 109 else | |
| 110 OnUpdateCheckFailed(error); | |
| 111 } | |
| 112 | |
| 113 void ActionUpdateCheck::OnUpdateCheckSucceeded( | |
| 114 const UpdateResponse::Results& results) { | |
| 115 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 116 VLOG(1) << "Update check succeeded."; | |
| 117 | |
| 118 for (const auto& result : results.list) { | |
| 119 CrxUpdateItem* crx = FindUpdateItemById(result.extension_id); | |
| 120 if (!crx) { | |
| 121 VLOG(1) << "Component not found " << result.extension_id; | |
| 122 continue; | |
| 123 } | |
| 124 | |
| 125 DCHECK_EQ(CrxUpdateItem::State::kChecking, crx->state); | |
| 126 | |
| 127 if (result.status == "ok") | |
| 128 HandleUpdateCheckOK(result, crx); | |
| 129 else if (result.status == "noupdate") | |
| 130 HandleUpdateCheckNoupdate(result, crx); | |
| 131 else | |
| 132 HandleUpdateCheckError(result, crx); | |
| 133 } | |
| 134 | |
| 135 // All components that are not included in the update response are | |
| 136 // considered up to date. | |
| 137 ChangeAllItemsState(CrxUpdateItem::State::kChecking, | |
| 138 CrxUpdateItem::State::kUpToDate); | |
| 139 | |
| 140 if (update_context_->queue.empty()) { | |
| 141 VLOG(1) << "Update check completed but no action is needed."; | |
| 142 UpdateComplete(Error::NONE); | |
| 143 return; | |
| 144 } | |
| 145 | |
| 146 // Starts the execution flow of updating the CRXs in this context. | |
| 147 UpdateCrx(); | |
| 148 } | |
| 149 | |
| 150 void ActionUpdateCheck::HandleUpdateCheckOK( | |
| 151 const UpdateResponse::Result& result, | |
| 152 CrxUpdateItem* crx) { | |
| 153 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 154 | |
| 155 const auto& manifest = result.manifest; | |
| 156 | |
| 157 if (manifest.version.empty()) { | |
| 158 // It can't update without a manifest version. | |
| 159 VLOG(1) << "No manifest version available for CRX: " << crx->id; | |
| 160 ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); | |
| 161 return; | |
| 162 } | |
| 163 | |
| 164 if (!IsVersionNewer(crx->component.version, manifest.version)) { | |
| 165 // The CRX is up to date. | |
| 166 VLOG(1) << "Component already up to date: " << crx->id; | |
| 167 ChangeItemState(crx, CrxUpdateItem::State::kUpToDate); | |
| 168 return; | |
| 169 } | |
| 170 | |
| 171 if (!manifest.browser_min_version.empty()) { | |
| 172 if (IsVersionNewer(browser_version_, manifest.browser_min_version)) { | |
| 173 // The CRX is not compatible with this Chrome version. | |
| 174 VLOG(1) << "Ignoring incompatible CRX: " << crx->id; | |
| 175 ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); | |
| 176 return; | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 if (manifest.packages.size() != 1) { | |
| 181 // Assume one and only one package per CRX. | |
| 182 VLOG(1) << "Ignoring multiple packages for CRX: " << crx->id; | |
| 183 ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); | |
| 184 return; | |
| 185 } | |
| 186 | |
| 187 // Parse the members of the result and queue an upgrade for this CRX. | |
| 188 VLOG(1) << "Update found for CRX: " << crx->id; | |
| 189 | |
| 190 crx->next_version = base::Version(manifest.version); | |
| 191 const auto& package = manifest.packages.front(); | |
| 192 crx->next_fp = package.fingerprint; | |
| 193 | |
| 194 // Resolve the urls by combining the base urls with the package names. | |
| 195 for (const auto& crx_url : result.crx_urls) { | |
| 196 const GURL url = crx_url.Resolve(package.name); | |
| 197 if (url.is_valid()) | |
| 198 crx->crx_urls.push_back(url); | |
| 199 } | |
| 200 for (const auto& crx_diffurl : result.crx_diffurls) { | |
| 201 const GURL url = crx_diffurl.Resolve(package.namediff); | |
| 202 if (url.is_valid()) | |
| 203 crx->crx_diffurls.push_back(url); | |
| 204 } | |
| 205 | |
| 206 crx->hash_sha256 = package.hash_sha256; | |
| 207 crx->hashdiff_sha256 = package.hashdiff_sha256; | |
| 208 | |
| 209 ChangeItemState(crx, CrxUpdateItem::State::kCanUpdate); | |
| 210 | |
| 211 update_context_->queue.push(crx->id); | |
| 212 } | |
| 213 | |
| 214 void ActionUpdateCheck::HandleUpdateCheckNoupdate( | |
| 215 const UpdateResponse::Result& result, | |
| 216 CrxUpdateItem* crx) { | |
| 217 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 218 VLOG(1) << "No update for CRX: " << crx->id; | |
| 219 ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); | |
| 220 } | |
| 221 | |
| 222 void ActionUpdateCheck::HandleUpdateCheckError( | |
| 223 const UpdateResponse::Result& result, | |
| 224 CrxUpdateItem* crx) { | |
| 225 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 226 VLOG(1) << "Update error for CRX: " << crx->id << ", " << result.status; | |
| 227 ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); | |
| 228 } | |
| 229 | |
| 230 void ActionUpdateCheck::OnUpdateCheckFailed(int error) { | |
| 231 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 232 DCHECK(error); | |
| 233 | |
| 234 VLOG(1) << "Update check failed." << error; | |
| 235 | |
| 236 ChangeAllItemsState(CrxUpdateItem::State::kChecking, | |
| 237 CrxUpdateItem::State::kNoUpdate); | |
| 238 | |
| 239 UpdateComplete(Error::UPDATE_CHECK_ERROR); | |
| 240 } | |
| 241 | |
| 242 } // namespace update_client | |
| OLD | NEW |