blob: e9541dec8204defc135dbc6dfef30595eab22ef2 [file] [log] [blame]
[email protected]35385332012-03-28 02:32:031// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]7577a5c52009-07-30 06:21:582// 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_CRX_INSTALLER_H_
6#define CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
[email protected]7577a5c52009-07-30 06:21:587
8#include <string>
9
[email protected]17902752011-08-31 22:52:5410#include "base/compiler_specific.h"
[email protected]7577a5c52009-07-30 06:21:5811#include "base/file_path.h"
[email protected]3b63f8f42011-03-28 01:54:1512#include "base/memory/ref_counted.h"
[email protected]14908b72011-04-20 06:54:3613#include "base/memory/weak_ptr.h"
[email protected]604322d2011-03-22 16:51:5614#include "base/version.h"
[email protected]4eaf0b32012-06-19 06:33:2815#include "chrome/browser/extensions/crx_installer_error.h"
[email protected]c82da8c42012-06-08 19:49:1116#include "chrome/browser/extensions/extension_install_prompt.h"
[email protected]f5ac2742012-07-02 17:50:5817#include "chrome/browser/extensions/sandboxed_unpacker.h"
[email protected]21a5ad62012-04-03 04:48:4518#include "chrome/browser/extensions/webstore_installer.h"
[email protected]7577a5c52009-07-30 06:21:5819#include "chrome/common/extensions/extension.h"
[email protected]bb461532010-11-26 21:50:2320#include "chrome/common/web_apps.h"
[email protected]36b643212012-09-07 12:53:0021#include "sync/api/string_ordinal.h"
[email protected]7577a5c52009-07-30 06:21:5822
[email protected]eaa7dd182010-12-14 11:09:0023class ExtensionService;
[email protected]d2817012009-08-04 06:46:2124class SkBitmap;
25
[email protected]42a08162012-03-16 18:09:1126namespace extensions {
27class ExtensionUpdaterTest;
[email protected]98270432012-09-11 20:51:2428class RequirementsChecker;
[email protected]42a08162012-03-16 18:09:1129
[email protected]7577a5c52009-07-30 06:21:5830// This class installs a crx file into a profile.
31//
32// Installing a CRX is a multi-step process, including unpacking the crx,
33// validating it, prompting the user, and installing. Since many of these
34// steps must occur on the file thread, this class contains a copy of all data
35// necessary to do its job. (This also minimizes external dependencies for
36// easier testing).
37//
[email protected]7577a5c52009-07-30 06:21:5838// Lifetime management:
39//
40// This class is ref-counted by each call it makes to itself on another thread,
41// and by UtilityProcessHost.
42//
43// Additionally, we hold a reference to our own client so that it lives at least
44// long enough to receive the result of unpacking.
[email protected]7577a5c52009-07-30 06:21:5845//
[email protected]6dfbbf82010-03-12 23:09:1646// IMPORTANT: Callers should keep a reference to a CrxInstaller while they are
47// working with it, eg:
48//
49// scoped_refptr<CrxInstaller> installer(new CrxInstaller(...));
50// installer->set_foo();
51// installer->set_bar();
52// installer->InstallCrx(...);
[email protected]11f4857282009-11-13 19:56:1753class CrxInstaller
[email protected]bf3d9df2012-07-24 23:20:2754 : public SandboxedUnpackerClient,
[email protected]c82da8c42012-06-08 19:49:1155 public ExtensionInstallPrompt::Delegate {
[email protected]7577a5c52009-07-30 06:21:5856 public:
[email protected]d9039812012-06-09 06:05:4857 // Used in histograms; do not change order.
58 enum OffStoreInstallAllowReason {
59 OffStoreInstallDisallowed,
60 OffStoreInstallAllowedFromSettingsPage,
61 OffStoreInstallAllowedBecausePref,
62 OffStoreInstallAllowedInTest,
63 NumOffStoreInstallAllowReasons
64 };
65
[email protected]d8c8f25f2011-11-02 18:18:0166 // Extensions will be installed into frontend->install_directory(),
67 // then registered with |frontend|. Any install UI will be displayed
[email protected]21a5ad62012-04-03 04:48:4568 // using |client|. Pass NULL for |client| for silent install
[email protected]d8c8f25f2011-11-02 18:18:0169 static scoped_refptr<CrxInstaller> Create(
70 ExtensionService* frontend,
[email protected]c82da8c42012-06-08 19:49:1171 ExtensionInstallPrompt* client);
[email protected]d8c8f25f2011-11-02 18:18:0172
[email protected]21a5ad62012-04-03 04:48:4573 // Same as the previous method, except use the |approval| to bypass the
74 // prompt. Note that the caller retains ownership of |approval|.
75 static scoped_refptr<CrxInstaller> Create(
76 ExtensionService* frontend,
[email protected]c82da8c42012-06-08 19:49:1177 ExtensionInstallPrompt* client,
[email protected]bf3d9df2012-07-24 23:20:2778 const WebstoreInstaller::Approval* approval);
[email protected]5349ac6d2011-04-05 22:20:1779
[email protected]bb461532010-11-26 21:50:2380 // Install the crx in |source_file|.
[email protected]6dfbbf82010-03-12 23:09:1681 void InstallCrx(const FilePath& source_file);
82
[email protected]bb461532010-11-26 21:50:2383 // Convert the specified user script into an extension and install it.
[email protected]6dfbbf82010-03-12 23:09:1684 void InstallUserScript(const FilePath& source_file,
[email protected]655b2b1a2011-10-13 17:13:0685 const GURL& download_url);
[email protected]6657afa62009-11-04 02:15:2086
[email protected]bb461532010-11-26 21:50:2387 // Convert the specified web app into an extension and install it.
88 void InstallWebApp(const WebApplicationInfo& web_app);
89
[email protected]c82da8c42012-06-08 19:49:1190 // Overridden from ExtensionInstallPrompt::Delegate:
[email protected]17902752011-08-31 22:52:5491 virtual void InstallUIProceed() OVERRIDE;
92 virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
[email protected]d2817012009-08-04 06:46:2193
[email protected]1bf73cc2011-10-26 22:38:3194 int creation_flags() const { return creation_flags_; }
95 void set_creation_flags(int val) { creation_flags_ = val; }
96
[email protected]655b2b1a2011-10-13 17:13:0697 const GURL& download_url() const { return download_url_; }
98 void set_download_url(const GURL& val) { download_url_ = val; }
[email protected]6dfbbf82010-03-12 23:09:1699
[email protected]5f7c4bf2012-03-30 10:28:28100 const FilePath& source_file() const { return source_file_; }
101
[email protected]bf3d9df2012-07-24 23:20:27102 Extension::Location install_source() const {
[email protected]1c321ee2012-05-21 03:02:34103 return install_source_;
104 }
[email protected]bf3d9df2012-07-24 23:20:27105 void set_install_source(Extension::Location source) {
[email protected]6dfbbf82010-03-12 23:09:16106 install_source_ = source;
107 }
108
[email protected]5c8516202010-03-18 21:43:34109 const std::string& expected_id() const { return expected_id_; }
[email protected]6dfbbf82010-03-12 23:09:16110 void set_expected_id(const std::string& val) { expected_id_ = val; }
111
[email protected]604322d2011-03-22 16:51:56112 void set_expected_version(const Version& val) {
[email protected]12126d372012-07-11 18:40:53113 expected_version_.reset(new Version(val));
[email protected]604322d2011-03-22 16:51:56114 }
115
[email protected]5c8516202010-03-18 21:43:34116 bool delete_source() const { return delete_source_; }
[email protected]6dfbbf82010-03-12 23:09:16117 void set_delete_source(bool val) { delete_source_ = val; }
118
[email protected]dd9d6272010-09-09 17:33:18119 bool allow_silent_install() const { return allow_silent_install_; }
120 void set_allow_silent_install(bool val) { allow_silent_install_ = val; }
121
[email protected]fc38935a2011-10-31 23:53:28122 bool is_gallery_install() const {
[email protected]bf3d9df2012-07-24 23:20:27123 return (creation_flags_ & Extension::FROM_WEBSTORE) > 0;
[email protected]fc38935a2011-10-31 23:53:28124 }
125 void set_is_gallery_install(bool val) {
[email protected]d8c8f25f2011-11-02 18:18:01126 if (val)
[email protected]bf3d9df2012-07-24 23:20:27127 creation_flags_ |= Extension::FROM_WEBSTORE;
[email protected]d8c8f25f2011-11-02 18:18:01128 else
[email protected]bf3d9df2012-07-24 23:20:27129 creation_flags_ &= ~Extension::FROM_WEBSTORE;
[email protected]fc38935a2011-10-31 23:53:28130 }
[email protected]5c8516202010-03-18 21:43:34131
[email protected]655b2b1a2011-10-13 17:13:06132 // The original download URL should be set when the WebstoreInstaller is
133 // tracking the installation. The WebstoreInstaller uses this URL to match
134 // failure notifications to the extension.
135 const GURL& original_download_url() const { return original_download_url_; }
136 void set_original_download_url(const GURL& url) {
137 original_download_url_ = url;
138 }
139
[email protected]d4a71882010-06-25 16:36:41140 // If |apps_require_extension_mime_type_| is set to true, be sure to set
141 // |original_mime_type_| as well.
142 void set_apps_require_extension_mime_type(
143 bool apps_require_extension_mime_type) {
144 apps_require_extension_mime_type_ = apps_require_extension_mime_type;
145 }
146
147 void set_original_mime_type(const std::string& original_mime_type) {
148 original_mime_type_ = original_mime_type;
149 }
150
[email protected]cb0e50312011-05-09 15:03:07151 extension_misc::CrxInstallCause install_cause() const {
152 return install_cause_;
153 }
[email protected]cb0e50312011-05-09 15:03:07154 void set_install_cause(extension_misc::CrxInstallCause install_cause) {
155 install_cause_ = install_cause;
156 }
157
[email protected]d9039812012-06-09 06:05:48158 OffStoreInstallAllowReason off_store_install_allow_reason() const {
159 return off_store_install_allow_reason_;
160 }
161 void set_off_store_install_allow_reason(OffStoreInstallAllowReason reason) {
162 off_store_install_allow_reason_ = reason;
163 }
[email protected]a9736892012-05-30 15:58:05164
[email protected]36b643212012-09-07 12:53:00165 void set_page_ordinal(const syncer::StringOrdinal& page_ordinal) {
[email protected]36a5c4c2011-12-14 16:34:50166 page_ordinal_ = page_ordinal;
[email protected]cc829cf2011-08-22 21:01:35167 }
168
[email protected]98270432012-09-11 20:51:24169 void set_error_on_unsupported_requirements(bool val) {
170 error_on_unsupported_requirements_ = val;
171 }
172
[email protected]86a99112012-06-19 01:18:07173 bool did_handle_successfully() const { return did_handle_successfully_; }
174
[email protected]655b2b1a2011-10-13 17:13:06175 Profile* profile() { return profile_; }
176
[email protected]2a464a92009-08-01 17:58:35177 private:
[email protected]bf3d9df2012-07-24 23:20:27178 friend class ExtensionUpdaterTest;
[email protected]d4a37f1c2012-07-09 21:36:13179 friend class ExtensionCrxInstallerTest;
[email protected]420a0ec2011-06-01 01:07:03180
[email protected]d8c8f25f2011-11-02 18:18:01181 CrxInstaller(base::WeakPtr<ExtensionService> frontend_weak,
[email protected]c82da8c42012-06-08 19:49:11182 ExtensionInstallPrompt* client,
[email protected]bf3d9df2012-07-24 23:20:27183 const WebstoreInstaller::Approval* approval);
[email protected]3690ebe02011-05-25 09:08:19184 virtual ~CrxInstaller();
[email protected]7577a5c52009-07-30 06:21:58185
[email protected]6657afa62009-11-04 02:15:20186 // Converts the source user script to an extension.
187 void ConvertUserScriptOnFileThread();
188
[email protected]bb461532010-11-26 21:50:23189 // Converts the source web app to an extension.
190 void ConvertWebAppOnFileThread(const WebApplicationInfo& web_app);
191
[email protected]da8479bf2010-10-08 15:19:45192 // Called after OnUnpackSuccess as a last check to see whether the install
193 // should complete.
[email protected]bf3d9df2012-07-24 23:20:27194 CrxInstallerError AllowInstall(const Extension* extension);
[email protected]da8479bf2010-10-08 15:19:45195
[email protected]f5ac2742012-07-02 17:50:58196 // SandboxedUnpackerClient
[email protected]fc670822011-12-17 09:33:49197 virtual void OnUnpackFailure(const string16& error_message) OVERRIDE;
[email protected]7577a5c52009-07-30 06:21:58198 virtual void OnUnpackSuccess(const FilePath& temp_dir,
199 const FilePath& extension_dir,
[email protected]f3a1c642011-07-12 19:15:03200 const base::DictionaryValue* original_manifest,
[email protected]bf3d9df2012-07-24 23:20:27201 const Extension* extension) OVERRIDE;
[email protected]7577a5c52009-07-30 06:21:58202
[email protected]5349ac6d2011-04-05 22:20:17203 // Returns true if we can skip confirmation because the install was
204 // whitelisted.
205 bool CanSkipConfirmation();
206
[email protected]98270432012-09-11 20:51:24207 // Called on the UI thread to start the requirements check on the extension.
208 void CheckRequirements();
209
210 // Runs on the UI thread. Callback from RequirementsChecker.
211 void OnRequirementsChecked(std::vector<std::string> requirement_errors);
212
[email protected]c82da8c42012-06-08 19:49:11213 // Runs on the UI thread. Confirms with the user (via ExtensionInstallPrompt)
214 // that it is OK to install this extension.
[email protected]2a464a92009-08-01 17:58:35215 void ConfirmInstall();
[email protected]7577a5c52009-07-30 06:21:58216
217 // Runs on File thread. Install the unpacked extension into the profile and
218 // notify the frontend.
219 void CompleteInstall();
220
221 // Result reporting.
[email protected]4eaf0b32012-06-19 06:33:28222 void ReportFailureFromFileThread(const CrxInstallerError& error);
223 void ReportFailureFromUIThread(const CrxInstallerError& error);
[email protected]7577a5c52009-07-30 06:21:58224 void ReportSuccessFromFileThread();
[email protected]2a464a92009-08-01 17:58:35225 void ReportSuccessFromUIThread();
[email protected]bf3d9df2012-07-24 23:20:27226 void NotifyCrxInstallComplete(const Extension* extension);
[email protected]7577a5c52009-07-30 06:21:58227
[email protected]6657afa62009-11-04 02:15:20228 // The file we're installing.
229 FilePath source_file_;
230
[email protected]6dfbbf82010-03-12 23:09:16231 // The URL the file was downloaded from.
[email protected]655b2b1a2011-10-13 17:13:06232 GURL download_url_;
[email protected]7577a5c52009-07-30 06:21:58233
234 // The directory extensions are installed to.
235 FilePath install_directory_;
236
237 // The location the installation came from (bundled with Chromium, registry,
238 // manual install, etc). This metadata is saved with the installation if
[email protected]6dfbbf82010-03-12 23:09:16239 // successful. Defaults to INTERNAL.
[email protected]bf3d9df2012-07-24 23:20:27240 Extension::Location install_source_;
[email protected]7577a5c52009-07-30 06:21:58241
[email protected]21a5ad62012-04-03 04:48:45242 // Indicates whether the user has already approved the extension to be
243 // installed. If true, |expected_manifest_| and |expected_id_| must match
244 // those of the CRX.
245 bool approved_;
246
247 // For updates, external and webstore installs we have an ID we're expecting
248 // the extension to contain.
[email protected]7577a5c52009-07-30 06:21:58249 std::string expected_id_;
250
[email protected]21a5ad62012-04-03 04:48:45251 // A parsed copy of the expected manifest, before any transformations like
252 // localization have taken place. If |approved_| is true, then the
253 // extension's manifest must match this for the install to proceed.
254 scoped_ptr<base::DictionaryValue> expected_manifest_;
255
[email protected]604322d2011-03-22 16:51:56256 // If non-NULL, contains the expected version of the extension we're
257 // installing. Important for external sources, where claiming the wrong
258 // version could cause unnessisary unpacking of an extension at every
259 // restart.
260 scoped_ptr<Version> expected_version_;
261
[email protected]2a464a92009-08-01 17:58:35262 // Whether manual extension installation is enabled. We can't just check this
263 // before trying to install because themes are special-cased to always be
264 // allowed.
[email protected]7577a5c52009-07-30 06:21:58265 bool extensions_enabled_;
266
[email protected]6dfbbf82010-03-12 23:09:16267 // Whether we're supposed to delete the source file on destruction. Defaults
268 // to false.
[email protected]6657afa62009-11-04 02:15:20269 bool delete_source_;
[email protected]7577a5c52009-07-30 06:21:58270
[email protected]655b2b1a2011-10-13 17:13:06271 // The download URL, before redirects, if this is a gallery install.
272 GURL original_download_url_;
273
[email protected]21217ca2010-01-19 07:18:45274 // Whether to create an app shortcut after successful installation. This is
275 // set based on the user's selection in the UI and can only ever be true for
276 // apps.
277 bool create_app_shortcut_;
278
[email protected]7577a5c52009-07-30 06:21:58279 // The extension we're installing. We own this and either pass it off to
[email protected]eaa7dd182010-12-14 11:09:00280 // ExtensionService on success, or delete it on failure.
[email protected]bf3d9df2012-07-24 23:20:27281 scoped_refptr<const Extension> extension_;
[email protected]7577a5c52009-07-30 06:21:58282
[email protected]36a5c4c2011-12-14 16:34:50283 // The ordinal of the NTP apps page |extension_| will be shown on.
[email protected]36b643212012-09-07 12:53:00284 syncer::StringOrdinal page_ordinal_;
[email protected]cc829cf2011-08-22 21:01:35285
[email protected]ad93c6ba2011-05-26 04:48:33286 // A parsed copy of the unmodified original manifest, before any
287 // transformations like localization have taken place.
[email protected]f3a1c642011-07-12 19:15:03288 scoped_ptr<base::DictionaryValue> original_manifest_;
[email protected]ad93c6ba2011-05-26 04:48:33289
[email protected]b6ab96d2009-08-20 18:58:19290 // If non-empty, contains the current version of the extension we're
291 // installing (for upgrades).
292 std::string current_version_;
293
[email protected]d2817012009-08-04 06:46:21294 // The icon we will display in the installation UI, if any.
295 scoped_ptr<SkBitmap> install_icon_;
296
[email protected]7577a5c52009-07-30 06:21:58297 // The temp directory extension resources were unpacked to. We own this and
298 // must delete it when we are done with it.
299 FilePath temp_dir_;
300
301 // The frontend we will report results back to.
[email protected]14908b72011-04-20 06:54:36302 base::WeakPtr<ExtensionService> frontend_weak_;
[email protected]7577a5c52009-07-30 06:21:58303
[email protected]655b2b1a2011-10-13 17:13:06304 // The Profile where the extension is being installed in.
305 Profile* profile_;
306
[email protected]2a464a92009-08-01 17:58:35307 // The client we will work with to do the installation. This can be NULL, in
308 // which case the install is silent.
[email protected]765b7ea52010-03-30 03:40:34309 // NOTE: we may be deleted on the file thread. To ensure the UI is deleted on
310 // the main thread we don't use a scoped_ptr here.
[email protected]c82da8c42012-06-08 19:49:11311 ExtensionInstallPrompt* client_;
[email protected]2a464a92009-08-01 17:58:35312
[email protected]7577a5c52009-07-30 06:21:58313 // The root of the unpacked extension directory. This is a subdirectory of
314 // temp_dir_, so we don't have to delete it explicitly.
315 FilePath unpacked_extension_root_;
316
[email protected]d4a71882010-06-25 16:36:41317 // True when the CRX being installed was just downloaded.
318 // Used to trigger extra checks before installing.
319 bool apps_require_extension_mime_type_;
320
[email protected]dd9d6272010-09-09 17:33:18321 // Allows for the possibility of a normal install (one in which a |client|
322 // is provided in the ctor) to procede without showing the permissions prompt
323 // dialog. Note that this will only take place if |allow_silent_install_|
324 // is true AND the unpacked id of the extension is whitelisted with
325 // SetWhitelistedInstallId().
326 bool allow_silent_install_;
327
[email protected]d4a71882010-06-25 16:36:41328 // The value of the content type header sent with the CRX.
329 // Ignorred unless |require_extension_mime_type_| is true.
330 std::string original_mime_type_;
331
[email protected]cb0e50312011-05-09 15:03:07332 // What caused this install? Used only for histograms that report
333 // on failure rates, broken down by the cause of the install.
334 extension_misc::CrxInstallCause install_cause_;
335
[email protected]1bf73cc2011-10-26 22:38:31336 // Creation flags to use for the extension. These flags will be used
337 // when calling Extenion::Create() by the crx installer.
338 int creation_flags_;
339
[email protected]a9736892012-05-30 15:58:05340 // Whether to allow off store installation.
[email protected]d9039812012-06-09 06:05:48341 OffStoreInstallAllowReason off_store_install_allow_reason_;
[email protected]a9736892012-05-30 15:58:05342
[email protected]86a99112012-06-19 01:18:07343 // Whether the installation was handled successfully. This is used to
344 // indicate to the client whether the file should be removed and any UI
345 // initiating the installation can be removed. This is different than whether
346 // there was an error; if there was an error that rejects installation we
347 // still consider the installation 'handled'.
348 bool did_handle_successfully_;
349
[email protected]b70a2d92012-06-28 19:51:21350 // Whether we should record an oauth2 grant upon successful install.
351 bool record_oauth2_grant_;
352
[email protected]98270432012-09-11 20:51:24353 // Whether we should produce an error if the manifest declares requirements
354 // that are not met. If false and there is an unmet requirement, the install
355 // will continue but the extension will be distabled.
356 bool error_on_unsupported_requirements_;
357
358 scoped_ptr<RequirementsChecker> requirements_checker_;
359
360 bool has_requirement_errors_;
361
[email protected]7577a5c52009-07-30 06:21:58362 DISALLOW_COPY_AND_ASSIGN(CrxInstaller);
363};
364
[email protected]bf3d9df2012-07-24 23:20:27365} // namespace extensions
366
[email protected]7577a5c52009-07-30 06:21:58367#endif // CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_