blob: ac8b2405dc90375bb2272875e567905b12e17620 [file] [log] [blame]
[email protected]32a83d132013-12-12 13:53:021// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]afa378f22013-12-02 03:37:542// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/component_updater/crx_downloader.h"
6#include "chrome/browser/component_updater/url_fetcher_downloader.h"
7#include "content/public/browser/browser_thread.h"
8
[email protected]3cb2a4f2013-12-07 21:54:349#if defined(OS_WIN)
10#include "chrome/browser/component_updater/background_downloader_win.h"
11#endif
12
[email protected]afa378f22013-12-02 03:37:5413using content::BrowserThread;
14
15namespace component_updater {
16
[email protected]3a0092d2013-12-18 03:04:3517CrxDownloader::Result::Result() : error(0) {}
18
19CrxDownloader::DownloadMetrics::DownloadMetrics()
20 : downloader(kNone),
21 error(0),
22 bytes_downloaded(0),
23 bytes_total(0),
24 download_time_ms(0) {}
25
[email protected]3cb2a4f2013-12-07 21:54:3426// On Windows, the first downloader in the chain is a background downloader,
27// which uses the BITS service.
[email protected]afa378f22013-12-02 03:37:5428CrxDownloader* CrxDownloader::Create(
[email protected]3cb2a4f2013-12-07 21:54:3429 bool is_background_download,
[email protected]afa378f22013-12-02 03:37:5430 net::URLRequestContextGetter* context_getter,
31 scoped_refptr<base::SequencedTaskRunner> task_runner,
32 const DownloadCallback& download_callback) {
[email protected]3cb2a4f2013-12-07 21:54:3433 scoped_ptr<CrxDownloader> url_fetcher_downloader(
34 new UrlFetcherDownloader(scoped_ptr<CrxDownloader>().Pass(),
35 context_getter,
36 task_runner,
37 download_callback));
38#if defined (OS_WIN)
39 if (is_background_download) {
40 return new BackgroundDownloader(url_fetcher_downloader.Pass(),
41 context_getter,
42 task_runner,
43 download_callback);
44 }
45#endif
[email protected]afa378f22013-12-02 03:37:5446
[email protected]3cb2a4f2013-12-07 21:54:3447 return url_fetcher_downloader.release();
[email protected]afa378f22013-12-02 03:37:5448}
49
[email protected]3cb2a4f2013-12-07 21:54:3450CrxDownloader::CrxDownloader(
51 scoped_ptr<CrxDownloader> successor,
52 const DownloadCallback& download_callback)
53 : successor_(successor.Pass()),
54 download_callback_(download_callback) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]afa378f22013-12-02 03:37:5456}
57
58CrxDownloader::~CrxDownloader() {
59}
60
[email protected]3a0092d2013-12-18 03:04:3561GURL CrxDownloader::url() const {
62 return current_url_ != urls_.end() ? *current_url_ : GURL();
63}
64
65const std::vector<CrxDownloader::DownloadMetrics>
66CrxDownloader::download_metrics() const {
67 if (!successor_)
68 return download_metrics_;
69
70 std::vector<DownloadMetrics> retval(successor_->download_metrics());
71 retval.insert(retval.begin(),
72 download_metrics_.begin(),
73 download_metrics_.end());
74 return retval;
75}
76
[email protected]3cb2a4f2013-12-07 21:54:3477bool CrxDownloader::StartDownloadFromUrl(const GURL& url) {
[email protected]afa378f22013-12-02 03:37:5478 std::vector<GURL> urls;
79 urls.push_back(url);
[email protected]3cb2a4f2013-12-07 21:54:3480 return StartDownload(urls);
[email protected]afa378f22013-12-02 03:37:5481}
82
[email protected]3cb2a4f2013-12-07 21:54:3483bool CrxDownloader::StartDownload(const std::vector<GURL>& urls) {
[email protected]afa378f22013-12-02 03:37:5484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
85
86 if (urls.empty())
[email protected]3cb2a4f2013-12-07 21:54:3487 return false;
[email protected]afa378f22013-12-02 03:37:5488
[email protected]3cb2a4f2013-12-07 21:54:3489 // If the urls are mutated while this downloader is active, then the
90 // behavior is undefined in the sense that the outcome of the download could
91 // be inconsistent for the list of urls. At any rate, the |current_url_| is
92 // reset at this point, and the iterator will be valid in all conditions.
[email protected]afa378f22013-12-02 03:37:5493 urls_ = urls;
[email protected]3cb2a4f2013-12-07 21:54:3494 current_url_ = urls_.begin();
[email protected]afa378f22013-12-02 03:37:5495
[email protected]3cb2a4f2013-12-07 21:54:3496 DoStartDownload(*current_url_);
97 return true;
[email protected]afa378f22013-12-02 03:37:5498}
99
[email protected]3a0092d2013-12-18 03:04:35100void CrxDownloader::OnDownloadComplete(
101 bool is_handled,
102 const Result& result,
103 const DownloadMetrics& download_metrics) {
[email protected]afa378f22013-12-02 03:37:54104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105
[email protected]3a0092d2013-12-18 03:04:35106 download_metrics_.push_back(download_metrics);
107
[email protected]3cb2a4f2013-12-07 21:54:34108 if (result.error) {
109 // If an error has occured, in general try the next url if there is any,
110 // then move on to the successor in the chain if there is any successor.
111 // If this downloader has received a 5xx error for the current url,
112 // as indicated by the |is_handled| flag, remove that url from the list of
113 // urls so the url is never retried. In both cases, move on to the
114 // next url.
115 if (!is_handled) {
116 ++current_url_;
117 } else {
118 current_url_ = urls_.erase(current_url_);
119 }
120
121 // Try downloading from another url from the list.
122 if (current_url_ != urls_.end()) {
123 DoStartDownload(*current_url_);
[email protected]afa378f22013-12-02 03:37:54124 return;
125 }
126
[email protected]3cb2a4f2013-12-07 21:54:34127 // If there is another downloader that can accept this request, then hand
128 // the request over to it so that the successor can try the pruned list
129 // of urls. Otherwise, the request ends here since the current downloader
130 // has tried all urls and it can't fall back on any other downloader.
131 if (successor_ && successor_->StartDownload(urls_))
[email protected]afa378f22013-12-02 03:37:54132 return;
[email protected]afa378f22013-12-02 03:37:54133 }
134
[email protected]3cb2a4f2013-12-07 21:54:34135 download_callback_.Run(result);
[email protected]afa378f22013-12-02 03:37:54136}
137
138} // namespace component_updater
139