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/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 
    103   void set_brand_code(const std::string& brand_code) {
    104     brand_code_ = brand_code;
    105   }
    106 
    107   void set_manifest_query_params(const std::string& params) {
    108     manifest_query_params_ = params;
    109   }
    110 
    111   void set_ping_enabled_domain(const std::string& domain) {
    112     ping_enabled_domain_ = domain;
    113   }
    114 
    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 {
    135     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