Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/component_updater/crx_downloader.h" | 5 #include "chrome/browser/component_updater/crx_downloader.h" |
| 6 #include "chrome/browser/component_updater/url_fetcher_downloader.h" | 6 #include "chrome/browser/component_updater/url_fetcher_downloader.h" |
| 7 #include "content/public/browser/browser_thread.h" | 7 #include "content/public/browser/browser_thread.h" |
| 8 | 8 |
| 9 #if defined(OS_WIN) | |
| 10 #include "chrome/browser/component_updater/background_downloader_win.h" | |
| 11 #endif | |
| 12 | |
| 9 using content::BrowserThread; | 13 using content::BrowserThread; |
| 10 | 14 |
| 11 namespace component_updater { | 15 namespace component_updater { |
| 12 | 16 |
| 13 // This factory method builds the chain of downloaders. Currently, there is only | 17 // On Windows, the first downloader in the chain is a background downloader, |
| 14 // a url fetcher downloader but more downloaders can be chained up to handle | 18 // which uses the BITS service. |
| 15 // the request. | |
| 16 CrxDownloader* CrxDownloader::Create( | 19 CrxDownloader* CrxDownloader::Create( |
| 20 bool is_background_download, | |
| 17 net::URLRequestContextGetter* context_getter, | 21 net::URLRequestContextGetter* context_getter, |
| 18 scoped_refptr<base::SequencedTaskRunner> task_runner, | 22 scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 19 const DownloadCallback& download_callback) { | 23 const DownloadCallback& download_callback) { |
| 20 CrxDownloader* crx_downloader = | 24 scoped_ptr<CrxDownloader> url_fetcher_downloader( |
| 21 new UrlFetcherDownloader(context_getter, task_runner); | 25 new UrlFetcherDownloader(scoped_ptr<CrxDownloader>().Pass(), |
| 26 context_getter, | |
| 27 task_runner, | |
| 28 download_callback)); | |
| 29 #if defined (OS_WIN) | |
| 30 if (is_background_download) { | |
| 31 return new BackgroundDownloader(url_fetcher_downloader.Pass(), | |
| 32 context_getter, | |
| 33 task_runner, | |
| 34 download_callback); | |
| 35 } | |
| 36 #endif | |
| 22 | 37 |
| 23 crx_downloader->download_callback_ = download_callback; | 38 return url_fetcher_downloader.release(); |
| 24 | |
| 25 return crx_downloader; | |
| 26 } | 39 } |
| 27 | 40 |
| 28 CrxDownloader::CrxDownloader() : current_url_(0) { | 41 CrxDownloader::CrxDownloader( |
| 29 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 42 scoped_ptr<CrxDownloader> successor, |
| 43 const DownloadCallback& download_callback) | |
| 44 : is_active_(false), | |
| 45 successor_(successor.Pass()), | |
| 46 download_callback_(download_callback) { | |
| 47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 30 } | 48 } |
| 31 | 49 |
| 32 CrxDownloader::~CrxDownloader() { | 50 CrxDownloader::~CrxDownloader() { |
| 33 } | 51 } |
| 34 | 52 |
| 35 void CrxDownloader::StartDownloadFromUrl(const GURL& url) { | 53 bool CrxDownloader::StartDownloadFromUrl(const GURL& url) { |
| 36 std::vector<GURL> urls; | 54 std::vector<GURL> urls; |
| 37 urls.push_back(url); | 55 urls.push_back(url); |
| 38 StartDownload(urls); | 56 return StartDownload(urls); |
| 39 } | 57 } |
| 40 | 58 |
| 41 void CrxDownloader::StartDownload(const std::vector<GURL>& urls) { | 59 bool CrxDownloader::StartDownload(const std::vector<GURL>& urls) { |
| 42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 43 | 61 |
| 44 if (urls.empty()) | 62 if (urls.empty() || is_active_) |
| 45 return; | 63 return false; |
| 64 | |
| 65 // |is_active_| defensively protects against mutating the container of urls | |
| 66 // once the download has started. | |
| 67 is_active_ = true; | |
| 46 | 68 |
| 47 urls_ = urls; | 69 urls_ = urls; |
| 70 current_url_ = urls_.begin(); | |
| 48 | 71 |
| 49 current_url_ = 0; | 72 DoStartDownload(*current_url_); |
| 50 DoStartDownload(urls[current_url_]); | 73 return true; |
| 51 } | 74 } |
| 52 | 75 |
| 53 // Handles the fallback in the case of multiple urls and routing of the | 76 void CrxDownloader::OnDownloadComplete(bool is_handled, const Result& result) { |
| 54 // download to the following successor in the chain. | |
| 55 void CrxDownloader::OnDownloadComplete(bool is_handled, | |
| 56 int error, | |
| 57 const base::FilePath& response) { | |
| 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 59 | 78 |
| 60 // If an error has occured, try the next url if possible, then move on | 79 // If an error has occured, try the next url if there is any, then move on |
| 61 // to the successor in the chain, if the request has not been handled | 80 // to the successor in the chain if the request has not been handled. |
| 62 if (error) { | 81 // In the case of an error, and if the downloader has received a 5xx error, as |
| 63 ++current_url_; | 82 // indicated by the |is_handled| flag, remove that url from the list of |
| 64 if (current_url_ != urls_.size()) { | 83 // urls so the url is not handed over to the successor. |
| 65 DoStartDownload(urls_[current_url_]); | 84 if (result.error) { |
| 85 if (!is_handled) | |
| 86 ++current_url_; | |
| 87 else | |
| 88 current_url_ = urls_.erase(current_url_); | |
| 89 | |
| 90 if (current_url_ != urls_.end()) { | |
| 91 DoStartDownload(*current_url_); | |
| 66 return; | 92 return; |
| 67 } | 93 } |
| 68 | 94 |
| 69 if (!is_handled && successor_) { | 95 if (!is_handled && successor_) { |
| 70 successor_->StartDownload(urls_); | 96 successor_->StartDownload(urls_); |
|
waffles
2013/12/05 01:15:07
What if this guy returns false?
I think this won'
Sorin Jianu
2013/12/05 01:43:07
I will like to get rid of the is_active_ defensive
| |
| 71 return; | 97 return; |
| 72 } | 98 } |
| 73 } | 99 } |
| 74 | 100 |
| 75 DCHECK(is_handled || !error || !successor_); | 101 DCHECK(is_handled || !result.error || !successor_); |
| 76 | 102 |
| 77 download_callback_.Run(error, response); | 103 download_callback_.Run(result); |
| 78 } | 104 } |
| 79 | 105 |
| 80 } // namespace component_updater | 106 } // namespace component_updater |
| 81 | 107 |
| OLD | NEW |