103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/crx_downloader.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/sequenced_task_runner.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/single_thread_task_runner.h" 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/url_fetcher_downloader.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN) 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/background_downloader_win.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace component_updater { 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)CrxDownloader::Result::Result() 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : error(0), downloaded_bytes(-1), total_bytes(-1) { 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CrxDownloader::DownloadMetrics::DownloadMetrics() 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : downloader(kNone), 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error(0), 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) downloaded_bytes(-1), 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) total_bytes(-1), 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) download_time_ms(0) { 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// On Windows, the first downloader in the chain is a background downloader, 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// which uses the BITS service. 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)CrxDownloader* CrxDownloader::Create( 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool is_background_download, 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) net::URLRequestContextGetter* context_getter, 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> url_fetcher_task_runner, 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> background_task_runner) { 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<CrxDownloader> url_fetcher_downloader( 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new UrlFetcherDownloader(scoped_ptr<CrxDownloader>().Pass(), 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context_getter, 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher_task_runner)); 41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_WIN) 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (is_background_download) { 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new BackgroundDownloader( 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher_downloader.Pass(), context_getter, background_task_runner); 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return url_fetcher_downloader.release(); 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuCrxDownloader::CrxDownloader(scoped_ptr<CrxDownloader> successor) 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : successor_(successor.Pass()) { 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)CrxDownloader::~CrxDownloader() { 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void CrxDownloader::set_progress_callback( 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ProgressCallback& progress_callback) { 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) progress_callback_ = progress_callback; 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GURL CrxDownloader::url() const { 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return current_url_ != urls_.end() ? *current_url_ : GURL(); 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const std::vector<CrxDownloader::DownloadMetrics> 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CrxDownloader::download_metrics() const { 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!successor_) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return download_metrics_; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<DownloadMetrics> retval(successor_->download_metrics()); 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) retval.insert( 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) retval.begin(), download_metrics_.begin(), download_metrics_.end()); 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return retval; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid CrxDownloader::StartDownloadFromUrl( 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const GURL& url, 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const DownloadCallback& download_callback) { 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<GURL> urls; 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) urls.push_back(url); 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu StartDownload(urls, download_callback); 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid CrxDownloader::StartDownload(const std::vector<GURL>& urls, 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const DownloadCallback& download_callback) { 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (urls.empty()) { 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Make a result and complete the download with a generic error for now. 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Result result; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.error = -1; 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu download_callback.Run(result); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If the urls are mutated while this downloader is active, then the 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // behavior is undefined in the sense that the outcome of the download could 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // be inconsistent for the list of urls. At any rate, the |current_url_| is 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // reset at this point, and the iterator will be valid in all conditions. 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) urls_ = urls; 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) current_url_ = urls_.begin(); 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu download_callback_ = download_callback; 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DoStartDownload(*current_url_); 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CrxDownloader::OnDownloadComplete( 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_handled, 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Result& result, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DownloadMetrics& download_metrics) { 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) download_metrics_.push_back(download_metrics); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (result.error) { 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If an error has occured, in general try the next url if there is any, 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // then move on to the successor in the chain if there is any successor. 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If this downloader has received a 5xx error for the current url, 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // as indicated by the |is_handled| flag, remove that url from the list of 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // urls so the url is never retried. In both cases, move on to the 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // next url. 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!is_handled) { 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++current_url_; 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) current_url_ = urls_.erase(current_url_); 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Try downloading from another url from the list. 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (current_url_ != urls_.end()) { 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DoStartDownload(*current_url_); 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If there is another downloader that can accept this request, then hand 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the request over to it so that the successor can try the pruned list 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // of urls. Otherwise, the request ends here since the current downloader 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // has tried all urls and it can't fall back on any other downloader. 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (successor_ && !urls_.empty()) { 1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu successor_->StartDownload(urls_, download_callback_); 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) download_callback_.Run(result); 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void CrxDownloader::OnDownloadProgress(const Result& result) { 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (progress_callback_.is_null()) 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) progress_callback_.Run(result); 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace component_updater 159