Home | History | Annotate | Download | only in extensions
      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 
     61     PingData() : rollcall_days(0), active_days(0) {}
     62     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 
     76   const GURL& base_url() const { return base_url_; }
     77   const GURL& full_url() const { return full_url_; }
     78   int extension_count() { return extension_ids_.size(); }
     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 {
    127     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.
    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