Index: components/update_client/update_checker.cc |
diff --git a/components/update_client/update_checker.cc b/components/update_client/update_checker.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9a38a5a4238a362a3939d2e5d0a34510e1d499ef |
--- /dev/null |
+++ b/components/update_client/update_checker.cc |
@@ -0,0 +1,163 @@ |
+// Copyright 2014 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/update_checker.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/compiler_specific.h" |
+#include "base/location.h" |
+#include "base/logging.h" |
+#include "base/macros.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/threading/thread_checker.h" |
+#include "components/update_client/configurator.h" |
+#include "components/update_client/crx_update_item.h" |
+#include "components/update_client/request_sender.h" |
+#include "components/update_client/utils.h" |
+#include "net/url_request/url_fetcher.h" |
+#include "url/gurl.h" |
+ |
+namespace update_client { |
+ |
+namespace { |
+ |
+// Builds an update check request for |components|. |additional_attributes| is |
+// serialized as part of the <request> element of the request to customize it |
+// with data that is not platform or component specific. For each |item|, a |
+// corresponding <app> element is created and inserted as a child node of |
+// the <request>. |
+// |
+// An app element looks like this: |
+// <app appid="hnimpnehoodheedghdeeijklkeaacbdc" |
+// version="0.1.2.3" installsource="ondemand"> |
+// <updatecheck /> |
+// <packages> |
+// <package fp="abcd" /> |
+// </packages> |
+// </app> |
+std::string BuildUpdateCheckRequest(const Configurator& config, |
+ const std::vector<CrxUpdateItem*>& items, |
+ const std::string& additional_attributes) { |
+ std::string app_elements; |
+ for (size_t i = 0; i != items.size(); ++i) { |
+ const CrxUpdateItem* item = items[i]; |
+ std::string app("<app "); |
+ base::StringAppendF(&app, "appid=\"%s\" version=\"%s\"", item->id.c_str(), |
+ item->component.version.GetString().c_str()); |
+ if (item->on_demand) |
+ base::StringAppendF(&app, " installsource=\"ondemand\""); |
+ base::StringAppendF(&app, ">"); |
+ base::StringAppendF(&app, "<updatecheck />"); |
+ if (!item->component.fingerprint.empty()) { |
+ base::StringAppendF(&app, |
+ "<packages>" |
+ "<package fp=\"%s\"/>" |
+ "</packages>", |
+ item->component.fingerprint.c_str()); |
+ } |
+ base::StringAppendF(&app, "</app>"); |
+ app_elements.append(app); |
+ VLOG(1) << "Appending to update request: " << app; |
+ } |
+ |
+ return BuildProtocolRequest(config.GetBrowserVersion().GetString(), |
+ config.GetChannel(), config.GetLang(), |
+ config.GetOSLongName(), app_elements, |
+ additional_attributes); |
+} |
+ |
+class UpdateCheckerImpl : public UpdateChecker { |
+ public: |
+ explicit UpdateCheckerImpl(const Configurator& config); |
+ ~UpdateCheckerImpl() override; |
+ |
+ // Overrides for UpdateChecker. |
+ bool CheckForUpdates( |
+ const std::vector<CrxUpdateItem*>& items_to_check, |
+ const std::string& additional_attributes, |
+ const UpdateCheckCallback& update_check_callback) override; |
+ |
+ private: |
+ void OnRequestSenderComplete(const net::URLFetcher* source); |
+ |
+ const Configurator& config_; |
+ UpdateCheckCallback update_check_callback_; |
+ scoped_ptr<RequestSender> request_sender_; |
+ |
+ base::ThreadChecker thread_checker_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(UpdateCheckerImpl); |
+}; |
+ |
+UpdateCheckerImpl::UpdateCheckerImpl(const Configurator& config) |
+ : config_(config) { |
+} |
+ |
+UpdateCheckerImpl::~UpdateCheckerImpl() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+} |
+ |
+bool UpdateCheckerImpl::CheckForUpdates( |
+ const std::vector<CrxUpdateItem*>& items_to_check, |
+ const std::string& additional_attributes, |
+ const UpdateCheckCallback& update_check_callback) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (request_sender_.get()) { |
+ NOTREACHED(); |
+ return false; // Another update check is in progress. |
+ } |
+ |
+ update_check_callback_ = update_check_callback; |
+ |
+ request_sender_.reset(new RequestSender(config_)); |
+ request_sender_->Send( |
+ BuildUpdateCheckRequest(config_, items_to_check, additional_attributes), |
+ config_.UpdateUrl(), |
+ base::Bind(&UpdateCheckerImpl::OnRequestSenderComplete, |
+ base::Unretained(this))); |
+ return true; |
+} |
+ |
+void UpdateCheckerImpl::OnRequestSenderComplete(const net::URLFetcher* source) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ const GURL original_url(source->GetOriginalURL()); |
+ VLOG(1) << "Update check request went to: " << original_url.spec(); |
+ |
+ int error = 0; |
+ std::string error_message; |
+ UpdateResponse update_response; |
+ |
+ if (FetchSuccess(*source)) { |
+ std::string xml; |
+ source->GetResponseAsString(&xml); |
+ if (!update_response.Parse(xml)) { |
+ error = -1; |
+ error_message = update_response.errors(); |
+ VLOG(1) << "Update request failed: " << error_message; |
+ } |
+ } else { |
+ error = GetFetchError(*source); |
+ error_message.assign("network error"); |
+ VLOG(1) << "Update request failed: network error"; |
+ } |
+ |
+ request_sender_.reset(); |
+ update_check_callback_.Run(original_url, error, error_message, |
+ update_response.results()); |
+} |
+ |
+} // namespace |
+ |
+scoped_ptr<UpdateChecker> UpdateChecker::Create(const Configurator& config) { |
+ return scoped_ptr<UpdateChecker>(new UpdateCheckerImpl(config)); |
+} |
+ |
+} // namespace update_client |