summaryrefslogtreecommitdiffstats
path: root/components/update_client/action_update_check.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/update_client/action_update_check.cc')
-rw-r--r--components/update_client/action_update_check.cc204
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