• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
set_brand_code(const std::string & brand_code)103   void set_brand_code(const std::string& brand_code) {
104     brand_code_ = brand_code;
105   }
106 
set_manifest_query_params(const std::string & params)107   void set_manifest_query_params(const std::string& params) {
108     manifest_query_params_ = params;
109   }
110 
set_ping_enabled_domain(const std::string & domain)111   void set_ping_enabled_domain(const std::string& domain) {
112     ping_enabled_domain_ = domain;
113   }
114 
set_enable_extra_update_metrics(bool enable)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 {
URLStatsURLStats135     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