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/request_queue.h" 23 #include "extensions/browser/updater/manifest_fetch_data.h" 24 #include "extensions/common/extension.h" 25 #include "extensions/common/update_manifest.h" 26 #include "google_apis/gaia/oauth2_token_service.h" 27 #include "net/url_request/url_fetcher_delegate.h" 28 #include "url/gurl.h" 29 30 class IdentityProvider; 31 32 namespace net { 33 class URLFetcher; 34 class URLRequestContextGetter; 35 class URLRequestStatus; 36 } 37 38 namespace extensions { 39 40 struct UpdateDetails { 41 UpdateDetails(const std::string& id, const base::Version& version); 42 ~UpdateDetails(); 43 44 std::string id; 45 base::Version version; 46 }; 47 48 class ExtensionCache; 49 class ExtensionUpdaterTest; 50 51 // A class that checks for updates of a given list of extensions, and downloads 52 // the crx file when updates are found. It uses a |ExtensionDownloaderDelegate| 53 // that takes ownership of the downloaded crx files, and handles events during 54 // the update check. 55 class ExtensionDownloader 56 : public net::URLFetcherDelegate, 57 public OAuth2TokenService::Consumer { 58 public: 59 // A closure which constructs a new ExtensionDownloader to be owned by the 60 // caller. 61 typedef base::Callback< 62 scoped_ptr<ExtensionDownloader>(ExtensionDownloaderDelegate* delegate)> 63 Factory; 64 65 // |delegate| is stored as a raw pointer and must outlive the 66 // ExtensionDownloader. 67 ExtensionDownloader(ExtensionDownloaderDelegate* delegate, 68 net::URLRequestContextGetter* request_context); 69 virtual ~ExtensionDownloader(); 70 71 // Adds |extension| to the list of extensions to check for updates. 72 // Returns false if the |extension| can't be updated due to invalid details. 73 // In that case, no callbacks will be performed on the |delegate_|. 74 // The |request_id| is passed on as is to the various |delegate_| callbacks. 75 // This is used for example by ExtensionUpdater to keep track of when 76 // potentially concurrent update checks complete. 77 bool AddExtension(const Extension& extension, int request_id); 78 79 // Adds extension |id| to the list of extensions to check for updates. 80 // Returns false if the |id| can't be updated due to invalid details. 81 // In that case, no callbacks will be performed on the |delegate_|. 82 // The |request_id| is passed on as is to the various |delegate_| callbacks. 83 // This is used for example by ExtensionUpdater to keep track of when 84 // potentially concurrent update checks complete. 85 bool AddPendingExtension(const std::string& id, 86 const GURL& update_url, 87 int request_id); 88 89 // Schedules a fetch of the manifest of all the extensions added with 90 // AddExtension() and AddPendingExtension(). 91 void StartAllPending(ExtensionCache* cache); 92 93 // Schedules an update check of the blacklist. 94 void StartBlacklistUpdate(const std::string& version, 95 const ManifestFetchData::PingData& ping_data, 96 int request_id); 97 98 // Sets an IdentityProvider to be used for OAuth2 authentication on protected 99 // Webstore downloads. 100 void SetWebstoreIdentityProvider( 101 scoped_ptr<IdentityProvider> identity_provider); 102 set_brand_code(const std::string & brand_code)103 void set_brand_code(const std::string& brand_code) { 104 brand_code_ = brand_code; 105 } 106 set_manifest_query_params(const std::string & params)107 void set_manifest_query_params(const std::string& params) { 108 manifest_query_params_ = params; 109 } 110 set_ping_enabled_domain(const std::string & domain)111 void set_ping_enabled_domain(const std::string& domain) { 112 ping_enabled_domain_ = domain; 113 } 114 set_enable_extra_update_metrics(bool enable)115 void set_enable_extra_update_metrics(bool enable) { 116 enable_extra_update_metrics_ = enable; 117 } 118 119 // These are needed for unit testing, to help identify the correct mock 120 // URLFetcher objects. 121 static const int kManifestFetcherId = 1; 122 static const int kExtensionFetcherId = 2; 123 124 // Update AppID for extension blacklist. 125 static const char kBlacklistAppID[]; 126 127 static const int kMaxRetries = 10; 128 129 private: 130 friend class ExtensionUpdaterTest; 131 132 // These counters are bumped as extensions are added to be fetched. They 133 // are then recorded as UMA metrics when all the extensions have been added. 134 struct URLStats { URLStatsURLStats135 URLStats() 136 : no_url_count(0), 137 google_url_count(0), 138 other_url_count(0), 139 extension_count(0), 140 theme_count(0), 141 app_count(0), 142 platform_app_count(0), 143 pending_count(0) {} 144 145 int no_url_count, google_url_count, other_url_count; 146 int extension_count, theme_count, app_count, platform_app_count, 147 pending_count; 148 }; 149 150 // We need to keep track of some information associated with a url 151 // when doing a fetch. 152 struct ExtensionFetch { 153 ExtensionFetch(); 154 ExtensionFetch(const std::string& id, const GURL& url, 155 const std::string& package_hash, const std::string& version, 156 const std::set<int>& request_ids); 157 ~ExtensionFetch(); 158 159 std::string id; 160 GURL url; 161 std::string package_hash; 162 std::string version; 163 std::set<int> request_ids; 164 165 enum CredentialsMode { 166 CREDENTIALS_NONE = 0, 167 CREDENTIALS_OAUTH2_TOKEN, 168 CREDENTIALS_COOKIES, 169 }; 170 171 // Indicates the type of credentials to include with this fetch. 172 CredentialsMode credentials; 173 174 // Counts the number of times OAuth2 authentication has been attempted for 175 // this fetch. 176 int oauth2_attempt_count; 177 }; 178 179 // Helper for AddExtension() and AddPendingExtension(). 180 bool AddExtensionData(const std::string& id, 181 const base::Version& version, 182 Manifest::Type extension_type, 183 const GURL& extension_update_url, 184 const std::string& update_url_data, 185 int request_id, 186 bool force_update, 187 const std::string& install_source_override); 188 189 // Adds all recorded stats taken so far to histogram counts. 190 void ReportStats() const; 191 192 // Begins an update check. 193 void StartUpdateCheck(scoped_ptr<ManifestFetchData> fetch_data); 194 195 // Called by RequestQueue when a new manifest fetch request is started. 196 void CreateManifestFetcher(); 197 198 // net::URLFetcherDelegate implementation. 199 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 200 201 // Handles the result of a manifest fetch. 202 void OnManifestFetchComplete(const GURL& url, 203 const net::URLRequestStatus& status, 204 int response_code, 205 const base::TimeDelta& backoff_delay, 206 const std::string& data); 207 208 // Once a manifest is parsed, this starts fetches of any relevant crx files. 209 // If |results| is null, it means something went wrong when parsing it. 210 void HandleManifestResults(const ManifestFetchData& fetch_data, 211 const UpdateManifest::Results* results); 212 213 // Given a list of potential updates, returns the indices of the ones that are 214 // applicable (are actually a new version, etc.) in |result|. 215 void DetermineUpdates(const ManifestFetchData& fetch_data, 216 const UpdateManifest::Results& possible_updates, 217 std::vector<int>* result); 218 219 // Begins (or queues up) download of an updated extension. 220 void FetchUpdatedExtension(scoped_ptr<ExtensionFetch> fetch_data); 221 222 // Called by RequestQueue when a new extension fetch request is started. 223 void CreateExtensionFetcher(); 224 225 // Handles the result of a crx fetch. 226 void OnCRXFetchComplete(const net::URLFetcher* source, 227 const GURL& url, 228 const net::URLRequestStatus& status, 229 int response_code, 230 const base::TimeDelta& backoff_delay); 231 232 // Invokes OnExtensionDownloadFailed() on the |delegate_| for each extension 233 // in the set, with |error| as the reason for failure. 234 void NotifyExtensionsDownloadFailed(const std::set<std::string>& id_set, 235 const std::set<int>& request_ids, 236 ExtensionDownloaderDelegate::Error error); 237 238 // Send a notification that an update was found for |id| that we'll 239 // attempt to download. 240 void NotifyUpdateFound(const std::string& id, const std::string& version); 241 242 // Do real work of StartAllPending. If .crx cache is used, this function 243 // is called when cache is ready. 244 void DoStartAllPending(); 245 246 // Notify delegate and remove ping results. 247 void NotifyDelegateDownloadFinished(scoped_ptr<ExtensionFetch> fetch_data, 248 const base::FilePath& crx_path, 249 bool file_ownership_passed); 250 251 // Potentially updates an ExtensionFetch's authentication state and returns 252 // |true| if the fetch should be retried. Returns |false| if the failure was 253 // not related to authentication, leaving the ExtensionFetch data unmodified. 254 bool IterateFetchCredentialsAfterFailure(ExtensionFetch* fetch, 255 const net::URLRequestStatus& status, 256 int response_code); 257 258 // OAuth2TokenService::Consumer implementation. 259 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, 260 const std::string& access_token, 261 const base::Time& expiration_time) OVERRIDE; 262 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, 263 const GoogleServiceAuthError& error) OVERRIDE; 264 265 ManifestFetchData* CreateManifestFetchData(const GURL& update_url, 266 int request_id); 267 268 // The delegate that receives the crx files downloaded by the 269 // ExtensionDownloader, and that fills in optional ping and update url data. 270 ExtensionDownloaderDelegate* delegate_; 271 272 // The request context to use for the URLFetchers. 273 scoped_refptr<net::URLRequestContextGetter> request_context_; 274 275 // Collects UMA samples that are reported when ReportStats() is called. 276 URLStats url_stats_; 277 278 // List of data on fetches we're going to do. We limit the number of 279 // extensions grouped together in one batch to avoid running into the limits 280 // on the length of http GET requests, so there might be multiple 281 // ManifestFetchData* objects with the same base_url. 282 typedef std::map<std::pair<int, GURL>, 283 std::vector<linked_ptr<ManifestFetchData> > > FetchMap; 284 FetchMap fetches_preparing_; 285 286 // Outstanding url fetch requests for manifests and updates. 287 scoped_ptr<net::URLFetcher> manifest_fetcher_; 288 scoped_ptr<net::URLFetcher> extension_fetcher_; 289 290 // Pending manifests and extensions to be fetched when the appropriate fetcher 291 // is available. 292 RequestQueue<ManifestFetchData> manifests_queue_; 293 RequestQueue<ExtensionFetch> extensions_queue_; 294 295 // Maps an extension-id to its PingResult data. 296 std::map<std::string, ExtensionDownloaderDelegate::PingResult> ping_results_; 297 298 // Cache for .crx files. 299 ExtensionCache* extension_cache_; 300 301 // An IdentityProvider which may be used for authentication on protected 302 // download requests. May be NULL. 303 scoped_ptr<IdentityProvider> identity_provider_; 304 305 // A Webstore download-scoped access token for the |identity_provider_|'s 306 // active account, if any. 307 std::string access_token_; 308 309 // A pending token fetch request. 310 scoped_ptr<OAuth2TokenService::Request> access_token_request_; 311 312 // Brand code to include with manifest fetch queries if sending ping data. 313 std::string brand_code_; 314 315 // Baseline parameters to include with manifest fetch queries. 316 std::string manifest_query_params_; 317 318 // Domain to enable ping data. Ping data will be sent with manifest fetches 319 // to update URLs which match this domain. Defaults to empty (no domain). 320 std::string ping_enabled_domain_; 321 322 // Indicates whether or not extra metrics should be included with ping data. 323 // Defaults to |false|. 324 bool enable_extra_update_metrics_; 325 326 // Used to create WeakPtrs to |this|. 327 base::WeakPtrFactory<ExtensionDownloader> weak_ptr_factory_; 328 329 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloader); 330 }; 331 332 } // namespace extensions 333 334 #endif // CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_DOWNLOADER_H_ 335