1 // Copyright (c) 2011 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_EXTENSION_UPDATER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_UPDATER_H_ 7 #pragma once 8 9 #include <deque> 10 #include <map> 11 #include <set> 12 #include <string> 13 #include <vector> 14 15 #include "base/gtest_prod_util.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_temp_dir.h" 19 #include "base/memory/weak_ptr.h" 20 #include "base/task.h" 21 #include "base/time.h" 22 #include "base/timer.h" 23 #include "chrome/browser/extensions/extension_service.h" 24 #include "chrome/common/extensions/update_manifest.h" 25 #include "chrome/common/net/url_fetcher.h" 26 #include "googleurl/src/gurl.h" 27 28 class Extension; 29 class ExtensionPrefs; 30 class ExtensionUpdaterTest; 31 class ExtensionUpdaterFileHandler; 32 class PrefService; 33 class Profile; 34 class SafeManifestParser; 35 36 // To save on server resources we can request updates for multiple extensions 37 // in one manifest check. This class helps us keep track of the id's for a 38 // given fetch, building up the actual URL, and what if anything to include 39 // in the ping parameter. 40 class ManifestFetchData { 41 public: 42 static const int kNeverPinged = -1; 43 44 // Each ping type is sent at most once per day. 45 enum PingType { 46 // Used for counting total installs of an extension/app/theme. 47 ROLLCALL, 48 49 // Used for counting number of active users of an app, where "active" means 50 // the app was launched at least once since the last active ping. 51 ACTIVE 52 }; 53 54 struct PingData { 55 // The number of days it's been since our last rollcall or active ping, 56 // respectively. These are calculated based on the start of day from the 57 // server's perspective. 58 int rollcall_days; 59 int active_days; 60 PingDataPingData61 PingData() : rollcall_days(0), active_days(0) {} PingDataPingData62 PingData(int rollcall, int active) 63 : rollcall_days(rollcall), active_days(active) {} 64 }; 65 66 explicit ManifestFetchData(const GURL& update_url); 67 ~ManifestFetchData(); 68 69 // Returns true if this extension information was successfully added. If the 70 // return value is false it means the full_url would have become too long, and 71 // this ManifestFetchData object remains unchanged. 72 bool AddExtension(std::string id, std::string version, 73 const PingData& ping_data, 74 const std::string& update_url_data); 75 base_url()76 const GURL& base_url() const { return base_url_; } full_url()77 const GURL& full_url() const { return full_url_; } extension_count()78 int extension_count() { return extension_ids_.size(); } extension_ids()79 const std::set<std::string>& extension_ids() const { return extension_ids_; } 80 81 // Returns true if the given id is included in this manifest fetch. 82 bool Includes(const std::string& extension_id) const; 83 84 // Returns true if a ping parameter for |type| was added to full_url for this 85 // extension id. 86 bool DidPing(std::string extension_id, PingType type) const; 87 88 private: 89 // The set of extension id's for this ManifestFetchData. 90 std::set<std::string> extension_ids_; 91 92 // The set of ping data we actually sent. 93 std::map<std::string, PingData> pings_; 94 95 // The base update url without any arguments added. 96 GURL base_url_; 97 98 // The base update url plus arguments indicating the id, version, etc. 99 // information about each extension. 100 GURL full_url_; 101 102 DISALLOW_COPY_AND_ASSIGN(ManifestFetchData); 103 }; 104 105 // A class for building a set of ManifestFetchData objects from 106 // extensions and pending extensions. 107 class ManifestFetchesBuilder { 108 public: 109 ManifestFetchesBuilder(ExtensionServiceInterface* service, 110 ExtensionPrefs* prefs); 111 ~ManifestFetchesBuilder(); 112 113 void AddExtension(const Extension& extension); 114 115 void AddPendingExtension(const std::string& id, 116 const PendingExtensionInfo& info); 117 118 // Adds all recorded stats taken so far to histogram counts. 119 void ReportStats() const; 120 121 // Caller takes ownership of the returned ManifestFetchData 122 // objects. Clears all recorded stats. 123 std::vector<ManifestFetchData*> GetFetches(); 124 125 private: 126 struct URLStats { URLStatsURLStats127 URLStats() 128 : no_url_count(0), 129 google_url_count(0), 130 other_url_count(0), 131 extension_count(0), 132 theme_count(0), 133 app_count(0), 134 pending_count(0) {} 135 136 int no_url_count, google_url_count, other_url_count; 137 int extension_count, theme_count, app_count, pending_count; 138 }; 139 140 void AddExtensionData(Extension::Location location, 141 const std::string& id, 142 const Version& version, 143 Extension::Type extension_type, 144 GURL update_url, 145 const std::string& update_url_data); 146 ExtensionServiceInterface* const service_; 147 ExtensionPrefs* const prefs_; 148 149 // List of data on fetches we're going to do. We limit the number of 150 // extensions grouped together in one batch to avoid running into the limits 151 // on the length of http GET requests, so there might be multiple 152 // ManifestFetchData* objects with the same base_url. 153 std::multimap<GURL, ManifestFetchData*> fetches_; 154 155 URLStats url_stats_; 156 157 DISALLOW_COPY_AND_ASSIGN(ManifestFetchesBuilder); 158 }; 159 160 // A class for doing auto-updates of installed Extensions. Used like this: 161 // 162 // ExtensionUpdater* updater = new ExtensionUpdater(my_extensions_service, 163 // pref_service, 164 // update_frequency_secs); 165 // updater->Start(); 166 // .... 167 // updater->Stop(); 168 class ExtensionUpdater : public URLFetcher::Delegate { 169 public: 170 // Holds a pointer to the passed |service|, using it for querying installed 171 // extensions and installing updated ones. The |frequency_seconds| parameter 172 // controls how often update checks are scheduled. 173 ExtensionUpdater(ExtensionServiceInterface* service, 174 ExtensionPrefs* extension_prefs, 175 PrefService* prefs, 176 Profile* profile, 177 int frequency_seconds); 178 179 virtual ~ExtensionUpdater(); 180 181 // Starts the updater running. Should be called at most once. 182 void Start(); 183 184 // Stops the updater running, cancelling any outstanding update manifest and 185 // crx downloads. Does not cancel any in-progress installs. 186 void Stop(); 187 188 // Posts a task to do an update check. Does nothing if there is 189 // already a pending task that has not yet run. 190 void CheckSoon(); 191 192 // Starts an update check right now, instead of waiting for the next 193 // regularly scheduled check or a pending check from CheckSoon(). 194 void CheckNow(); 195 196 // Set blacklist checks on or off. set_blacklist_checks_enabled(bool enabled)197 void set_blacklist_checks_enabled(bool enabled) { 198 blacklist_checks_enabled_ = enabled; 199 } 200 201 // Returns true iff CheckSoon() has been called but the update check 202 // hasn't been performed yet. This is used mostly by tests; calling 203 // code should just call CheckSoon(). 204 bool WillCheckSoon() const; 205 206 private: 207 friend class ExtensionUpdaterTest; 208 friend class ExtensionUpdaterFileHandler; 209 friend class SafeManifestParser; 210 211 // We need to keep track of some information associated with a url 212 // when doing a fetch. 213 struct ExtensionFetch { 214 ExtensionFetch(); 215 ExtensionFetch(const std::string& i, const GURL& u, 216 const std::string& h, const std::string& v); 217 ~ExtensionFetch(); 218 219 std::string id; 220 GURL url; 221 std::string package_hash; 222 std::string version; 223 }; 224 225 // These are needed for unit testing, to help identify the correct mock 226 // URLFetcher objects. 227 static const int kManifestFetcherId = 1; 228 static const int kExtensionFetcherId = 2; 229 230 static const char* kBlacklistAppID; 231 232 // Does common work from constructors. 233 void Init(); 234 235 // Computes when to schedule the first update check. 236 base::TimeDelta DetermineFirstCheckDelay(); 237 238 // URLFetcher::Delegate interface. 239 virtual void OnURLFetchComplete(const URLFetcher* source, 240 const GURL& url, 241 const net::URLRequestStatus& status, 242 int response_code, 243 const ResponseCookies& cookies, 244 const std::string& data); 245 246 // These do the actual work when a URL fetch completes. 247 virtual void OnManifestFetchComplete(const GURL& url, 248 const net::URLRequestStatus& status, 249 int response_code, 250 const std::string& data); 251 virtual void OnCRXFetchComplete(const GURL& url, 252 const net::URLRequestStatus& status, 253 int response_code, 254 const std::string& data); 255 256 // Called when a crx file has been written into a temp file, and is ready 257 // to be installed. 258 void OnCRXFileWritten(const std::string& id, 259 const FilePath& path, 260 const GURL& download_url); 261 262 // Called when we encountered an error writing a crx file to a temp file. 263 void OnCRXFileWriteError(const std::string& id); 264 265 // Verifies downloaded blacklist. Based on the blacklist, calls extension 266 // service to unload blacklisted extensions and update pref. 267 void ProcessBlacklist(const std::string& data); 268 269 // Sets the timer to call TimerFired after roughly |target_delay| from now. 270 // To help spread load evenly on servers, this method adds some random 271 // jitter. It also saves the scheduled time so it can be reloaded on 272 // browser restart. 273 void ScheduleNextCheck(const base::TimeDelta& target_delay); 274 275 // BaseTimer::ReceiverMethod callback. 276 void TimerFired(); 277 278 // Posted by CheckSoon(). 279 void DoCheckSoon(); 280 281 // Begins an update check. Takes ownership of |fetch_data|. 282 void StartUpdateCheck(ManifestFetchData* fetch_data); 283 284 // Begins (or queues up) download of an updated extension. 285 void FetchUpdatedExtension(const std::string& id, const GURL& url, 286 const std::string& hash, const std::string& version); 287 288 // Once a manifest is parsed, this starts fetches of any relevant crx files. 289 // If |results| is null, it means something went wrong when parsing it. 290 void HandleManifestResults(const ManifestFetchData& fetch_data, 291 const UpdateManifest::Results* results); 292 293 // Determines the version of an existing extension. 294 // Returns true on success and false on failures. 295 bool GetExistingVersion(const std::string& id, std::string* version); 296 297 // Given a list of potential updates, returns the indices of the ones that are 298 // applicable (are actually a new version, etc.) in |result|. 299 std::vector<int> DetermineUpdates(const ManifestFetchData& fetch_data, 300 const UpdateManifest::Results& possible_updates); 301 302 // Send a notification that update checks are starting. 303 void NotifyStarted(); 304 305 // Send a notification that an update was found for extension_id that we'll 306 // attempt to download and install. 307 void NotifyUpdateFound(const std::string& extension_id); 308 309 // Send a notification if we're finished updating. 310 void NotifyIfFinished(); 311 312 // Adds a set of ids to in_progress_ids_. 313 void AddToInProgress(const std::set<std::string>& ids); 314 315 // Removes a set of ids from in_progress_ids_. 316 void RemoveFromInProgress(const std::set<std::string>& ids); 317 318 // Whether Start() has been called but not Stop(). 319 bool alive_; 320 321 base::WeakPtrFactory<ExtensionUpdater> weak_ptr_factory_; 322 323 // Outstanding url fetch requests for manifests and updates. 324 scoped_ptr<URLFetcher> manifest_fetcher_; 325 scoped_ptr<URLFetcher> extension_fetcher_; 326 327 // Pending manifests and extensions to be fetched when the appropriate fetcher 328 // is available. 329 std::deque<ManifestFetchData*> manifests_pending_; 330 std::deque<ExtensionFetch> extensions_pending_; 331 332 // The manifest currently being fetched (if any). 333 scoped_ptr<ManifestFetchData> current_manifest_fetch_; 334 335 // The extension currently being fetched (if any). 336 ExtensionFetch current_extension_fetch_; 337 338 // Pointer back to the service that owns this ExtensionUpdater. 339 ExtensionServiceInterface* service_; 340 341 base::OneShotTimer<ExtensionUpdater> timer_; 342 int frequency_seconds_; 343 344 ScopedRunnableMethodFactory<ExtensionUpdater> method_factory_; 345 346 bool will_check_soon_; 347 348 ExtensionPrefs* extension_prefs_; 349 PrefService* prefs_; 350 Profile* profile_; 351 352 scoped_refptr<ExtensionUpdaterFileHandler> file_handler_; 353 bool blacklist_checks_enabled_; 354 355 // The ids of extensions that have in-progress update checks. 356 std::set<std::string> in_progress_ids_; 357 358 FRIEND_TEST(ExtensionUpdaterTest, TestStartUpdateCheckMemory); 359 FRIEND_TEST(ExtensionUpdaterTest, TestAfterStopBehavior); 360 361 DISALLOW_COPY_AND_ASSIGN(ExtensionUpdater); 362 }; 363 364 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_UPDATER_H_ 365