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 |