1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_COMPONENT_UPDATER_CRX_DOWNLOADER_H_ 6 #define CHROME_BROWSER_COMPONENT_UPDATER_CRX_DOWNLOADER_H_ 7 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/callback.h" 12 #include "base/files/file_path.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/sequenced_task_runner.h" 16 #include "url/gurl.h" 17 18 namespace net { 19 class URLRequestContextGetter; 20 } 21 22 namespace component_updater { 23 24 // Defines a download interface for downloading components, with retrying on 25 // fallback urls in case of errors. This class implements a chain of 26 // responsibility design pattern. It can give successors in the chain a chance 27 // to handle a download request, until one of them succeeds, or there are no 28 // more urls or successors to try. A callback is always called at the end of 29 // the download, one time only. 30 // When multiple urls and downloaders exists, first all the urls are tried, in 31 // the order they are provided in the StartDownload function argument. After 32 // that, the download request is routed to the next downloader in the chain. 33 // The members of this class expect to be called from the UI thread only. 34 class CrxDownloader { 35 public: 36 struct DownloadMetrics { 37 enum Downloader { kNone = 0, kUrlFetcher, kBits }; 38 39 DownloadMetrics(); 40 41 GURL url; 42 43 Downloader downloader; 44 45 int error; 46 47 int64 downloaded_bytes; // -1 means that the byte count is unknown. 48 int64 total_bytes; 49 50 uint64 download_time_ms; 51 }; 52 53 // Contains the progress or the outcome of the download. 54 struct Result { 55 Result(); 56 57 // Download error: 0 indicates success. 58 int error; 59 60 // Path of the downloaded file if the download was successful. 61 base::FilePath response; 62 63 // Number of bytes actually downloaded, not including the bytes downloaded 64 // as a result of falling back on urls. 65 int64 downloaded_bytes; 66 67 // Number of bytes expected to be downloaded. 68 int64 total_bytes; 69 }; 70 71 // The callback fires only once, regardless of how many urls are tried, and 72 // how many successors in the chain of downloaders have handled the 73 // download. The callback interface can be extended if needed to provide 74 // more visibility into how the download has been handled, including 75 // specific error codes and download metrics. 76 typedef base::Callback<void(const Result& result)> DownloadCallback; 77 78 // The callback may fire 0 or many times during a download. Since this 79 // class implements a chain of responsibility, the callback can fire for 80 // different urls and different downloaders. The number of actual downloaded 81 // bytes is not guaranteed to monotonically increment over time. 82 typedef base::Callback<void(const Result& result)> ProgressCallback; 83 84 // Factory method to create an instance of this class and build the 85 // chain of responsibility. |is_background_download| specifies that a 86 // background downloader be used, if the platform supports it. 87 static CrxDownloader* Create( 88 bool is_background_download, 89 net::URLRequestContextGetter* context_getter, 90 scoped_refptr<base::SequencedTaskRunner> task_runner); 91 virtual ~CrxDownloader(); 92 93 void set_progress_callback(const ProgressCallback& progress_callback); 94 95 // Starts the download. One instance of the class handles one download only. 96 // One instance of CrxDownloader can only be started once, otherwise the 97 // behavior is undefined. The callback gets invoked if the download can't 98 // be started. 99 void StartDownloadFromUrl(const GURL& url, 100 const DownloadCallback& download_callback); 101 void StartDownload(const std::vector<GURL>& urls, 102 const DownloadCallback& download_callback); 103 104 const std::vector<DownloadMetrics> download_metrics() const; 105 106 protected: 107 explicit CrxDownloader(scoped_ptr<CrxDownloader> successor); 108 109 // Handles the fallback in the case of multiple urls and routing of the 110 // download to the following successor in the chain. Derived classes must call 111 // this function after each attempt at downloading the urls provided 112 // in the StartDownload function. 113 // In case of errors, |is_handled| indicates that a server side error has 114 // occured for the current url and the url should not be retried down 115 // the chain to avoid DDOS of the server. This url will be removed from the 116 // list of url and never tried again. 117 void OnDownloadComplete(bool is_handled, 118 const Result& result, 119 const DownloadMetrics& download_metrics); 120 121 // Calls the callback when progress is made. 122 void OnDownloadProgress(const Result& result); 123 124 // Returns the url which is currently being downloaded from. 125 GURL url() const; 126 127 private: 128 virtual void DoStartDownload(const GURL& url) = 0; 129 130 std::vector<GURL> urls_; 131 scoped_ptr<CrxDownloader> successor_; 132 DownloadCallback download_callback_; 133 ProgressCallback progress_callback_; 134 135 std::vector<GURL>::iterator current_url_; 136 137 std::vector<DownloadMetrics> download_metrics_; 138 139 DISALLOW_COPY_AND_ASSIGN(CrxDownloader); 140 }; 141 142 } // namespace component_updater 143 144 #endif // CHROME_BROWSER_COMPONENT_UPDATER_CRX_DOWNLOADER_H_ 145