Componentize component_updater: Move over a bunch of files to the component.
BUG=371463
Review URL: https://codereview.chromium.org/449643002
Cr-Commit-Position: refs/heads/master@{#290499}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@290499 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/components/component_updater/crx_downloader.cc b/components/component_updater/crx_downloader.cc
new file mode 100644
index 0000000..b56b397
--- /dev/null
+++ b/components/component_updater/crx_downloader.cc
@@ -0,0 +1,158 @@
+// 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/component_updater/crx_downloader.h"
+
+#include "base/logging.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "components/component_updater/url_fetcher_downloader.h"
+
+#if defined(OS_WIN)
+#include "components/component_updater/background_downloader_win.h"
+#endif
+
+namespace component_updater {
+
+CrxDownloader::Result::Result()
+ : error(0), downloaded_bytes(-1), total_bytes(-1) {
+}
+
+CrxDownloader::DownloadMetrics::DownloadMetrics()
+ : downloader(kNone),
+ error(0),
+ downloaded_bytes(-1),
+ total_bytes(-1),
+ download_time_ms(0) {
+}
+
+// On Windows, the first downloader in the chain is a background downloader,
+// which uses the BITS service.
+CrxDownloader* CrxDownloader::Create(
+ bool is_background_download,
+ net::URLRequestContextGetter* context_getter,
+ scoped_refptr<base::SequencedTaskRunner> url_fetcher_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> background_task_runner) {
+ scoped_ptr<CrxDownloader> url_fetcher_downloader(
+ new UrlFetcherDownloader(scoped_ptr<CrxDownloader>().Pass(),
+ context_getter,
+ url_fetcher_task_runner));
+#if defined(OS_WIN)
+ if (is_background_download) {
+ return new BackgroundDownloader(
+ url_fetcher_downloader.Pass(), context_getter, background_task_runner);
+ }
+#endif
+
+ return url_fetcher_downloader.release();
+}
+
+CrxDownloader::CrxDownloader(scoped_ptr<CrxDownloader> successor)
+ : successor_(successor.Pass()) {
+}
+
+CrxDownloader::~CrxDownloader() {
+}
+
+void CrxDownloader::set_progress_callback(
+ const ProgressCallback& progress_callback) {
+ progress_callback_ = progress_callback;
+}
+
+GURL CrxDownloader::url() const {
+ return current_url_ != urls_.end() ? *current_url_ : GURL();
+}
+
+const std::vector<CrxDownloader::DownloadMetrics>
+CrxDownloader::download_metrics() const {
+ if (!successor_)
+ return download_metrics_;
+
+ std::vector<DownloadMetrics> retval(successor_->download_metrics());
+ retval.insert(
+ retval.begin(), download_metrics_.begin(), download_metrics_.end());
+ return retval;
+}
+
+void CrxDownloader::StartDownloadFromUrl(
+ const GURL& url,
+ const DownloadCallback& download_callback) {
+ std::vector<GURL> urls;
+ urls.push_back(url);
+ StartDownload(urls, download_callback);
+}
+
+void CrxDownloader::StartDownload(const std::vector<GURL>& urls,
+ const DownloadCallback& download_callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (urls.empty()) {
+ // Make a result and complete the download with a generic error for now.
+ Result result;
+ result.error = -1;
+ download_callback.Run(result);
+ return;
+ }
+
+ // If the urls are mutated while this downloader is active, then the
+ // behavior is undefined in the sense that the outcome of the download could
+ // be inconsistent for the list of urls. At any rate, the |current_url_| is
+ // reset at this point, and the iterator will be valid in all conditions.
+ urls_ = urls;
+ current_url_ = urls_.begin();
+ download_callback_ = download_callback;
+
+ DoStartDownload(*current_url_);
+}
+
+void CrxDownloader::OnDownloadComplete(
+ bool is_handled,
+ const Result& result,
+ const DownloadMetrics& download_metrics) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ download_metrics_.push_back(download_metrics);
+
+ if (result.error) {
+ // If an error has occured, in general try the next url if there is any,
+ // then move on to the successor in the chain if there is any successor.
+ // If this downloader has received a 5xx error for the current url,
+ // as indicated by the |is_handled| flag, remove that url from the list of
+ // urls so the url is never retried. In both cases, move on to the
+ // next url.
+ if (!is_handled) {
+ ++current_url_;
+ } else {
+ current_url_ = urls_.erase(current_url_);
+ }
+
+ // Try downloading from another url from the list.
+ if (current_url_ != urls_.end()) {
+ DoStartDownload(*current_url_);
+ return;
+ }
+
+ // If there is another downloader that can accept this request, then hand
+ // the request over to it so that the successor can try the pruned list
+ // of urls. Otherwise, the request ends here since the current downloader
+ // has tried all urls and it can't fall back on any other downloader.
+ if (successor_ && !urls_.empty()) {
+ successor_->StartDownload(urls_, download_callback_);
+ return;
+ }
+ }
+
+ download_callback_.Run(result);
+}
+
+void CrxDownloader::OnDownloadProgress(const Result& result) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (progress_callback_.is_null())
+ return;
+
+ progress_callback_.Run(result);
+}
+
+} // namespace component_updater