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
30class IdentityProvider;
31
32namespace net {
33class URLFetcher;
34class URLRequestContextGetter;
35class URLRequestStatus;
36}
37
38namespace extensions {
39
40struct UpdateDetails {
41  UpdateDetails(const std::string& id, const base::Version& version);
42  ~UpdateDetails();
43
44  std::string id;
45  base::Version version;
46};
47
48class ExtensionCache;
49class 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.
55class 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