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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_DOWNLOADER_H_
6 #define CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_DOWNLOADER_H_
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"
31 class URLRequestContextGetter
;
32 class URLRequestStatus
;
35 namespace extensions
{
37 struct UpdateDetails
{
38 UpdateDetails(const std::string
& id
, const base::Version
& version
);
42 base::Version version
;
45 class ExtensionUpdaterTest
;
47 // A class that checks for updates of a given list of extensions, and downloads
48 // the crx file when updates are found. It uses a |ExtensionDownloaderDelegate|
49 // that takes ownership of the downloaded crx files, and handles events during
51 class ExtensionDownloader
: public net::URLFetcherDelegate
{
53 // |delegate| is stored as a raw pointer and must outlive the
54 // ExtensionDownloader.
55 ExtensionDownloader(ExtensionDownloaderDelegate
* delegate
,
56 net::URLRequestContextGetter
* request_context
);
57 virtual ~ExtensionDownloader();
59 // Adds |extension| to the list of extensions to check for updates.
60 // Returns false if the |extension| can't be updated due to invalid details.
61 // In that case, no callbacks will be performed on the |delegate_|.
62 // The |request_id| is passed on as is to the various |delegate_| callbacks.
63 // This is used for example by ExtensionUpdater to keep track of when
64 // potentially concurrent update checks complete.
65 bool AddExtension(const Extension
& extension
, int request_id
);
67 // Adds extension |id| to the list of extensions to check for updates.
68 // Returns false if the |id| can't be updated due to invalid details.
69 // In that case, no callbacks will be performed on the |delegate_|.
70 // The |request_id| is passed on as is to the various |delegate_| callbacks.
71 // This is used for example by ExtensionUpdater to keep track of when
72 // potentially concurrent update checks complete.
73 bool AddPendingExtension(const std::string
& id
,
74 const GURL
& update_url
,
77 // Schedules a fetch of the manifest of all the extensions added with
78 // AddExtension() and AddPendingExtension().
79 void StartAllPending();
81 // Schedules an update check of the blacklist.
82 void StartBlacklistUpdate(const std::string
& version
,
83 const ManifestFetchData::PingData
& ping_data
,
86 // These are needed for unit testing, to help identify the correct mock
87 // URLFetcher objects.
88 static const int kManifestFetcherId
= 1;
89 static const int kExtensionFetcherId
= 2;
91 // Update AppID for extension blacklist.
92 static const char kBlacklistAppID
[];
94 static const int kMaxRetries
= 10;
97 friend class ExtensionUpdaterTest
;
99 // These counters are bumped as extensions are added to be fetched. They
100 // are then recorded as UMA metrics when all the extensions have been added.
109 platform_app_count(0),
112 int no_url_count
, google_url_count
, other_url_count
;
113 int extension_count
, theme_count
, app_count
, platform_app_count
,
117 // We need to keep track of some information associated with a url
118 // when doing a fetch.
119 struct ExtensionFetch
{
121 ExtensionFetch(const std::string
& id
, const GURL
& url
,
122 const std::string
& package_hash
, const std::string
& version
,
123 const std::set
<int>& request_ids
);
128 std::string package_hash
;
130 std::set
<int> request_ids
;
133 // Helper for AddExtension() and AddPendingExtension().
134 bool AddExtensionData(const std::string
& id
,
135 const base::Version
& version
,
136 Manifest::Type extension_type
,
137 const GURL
& extension_update_url
,
138 const std::string
& update_url_data
,
141 // Adds all recorded stats taken so far to histogram counts.
142 void ReportStats() const;
144 // Begins an update check.
145 void StartUpdateCheck(scoped_ptr
<ManifestFetchData
> fetch_data
);
147 // Called by RequestQueue when a new manifest fetch request is started.
148 void CreateManifestFetcher();
150 // net::URLFetcherDelegate implementation.
151 virtual void OnURLFetchComplete(const net::URLFetcher
* source
) OVERRIDE
;
153 // Handles the result of a manifest fetch.
154 void OnManifestFetchComplete(const GURL
& url
,
155 const net::URLRequestStatus
& status
,
157 const base::TimeDelta
& backoff_delay
,
158 const std::string
& data
);
160 // Once a manifest is parsed, this starts fetches of any relevant crx files.
161 // If |results| is null, it means something went wrong when parsing it.
162 void HandleManifestResults(const ManifestFetchData
& fetch_data
,
163 const UpdateManifest::Results
* results
);
165 // Given a list of potential updates, returns the indices of the ones that are
166 // applicable (are actually a new version, etc.) in |result|.
167 void DetermineUpdates(const ManifestFetchData
& fetch_data
,
168 const UpdateManifest::Results
& possible_updates
,
169 std::vector
<int>* result
);
171 // Begins (or queues up) download of an updated extension.
172 void FetchUpdatedExtension(scoped_ptr
<ExtensionFetch
> fetch_data
);
174 // Called by RequestQueue when a new extension fetch request is started.
175 void CreateExtensionFetcher();
177 // Handles the result of a crx fetch.
178 void OnCRXFetchComplete(const net::URLFetcher
* source
,
180 const net::URLRequestStatus
& status
,
182 const base::TimeDelta
& backoff_delay
);
184 // Invokes OnExtensionDownloadFailed() on the |delegate_| for each extension
185 // in the set, with |error| as the reason for failure.
186 void NotifyExtensionsDownloadFailed(const std::set
<std::string
>& id_set
,
187 const std::set
<int>& request_ids
,
188 ExtensionDownloaderDelegate::Error error
);
190 // Send a notification that an update was found for |id| that we'll
191 // attempt to download.
192 void NotifyUpdateFound(const std::string
& id
, const std::string
& version
);
194 // The delegate that receives the crx files downloaded by the
195 // ExtensionDownloader, and that fills in optional ping and update url data.
196 ExtensionDownloaderDelegate
* delegate_
;
198 // The request context to use for the URLFetchers.
199 scoped_refptr
<net::URLRequestContextGetter
> request_context_
;
201 // Used to create WeakPtrs to |this|.
202 base::WeakPtrFactory
<ExtensionDownloader
> weak_ptr_factory_
;
204 // Collects UMA samples that are reported when ReportStats() is called.
207 // List of data on fetches we're going to do. We limit the number of
208 // extensions grouped together in one batch to avoid running into the limits
209 // on the length of http GET requests, so there might be multiple
210 // ManifestFetchData* objects with the same base_url.
211 typedef std::map
<std::pair
<int, GURL
>,
212 std::vector
<linked_ptr
<ManifestFetchData
> > > FetchMap
;
213 FetchMap fetches_preparing_
;
215 // Outstanding url fetch requests for manifests and updates.
216 scoped_ptr
<net::URLFetcher
> manifest_fetcher_
;
217 scoped_ptr
<net::URLFetcher
> extension_fetcher_
;
219 // Pending manifests and extensions to be fetched when the appropriate fetcher
221 RequestQueue
<ManifestFetchData
> manifests_queue_
;
222 RequestQueue
<ExtensionFetch
> extensions_queue_
;
224 // Maps an extension-id to its PingResult data.
225 std::map
<std::string
, ExtensionDownloaderDelegate::PingResult
> ping_results_
;
227 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloader
);
230 } // namespace extensions
232 #endif // CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_DOWNLOADER_H_