Home | History | Annotate | Download | only in updater
      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