Add a webstorePrivate API to show a permission prompt for delegated bundle installs
[chromium-blink-merge.git] / chrome / browser / extensions / crx_installer.h
blob43b54f2f40ba4ac34671287a99957ece66e951b9
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_CRX_INSTALLER_H_
6 #define CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
8 #include <string>
9 #include <vector>
11 #include "base/compiler_specific.h"
12 #include "base/files/file_path.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/version.h"
16 #include "chrome/browser/extensions/extension_install_checker.h"
17 #include "chrome/browser/extensions/extension_install_prompt.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/webstore_installer.h"
20 #include "chrome/common/extensions/extension_constants.h"
21 #include "extensions/browser/install_flag.h"
22 #include "extensions/browser/sandboxed_unpacker.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/manifest.h"
25 #include "sync/api/string_ordinal.h"
27 class ExtensionService;
28 class ExtensionServiceTest;
29 class SkBitmap;
30 struct WebApplicationInfo;
32 namespace base {
33 class SequencedTaskRunner;
36 namespace extensions {
37 class CrxInstallError;
38 class ExtensionUpdaterTest;
39 class RequirementsChecker;
41 // This class installs a crx file into a profile.
43 // Installing a CRX is a multi-step process, including unpacking the crx,
44 // validating it, prompting the user, and installing. Since many of these
45 // steps must occur on the file thread, this class contains a copy of all data
46 // necessary to do its job. (This also minimizes external dependencies for
47 // easier testing).
49 // Lifetime management:
51 // This class is ref-counted by each call it makes to itself on another thread,
52 // and by UtilityProcessHost.
54 // Additionally, we hold a reference to our own client so that it lives at least
55 // long enough to receive the result of unpacking.
57 // IMPORTANT: Callers should keep a reference to a CrxInstaller while they are
58 // working with it, eg:
60 // scoped_refptr<CrxInstaller> installer(new CrxInstaller(...));
61 // installer->set_foo();
62 // installer->set_bar();
63 // installer->InstallCrx(...);
65 // Installation is aborted if the extension service learns that Chrome is
66 // terminating during the install. We can't listen for the app termination
67 // notification here in this class because it can be destroyed on any thread
68 // and won't safely be able to clean up UI thread notification listeners.
69 class CrxInstaller
70 : public SandboxedUnpackerClient,
71 public ExtensionInstallPrompt::Delegate {
72 public:
73 // Used in histograms; do not change order.
74 enum OffStoreInstallAllowReason {
75 OffStoreInstallDisallowed,
76 OffStoreInstallAllowedFromSettingsPage,
77 OffStoreInstallAllowedBecausePref,
78 OffStoreInstallAllowedInTest,
79 NumOffStoreInstallAllowReasons
82 // Extensions will be installed into service->install_directory(), then
83 // registered with |service|. This does a silent install - see below for
84 // other options.
85 static scoped_refptr<CrxInstaller> CreateSilent(ExtensionService* service);
87 // Same as above, but use |client| to generate a confirmation prompt.
88 static scoped_refptr<CrxInstaller> Create(
89 ExtensionService* service,
90 scoped_ptr<ExtensionInstallPrompt> client);
92 // Same as the previous method, except use the |approval| to bypass the
93 // prompt. Note that the caller retains ownership of |approval|.
94 static scoped_refptr<CrxInstaller> Create(
95 ExtensionService* service,
96 scoped_ptr<ExtensionInstallPrompt> client,
97 const WebstoreInstaller::Approval* approval);
99 // Install the crx in |source_file|.
100 void InstallCrx(const base::FilePath& source_file);
101 void InstallCrxFile(const CRXFileInfo& source_file);
103 // Convert the specified user script into an extension and install it.
104 void InstallUserScript(const base::FilePath& source_file,
105 const GURL& download_url);
107 // Convert the specified web app into an extension and install it.
108 void InstallWebApp(const WebApplicationInfo& web_app);
110 // Overridden from ExtensionInstallPrompt::Delegate:
111 void InstallUIProceed() override;
112 void InstallUIAbort(bool user_initiated) override;
114 int creation_flags() const { return creation_flags_; }
115 void set_creation_flags(int val) { creation_flags_ = val; }
117 const base::FilePath& source_file() const { return source_file_; }
119 Manifest::Location install_source() const {
120 return install_source_;
122 void set_install_source(Manifest::Location source) {
123 install_source_ = source;
126 const std::string& expected_id() const { return expected_id_; }
127 void set_expected_id(const std::string& val) { expected_id_ = val; }
129 // Expected SHA256 hash sum for the package.
130 const std::string& expected_hash() const { return expected_hash_; }
131 void set_expected_hash(const std::string& val) { expected_hash_ = val; }
133 bool hash_check_failed() const { return hash_check_failed_; }
134 void set_hash_check_failed(bool val) { hash_check_failed_ = val; }
136 void set_expected_version(const Version& val) {
137 expected_version_.reset(new Version(val));
138 expected_version_strict_checking_ = true;
141 bool delete_source() const { return delete_source_; }
142 void set_delete_source(bool val) { delete_source_ = val; }
144 bool allow_silent_install() const { return allow_silent_install_; }
145 void set_allow_silent_install(bool val) { allow_silent_install_ = val; }
147 bool grant_permissions() const { return grant_permissions_; }
148 void set_grant_permissions(bool val) { grant_permissions_ = val; }
150 bool is_gallery_install() const {
151 return (creation_flags_ & Extension::FROM_WEBSTORE) > 0;
153 void set_is_gallery_install(bool val) {
154 if (val)
155 creation_flags_ |= Extension::FROM_WEBSTORE;
156 else
157 creation_flags_ &= ~Extension::FROM_WEBSTORE;
160 // If |apps_require_extension_mime_type_| is set to true, be sure to set
161 // |original_mime_type_| as well.
162 void set_apps_require_extension_mime_type(
163 bool apps_require_extension_mime_type) {
164 apps_require_extension_mime_type_ = apps_require_extension_mime_type;
167 void set_original_mime_type(const std::string& original_mime_type) {
168 original_mime_type_ = original_mime_type;
171 extension_misc::CrxInstallCause install_cause() const {
172 return install_cause_;
174 void set_install_cause(extension_misc::CrxInstallCause install_cause) {
175 install_cause_ = install_cause;
178 OffStoreInstallAllowReason off_store_install_allow_reason() const {
179 return off_store_install_allow_reason_;
181 void set_off_store_install_allow_reason(OffStoreInstallAllowReason reason) {
182 off_store_install_allow_reason_ = reason;
185 void set_page_ordinal(const syncer::StringOrdinal& page_ordinal) {
186 page_ordinal_ = page_ordinal;
189 void set_error_on_unsupported_requirements(bool val) {
190 error_on_unsupported_requirements_ = val;
193 void set_install_immediately(bool val) {
194 set_install_flag(kInstallFlagInstallImmediately, val);
196 void set_is_ephemeral(bool val) {
197 set_install_flag(kInstallFlagIsEphemeral, val);
199 void set_do_not_sync(bool val) {
200 set_install_flag(kInstallFlagDoNotSync, val);
203 bool did_handle_successfully() const { return did_handle_successfully_; }
205 Profile* profile() { return install_checker_.profile(); }
207 const Extension* extension() { return install_checker_.extension().get(); }
209 const std::string& current_version() const { return current_version_; }
211 private:
212 friend class ::ExtensionServiceTest;
213 friend class ExtensionUpdaterTest;
214 friend class ExtensionCrxInstallerTest;
216 CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
217 scoped_ptr<ExtensionInstallPrompt> client,
218 const WebstoreInstaller::Approval* approval);
219 ~CrxInstaller() override;
221 // Converts the source user script to an extension.
222 void ConvertUserScriptOnFileThread();
224 // Converts the source web app to an extension.
225 void ConvertWebAppOnFileThread(const WebApplicationInfo& web_app);
227 // Called after OnUnpackSuccess as a last check to see whether the install
228 // should complete.
229 CrxInstallError AllowInstall(const Extension* extension);
231 // SandboxedUnpackerClient
232 void OnUnpackFailure(const CrxInstallError& error) override;
233 void OnUnpackSuccess(const base::FilePath& temp_dir,
234 const base::FilePath& extension_dir,
235 const base::DictionaryValue* original_manifest,
236 const Extension* extension,
237 const SkBitmap& install_icon) override;
239 // Called on the UI thread to start the requirements, policy and blacklist
240 // checks on the extension.
241 void CheckInstall();
243 // Runs on the UI thread. Callback from ExtensionInstallChecker.
244 void OnInstallChecksComplete(int failed_checks);
246 // Runs on the UI thread. Callback from Blacklist.
247 void OnBlacklistChecked(
248 extensions::BlacklistState blacklist_state);
250 // Runs on the UI thread. Confirms the installation to the ExtensionService.
251 void ConfirmInstall();
253 // Runs on File thread. Install the unpacked extension into the profile and
254 // notify the frontend.
255 void CompleteInstall();
257 // Reloads extension on File thread and reports installation result back
258 // to UI thread.
259 void ReloadExtensionAfterInstall(const base::FilePath& version_dir);
261 // Result reporting.
262 void ReportFailureFromFileThread(const CrxInstallError& error);
263 void ReportFailureFromUIThread(const CrxInstallError& error);
264 void ReportSuccessFromFileThread();
265 void ReportSuccessFromUIThread();
266 void NotifyCrxInstallBegin();
267 void NotifyCrxInstallComplete(bool success);
269 // Deletes temporary directory and crx file if needed.
270 void CleanupTempFiles();
272 // Checks whether the current installation is initiated by the user from
273 // the extension settings page to update an existing extension or app.
274 void CheckUpdateFromSettingsPage();
276 // Show re-enable prompt if the update is initiated from the settings page
277 // and needs additional permissions.
278 void ConfirmReEnable();
280 void set_install_flag(int flag, bool val) {
281 if (val)
282 install_flags_ |= flag;
283 else
284 install_flags_ &= ~flag;
287 // The file we're installing.
288 base::FilePath source_file_;
290 // The URL the file was downloaded from.
291 GURL download_url_;
293 // The directory extensions are installed to.
294 const base::FilePath install_directory_;
296 // The location the installation came from (bundled with Chromium, registry,
297 // manual install, etc). This metadata is saved with the installation if
298 // successful. Defaults to INTERNAL.
299 Manifest::Location install_source_;
301 // Indicates whether the user has already approved the extension to be
302 // installed. If true, |expected_manifest_| and |expected_id_| must match
303 // those of the CRX.
304 bool approved_;
306 // For updates, external and webstore installs we have an ID we're expecting
307 // the extension to contain.
308 std::string expected_id_;
310 // An expected hash sum for the .crx file.
311 std::string expected_hash_;
313 // True if installation failed due to a hash sum mismatch.
314 bool hash_check_failed_;
316 // A parsed copy of the expected manifest, before any transformations like
317 // localization have taken place. If |approved_| is true, then the
318 // extension's manifest must match this for the install to proceed.
319 scoped_ptr<Manifest> expected_manifest_;
321 // The level of checking when comparing the actual manifest against
322 // the |expected_manifest_|.
323 WebstoreInstaller::ManifestCheckLevel expected_manifest_check_level_;
325 // If non-NULL, contains the expected version of the extension we're
326 // installing. Important for external sources, where claiming the wrong
327 // version could cause unnecessary unpacking of an extension at every
328 // restart.
329 scoped_ptr<Version> expected_version_;
331 // If true, the actual version should be same with the |expected_version_|,
332 // Otherwise the actual version should be equal to or newer than
333 // the |expected_version_|.
334 bool expected_version_strict_checking_;
336 // Whether manual extension installation is enabled. We can't just check this
337 // before trying to install because themes are special-cased to always be
338 // allowed.
339 bool extensions_enabled_;
341 // Whether we're supposed to delete the source file on destruction. Defaults
342 // to false.
343 bool delete_source_;
345 // Whether to create an app shortcut after successful installation. This is
346 // set based on the user's selection in the UI and can only ever be true for
347 // apps.
348 bool create_app_shortcut_;
350 // The ordinal of the NTP apps page |extension_| will be shown on.
351 syncer::StringOrdinal page_ordinal_;
353 // A parsed copy of the unmodified original manifest, before any
354 // transformations like localization have taken place.
355 scoped_ptr<Manifest> original_manifest_;
357 // If non-empty, contains the current version of the extension we're
358 // installing (for upgrades).
359 std::string current_version_;
361 // The icon we will display in the installation UI, if any.
362 scoped_ptr<SkBitmap> install_icon_;
364 // The temp directory extension resources were unpacked to. We own this and
365 // must delete it when we are done with it.
366 base::FilePath temp_dir_;
368 // The frontend we will report results back to.
369 base::WeakPtr<ExtensionService> service_weak_;
371 // The client we will work with to do the installation. This can be NULL, in
372 // which case the install is silent.
373 scoped_ptr<ExtensionInstallPrompt> client_;
375 // The root of the unpacked extension directory. This is a subdirectory of
376 // temp_dir_, so we don't have to delete it explicitly.
377 base::FilePath unpacked_extension_root_;
379 // True when the CRX being installed was just downloaded.
380 // Used to trigger extra checks before installing.
381 bool apps_require_extension_mime_type_;
383 // Allows for the possibility of a normal install (one in which a |client|
384 // is provided in the ctor) to proceed without showing the permissions prompt
385 // dialog.
386 bool allow_silent_install_;
388 // Allows for the possibility of an installation without granting any
389 // permissions to the extension.
390 bool grant_permissions_;
392 // The value of the content type header sent with the CRX.
393 // Ignorred unless |require_extension_mime_type_| is true.
394 std::string original_mime_type_;
396 // What caused this install? Used only for histograms that report
397 // on failure rates, broken down by the cause of the install.
398 extension_misc::CrxInstallCause install_cause_;
400 // Creation flags to use for the extension. These flags will be used
401 // when calling Extenion::Create() by the crx installer.
402 int creation_flags_;
404 // Whether to allow off store installation.
405 OffStoreInstallAllowReason off_store_install_allow_reason_;
407 // Whether the installation was handled successfully. This is used to
408 // indicate to the client whether the file should be removed and any UI
409 // initiating the installation can be removed. This is different than whether
410 // there was an error; if there was an error that rejects installation we
411 // still consider the installation 'handled'.
412 bool did_handle_successfully_;
414 // Whether we should produce an error if the manifest declares requirements
415 // that are not met. If false and there is an unmet requirement, the install
416 // will continue but the extension will be distabled.
417 bool error_on_unsupported_requirements_;
419 // Sequenced task runner where file I/O operations will be performed.
420 scoped_refptr<base::SequencedTaskRunner> installer_task_runner_;
422 // Used to show the install dialog.
423 ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback_;
425 // Whether the update is initiated by the user from the extension settings
426 // page.
427 bool update_from_settings_page_;
429 // The flags for ExtensionService::OnExtensionInstalled.
430 int install_flags_;
432 // Performs requirements, policy and blacklist checks on the extension.
433 ExtensionInstallChecker install_checker_;
435 DISALLOW_COPY_AND_ASSIGN(CrxInstaller);
438 } // namespace extensions
440 #endif // CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_