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 { 38 kNone = 0, 39 kUrlFetcher, 40 kBits 41 }; 42 43 DownloadMetrics(); 44 45 GURL url; 46 47 Downloader downloader; 48 49 int error; 50 51 int64 bytes_downloaded; // -1 means that the byte count is unknown. 52 int64 bytes_total; 53 54 uint64 download_time_ms; 55 }; 56 57 // Contains the outcome of the download. 58 struct Result { 59 Result(); 60 61 // Download error: 0 indicates success. 62 int error; 63 64 // Path of the downloaded file if the download was successful. 65 base::FilePath response; 66 }; 67 68 // The callback fires only once, regardless of how many urls are tried, and 69 // how many successors in the chain of downloaders have handled the 70 // download. The callback interface can be extended if needed to provide 71 // more visibility into how the download has been handled, including 72 // specific error codes and download metrics. 73 typedef base::Callback<void (const Result& result)> DownloadCallback; 74 75 // Factory method to create an instance of this class and build the 76 // chain of responsibility. |is_background_download| specifies that a 77 // background downloader be used, if the platform supports it. 78 static CrxDownloader* Create( 79 bool is_background_download, 80 net::URLRequestContextGetter* context_getter, 81 scoped_refptr<base::SequencedTaskRunner> task_runner, 82 const DownloadCallback& download_callback); 83 virtual ~CrxDownloader(); 84 85 // Starts the download. One instance of the class handles one download only. 86 // One instance of CrxDownloader can only be started once, otherwise the 87 // behavior is undefined. The callback gets invoked if the download can't 88 // be started. 89 void StartDownloadFromUrl(const GURL& url); 90 void StartDownload(const std::vector<GURL>& urls); 91 92 const std::vector<DownloadMetrics> download_metrics() const; 93 94 protected: 95 CrxDownloader(scoped_ptr<CrxDownloader> successor, 96 const DownloadCallback& download_callback); 97 98 // Handles the fallback in the case of multiple urls and routing of the 99 // download to the following successor in the chain. Derived classes must call 100 // this function after each attempt at downloading the urls provided 101 // in the StartDownload function. 102 // In case of errors, |is_handled| indicates that a server side error has 103 // occured for the current url and the url should not be retried down 104 // the chain to avoid DDOS of the server. This url will be removed from the 105 // list of url and never tried again. 106 void OnDownloadComplete(bool is_handled, 107 const Result& result, 108 const DownloadMetrics& download_metrics); 109 110 // Returns the url which is currently downloaded from. 111 GURL url() const; 112 113 private: 114 virtual void DoStartDownload(const GURL& url) = 0; 115 116 std::vector<GURL> urls_; 117 scoped_ptr<CrxDownloader> successor_; 118 DownloadCallback download_callback_; 119 120 std::vector<GURL>::iterator current_url_; 121 122 std::vector<DownloadMetrics> download_metrics_; 123 124 DISALLOW_COPY_AND_ASSIGN(CrxDownloader); 125 }; 126 127 } // namespace component_updater 128 129 #endif // CHROME_BROWSER_COMPONENT_UPDATER_CRX_DOWNLOADER_H_ 130 131