1 // Copyright (c) 2012 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_EXTENSIONS_UPDATER_EXTENSION_DOWNLOADER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_DOWNLOADER_H_ 7 8 #include <deque> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "base/basictypes.h" 16 #include "base/compiler_specific.h" 17 #include "base/memory/linked_ptr.h" 18 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/weak_ptr.h" 20 #include "base/version.h" 21 #include "chrome/browser/extensions/updater/extension_downloader_delegate.h" 22 #include "chrome/browser/extensions/updater/manifest_fetch_data.h" 23 #include "chrome/browser/extensions/updater/request_queue.h" 24 #include "chrome/common/extensions/update_manifest.h" 25 #include "extensions/common/extension.h" 26 #include "net/url_request/url_fetcher_delegate.h" 27 #include "url/gurl.h" 28 29 namespace net { 30 class URLFetcher; 31 class URLRequestContextGetter; 32 class URLRequestStatus; 33 } 34 35 namespace extensions { 36 37 struct UpdateDetails { 38 UpdateDetails(const std::string& id, const base::Version& version); 39 ~UpdateDetails(); 40 41 std::string id; 42 base::Version version; 43 }; 44 45 class ExtensionCache; 46 class ExtensionUpdaterTest; 47 48 // A class that checks for updates of a given list of extensions, and downloads 49 // the crx file when updates are found. It uses a |ExtensionDownloaderDelegate| 50 // that takes ownership of the downloaded crx files, and handles events during 51 // the update check. 52 class ExtensionDownloader : public net::URLFetcherDelegate { 53 public: 54 // |delegate| is stored as a raw pointer and must outlive the 55 // ExtensionDownloader. 56 ExtensionDownloader(ExtensionDownloaderDelegate* delegate, 57 net::URLRequestContextGetter* request_context); 58 virtual ~ExtensionDownloader(); 59 60 // Adds |extension| to the list of extensions to check for updates. 61 // Returns false if the |extension| can't be updated due to invalid details. 62 // In that case, no callbacks will be performed on the |delegate_|. 63 // The |request_id| is passed on as is to the various |delegate_| callbacks. 64 // This is used for example by ExtensionUpdater to keep track of when 65 // potentially concurrent update checks complete. 66 bool AddExtension(const Extension& extension, int request_id); 67 68 // Adds extension |id| to the list of extensions to check for updates. 69 // Returns false if the |id| can't be updated due to invalid details. 70 // In that case, no callbacks will be performed on the |delegate_|. 71 // The |request_id| is passed on as is to the various |delegate_| callbacks. 72 // This is used for example by ExtensionUpdater to keep track of when 73 // potentially concurrent update checks complete. 74 bool AddPendingExtension(const std::string& id, 75 const GURL& update_url, 76 int request_id); 77 78 // Schedules a fetch of the manifest of all the extensions added with 79 // AddExtension() and AddPendingExtension(). 80 void StartAllPending(ExtensionCache* cache); 81 82 // Schedules an update check of the blacklist. 83 void StartBlacklistUpdate(const std::string& version, 84 const ManifestFetchData::PingData& ping_data, 85 int request_id); 86 87 // These are needed for unit testing, to help identify the correct mock 88 // URLFetcher objects. 89 static const int kManifestFetcherId = 1; 90 static const int kExtensionFetcherId = 2; 91 92 // Update AppID for extension blacklist. 93 static const char kBlacklistAppID[]; 94 95 static const int kMaxRetries = 10; 96 97 private: 98 friend class ExtensionUpdaterTest; 99 100 // These counters are bumped as extensions are added to be fetched. They 101 // are then recorded as UMA metrics when all the extensions have been added. 102 struct URLStats { 103 URLStats() 104 : no_url_count(0), 105 google_url_count(0), 106 other_url_count(0), 107 extension_count(0), 108 theme_count(0), 109 app_count(0), 110 platform_app_count(0), 111 pending_count(0) {} 112 113 int no_url_count, google_url_count, other_url_count; 114 int extension_count, theme_count, app_count, platform_app_count, 115 pending_count; 116 }; 117 118 // We need to keep track of some information associated with a url 119 // when doing a fetch. 120 struct ExtensionFetch { 121 ExtensionFetch(); 122 ExtensionFetch(const std::string& id, const GURL& url, 123 const std::string& package_hash, const std::string& version, 124 const std::set<int>& request_ids); 125 ~ExtensionFetch(); 126 127 std::string id; 128 GURL url; 129 std::string package_hash; 130 std::string version; 131 std::set<int> request_ids; 132 133 // Indicates whether or not the fetch is known to require credentials. 134 bool is_protected; 135 }; 136 137 // Helper for AddExtension() and AddPendingExtension(). 138 bool AddExtensionData(const std::string& id, 139 const base::Version& version, 140 Manifest::Type extension_type, 141 const GURL& extension_update_url, 142 const std::string& update_url_data, 143 int request_id); 144 145 // Adds all recorded stats taken so far to histogram counts. 146 void ReportStats() const; 147 148 // Begins an update check. 149 void StartUpdateCheck(scoped_ptr<ManifestFetchData> fetch_data); 150 151 // Called by RequestQueue when a new manifest fetch request is started. 152 void CreateManifestFetcher(); 153 154 // net::URLFetcherDelegate implementation. 155 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 156 157 // Handles the result of a manifest fetch. 158 void OnManifestFetchComplete(const GURL& url, 159 const net::URLRequestStatus& status, 160 int response_code, 161 const base::TimeDelta& backoff_delay, 162 const std::string& data); 163 164 // Once a manifest is parsed, this starts fetches of any relevant crx files. 165 // If |results| is null, it means something went wrong when parsing it. 166 void HandleManifestResults(const ManifestFetchData& fetch_data, 167 const UpdateManifest::Results* results); 168 169 // Given a list of potential updates, returns the indices of the ones that are 170 // applicable (are actually a new version, etc.) in |result|. 171 void DetermineUpdates(const ManifestFetchData& fetch_data, 172 const UpdateManifest::Results& possible_updates, 173 std::vector<int>* result); 174 175 // Begins (or queues up) download of an updated extension. 176 void FetchUpdatedExtension(scoped_ptr<ExtensionFetch> fetch_data); 177 178 // Called by RequestQueue when a new extension fetch request is started. 179 void CreateExtensionFetcher(); 180 181 // Handles the result of a crx fetch. 182 void OnCRXFetchComplete(const net::URLFetcher* source, 183 const GURL& url, 184 const net::URLRequestStatus& status, 185 int response_code, 186 const base::TimeDelta& backoff_delay); 187 188 // Invokes OnExtensionDownloadFailed() on the |delegate_| for each extension 189 // in the set, with |error| as the reason for failure. 190 void NotifyExtensionsDownloadFailed(const std::set<std::string>& id_set, 191 const std::set<int>& request_ids, 192 ExtensionDownloaderDelegate::Error error); 193 194 // Send a notification that an update was found for |id| that we'll 195 // attempt to download. 196 void NotifyUpdateFound(const std::string& id, const std::string& version); 197 198 // Do real work of StartAllPending. If .crx cache is used, this function 199 // is called when cache is ready. 200 void DoStartAllPending(); 201 202 // Notify delegate and remove ping results. 203 void NotifyDelegateDownloadFinished(scoped_ptr<ExtensionFetch> fetch_data, 204 const base::FilePath& crx_path, 205 bool file_ownership_passed); 206 207 // The delegate that receives the crx files downloaded by the 208 // ExtensionDownloader, and that fills in optional ping and update url data. 209 ExtensionDownloaderDelegate* delegate_; 210 211 // The request context to use for the URLFetchers. 212 scoped_refptr<net::URLRequestContextGetter> request_context_; 213 214 // Used to create WeakPtrs to |this|. 215 base::WeakPtrFactory<ExtensionDownloader> weak_ptr_factory_; 216 217 // Collects UMA samples that are reported when ReportStats() is called. 218 URLStats url_stats_; 219 220 // List of data on fetches we're going to do. We limit the number of 221 // extensions grouped together in one batch to avoid running into the limits 222 // on the length of http GET requests, so there might be multiple 223 // ManifestFetchData* objects with the same base_url. 224 typedef std::map<std::pair<int, GURL>, 225 std::vector<linked_ptr<ManifestFetchData> > > FetchMap; 226 FetchMap fetches_preparing_; 227 228 // Outstanding url fetch requests for manifests and updates. 229 scoped_ptr<net::URLFetcher> manifest_fetcher_; 230 scoped_ptr<net::URLFetcher> extension_fetcher_; 231 232 // Pending manifests and extensions to be fetched when the appropriate fetcher 233 // is available. 234 RequestQueue<ManifestFetchData> manifests_queue_; 235 RequestQueue<ExtensionFetch> extensions_queue_; 236 237 // Maps an extension-id to its PingResult data. 238 std::map<std::string, ExtensionDownloaderDelegate::PingResult> ping_results_; 239 240 // Cache for .crx files. 241 ExtensionCache* extension_cache_; 242 243 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloader); 244 }; 245 246 } // namespace extensions 247 248 #endif // CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_DOWNLOADER_H_ 249