diff options
Diffstat (limited to 'components/update_client/action_update_check.cc')
-rw-r--r-- | components/update_client/action_update_check.cc | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/components/update_client/action_update_check.cc b/components/update_client/action_update_check.cc new file mode 100644 index 0000000..c480de8 --- /dev/null +++ b/components/update_client/action_update_check.cc @@ -0,0 +1,204 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/update_client/action_update_check.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "base/version.h" +#include "components/update_client/action_update.h" +#include "components/update_client/configurator.h" +#include "components/update_client/update_checker.h" +#include "components/update_client/update_client.h" +#include "components/update_client/utils.h" + +using std::string; +using std::vector; + +namespace update_client { + +namespace { + +// Returns true if the |proposed| version is newer than |current| version. +bool IsVersionNewer(const Version& current, const std::string& proposed) { + Version proposed_ver(proposed); + return proposed_ver.IsValid() && current.CompareTo(proposed_ver) < 0; +} + +} // namespace + +ActionUpdateCheck::ActionUpdateCheck( + scoped_ptr<UpdateChecker> update_checker, + const base::Version& browser_version, + const std::string& extra_request_parameters) + : update_checker_(update_checker.Pass()), + browser_version_(browser_version), + extra_request_parameters_(extra_request_parameters) { +} + +ActionUpdateCheck::~ActionUpdateCheck() { + DCHECK(thread_checker_.CalledOnValidThread()); +} + +void ActionUpdateCheck::Run(UpdateContext* update_context, Callback callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + ActionImpl::Run(update_context, callback); + + // Calls out to get the corresponding CrxComponent data for the CRXs in this + // update context. + vector<CrxComponent> crx_components; + update_context_->crx_data_callback.Run(update_context_->ids, &crx_components); + + update_context_->update_items.reserve(crx_components.size()); + + for (size_t i = 0; i != crx_components.size(); ++i) { + scoped_ptr<CrxUpdateItem> item(new CrxUpdateItem); + const CrxComponent& crx_component = crx_components[i]; + + item->id = GetCrxComponentID(crx_component); + item->component = crx_component; + item->last_check = base::Time::Now(); + item->crx_urls.clear(); + item->crx_diffurls.clear(); + item->previous_version = crx_component.version; + item->next_version = Version(); + item->previous_fp = crx_component.fingerprint; + item->next_fp.clear(); + item->diff_update_failed = false; + item->error_category = 0; + item->error_code = 0; + item->extra_code1 = 0; + item->diff_error_category = 0; + item->diff_error_code = 0; + item->diff_extra_code1 = 0; + item->download_metrics.clear(); + + ChangeItemState(item.get(), CrxUpdateItem::State::kChecking); + + update_context_->update_items.push_back(item.release()); + } + + update_checker_->CheckForUpdates( + update_context_->update_items, extra_request_parameters_, + base::Bind(&ActionUpdateCheck::UpdateCheckComplete, + base::Unretained(this))); +} + +void ActionUpdateCheck::UpdateCheckComplete( + const GURL& original_url, + int error, + const std::string& error_message, + const UpdateResponse::Results& results) { + DCHECK(thread_checker_.CalledOnValidThread()); + + VLOG(1) << "Update check completed from: " << original_url.spec(); + + if (!error) + OnUpdateCheckSucceeded(results); + else + OnUpdateCheckFailed(error, error_message); +} + +void ActionUpdateCheck::OnUpdateCheckSucceeded( + const UpdateResponse::Results& results) { + DCHECK(thread_checker_.CalledOnValidThread()); + VLOG(1) << "Update check succeeded."; + std::vector<UpdateResponse::Result>::const_iterator it; + for (it = results.list.begin(); it != results.list.end(); ++it) { + CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); + if (!crx) + continue; + + if (crx->state != CrxUpdateItem::State::kChecking) { + NOTREACHED(); + continue; // Not updating this CRX now. + } + + if (it->manifest.version.empty()) { + // No version means no update available. + ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); + VLOG(1) << "No update available for CRX: " << crx->id; + continue; + } + + if (!IsVersionNewer(crx->component.version, it->manifest.version)) { + // The CRX is up to date. + ChangeItemState(crx, CrxUpdateItem::State::kUpToDate); + VLOG(1) << "Component already up-to-date: " << crx->id; + continue; + } + + if (!it->manifest.browser_min_version.empty()) { + if (IsVersionNewer(browser_version_, it->manifest.browser_min_version)) { + // The CRX is not compatible with this Chrome version. + VLOG(1) << "Ignoring incompatible CRX: " << crx->id; + ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); + continue; + } + } + + if (it->manifest.packages.size() != 1) { + // Assume one and only one package per CRX. + VLOG(1) << "Ignoring multiple packages for CRX: " << crx->id; + ChangeItemState(crx, CrxUpdateItem::State::kNoUpdate); + continue; + } + + // Parse the members of the result and queue an upgrade for this CRX. + crx->next_version = Version(it->manifest.version); + + VLOG(1) << "Update found for CRX: " << crx->id; + + const auto& package(it->manifest.packages[0]); + crx->next_fp = package.fingerprint; + + // Resolve the urls by combining the base urls with the package names. + for (size_t i = 0; i != it->crx_urls.size(); ++i) { + const GURL url(it->crx_urls[i].Resolve(package.name)); + if (url.is_valid()) + crx->crx_urls.push_back(url); + } + for (size_t i = 0; i != it->crx_diffurls.size(); ++i) { + const GURL url(it->crx_diffurls[i].Resolve(package.namediff)); + if (url.is_valid()) + crx->crx_diffurls.push_back(url); + } + + ChangeItemState(crx, CrxUpdateItem::State::kCanUpdate); + + update_context_->queue.push(crx->id); + } + + // All components that are not included in the update response are + // considered up to date. + ChangeAllItemsState(CrxUpdateItem::State::kChecking, + CrxUpdateItem::State::kUpToDate); + + if (update_context_->queue.empty()) { + VLOG(1) << "Update check completed but no update is needed."; + UpdateComplete(0); + return; + } + + // Starts the execution flow of updating the CRXs in this context. + UpdateCrx(); +} + +void ActionUpdateCheck::OnUpdateCheckFailed(int error, + const std::string& error_message) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(error); + + VLOG(1) << "Update check failed." << error; + + UpdateComplete(error); +} + +} // namespace update_client |