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_CRX_INSTALLER_H_
6 #define CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/optional.h"
19 #include "base/version.h"
20 #include "chrome/browser/extensions/extension_install_prompt.h"
21 #include "chrome/browser/extensions/extension_service.h"
22 #include "chrome/browser/extensions/webstore_installer.h"
23 #include "chrome/common/extensions/extension_constants.h"
24 #include "components/sync/model/string_ordinal.h"
25 #include "extensions/browser/api/declarative_net_request/ruleset_install_pref.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/browser/install_flag.h"
28 #include "extensions/browser/preload_check.h"
29 #include "extensions/browser/sandboxed_unpacker.h"
30 #include "extensions/common/extension.h"
31 #include "extensions/common/manifest.h"
32 
33 class ExtensionServiceTest;
34 class SkBitmap;
35 struct WebApplicationInfo;
36 
37 namespace base {
38 class SequencedTaskRunner;
39 }
40 
41 namespace extensions {
42 class CrxInstallError;
43 class ExtensionService;
44 class ExtensionUpdaterTest;
45 enum class InstallationStage;
46 class PreloadCheckGroup;
47 
48 // This class installs a crx file into a profile.
49 //
50 // Installing a CRX is a multi-step process, including unpacking the crx,
51 // validating it, prompting the user, and installing. Since many of these
52 // steps must occur on the file thread, this class contains a copy of all data
53 // necessary to do its job. (This also minimizes external dependencies for
54 // easier testing).
55 //
56 // Lifetime management:
57 //
58 // This class is ref-counted by each call it makes to itself on another thread,
59 // and by UtilityProcessHost.
60 //
61 // Additionally, we hold a reference to our own client so that it lives at least
62 // long enough to receive the result of unpacking.
63 //
64 // IMPORTANT: Callers should keep a reference to a CrxInstaller while they are
65 // working with it, eg:
66 //
67 // scoped_refptr<CrxInstaller> installer(new CrxInstaller(...));
68 // installer->set_foo();
69 // installer->set_bar();
70 // installer->InstallCrx(...);
71 //
72 // Installation is aborted if the extension service learns that Chrome is
73 // terminating during the install. We can't listen for the app termination
74 // notification here in this class because it can be destroyed on any thread
75 // and won't safely be able to clean up UI thread notification listeners.
76 class CrxInstaller : public SandboxedUnpackerClient {
77  public:
78   // A callback to be executed when the install finishes.
79   using InstallerResultCallback = ExtensionSystem::InstallUpdateCallback;
80 
81   using ExpectationsVerifiedCallback = base::OnceClosure;
82 
83   // Used in histograms; do not change order.
84   enum OffStoreInstallAllowReason {
85     OffStoreInstallDisallowed,
86     OffStoreInstallAllowedFromSettingsPage,
87     OffStoreInstallAllowedBecausePref,
88     OffStoreInstallAllowedInTest,
89     NumOffStoreInstallAllowReasons
90   };
91 
92   // Used to indicate if host permissions should be withheld during
93   // installation.
94   enum WithholdingBehavior { kWithholdPermissions, kDontWithholdPermissions };
95 
96   // Extensions will be installed into service->install_directory(), then
97   // registered with |service|. This does a silent install - see below for
98   // other options.
99   static scoped_refptr<CrxInstaller> CreateSilent(ExtensionService* service);
100 
101   // Same as above, but use |client| to generate a confirmation prompt.
102   static scoped_refptr<CrxInstaller> Create(
103       ExtensionService* service,
104       std::unique_ptr<ExtensionInstallPrompt> client);
105 
106   // Same as the previous method, except use the |approval| to bypass the
107   // prompt. Note that the caller retains ownership of |approval|.
108   static scoped_refptr<CrxInstaller> Create(
109       ExtensionService* service,
110       std::unique_ptr<ExtensionInstallPrompt> client,
111       const WebstoreInstaller::Approval* approval);
112 
113   // Install the crx in |source_file|. The file must be a CRX3. A publisher
114   // proof in the file is required unless off-webstore installation is allowed.
115   void InstallCrx(const base::FilePath& source_file);
116 
117   // Install the crx in |source_file|.
118   void InstallCrxFile(const CRXFileInfo& source_file);
119 
120   // Install the unpacked crx in |unpacked_dir|.
121   // If |delete_source_| is true, |unpacked_dir| will be removed at the end of
122   // the installation.
123   void InstallUnpackedCrx(const std::string& extension_id,
124                           const std::string& public_key,
125                           const base::FilePath& unpacked_dir);
126 
127   // Convert the specified user script into an extension and install it.
128   void InstallUserScript(const base::FilePath& source_file,
129                          const GURL& download_url);
130 
131   // Convert the specified web app into an extension and install it.
132   // Virtual for testing.
133   virtual void InstallWebApp(const WebApplicationInfo& web_app);
134 
135   // Update the extension |extension_id| with the unpacked crx in
136   // |unpacked_dir|.
137   // If |delete_source_| is true, |unpacked_dir| will be removed at the end of
138   // the update.
139   void UpdateExtensionFromUnpackedCrx(const std::string& extension_id,
140                                       const std::string& public_key,
141                                       const base::FilePath& unpacked_dir);
142 
143   void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
144 
145   void InitializeCreationFlagsForUpdate(const Extension* extension,
146                                         const int initial_flags);
147 
creation_flags()148   int creation_flags() const { return creation_flags_; }
set_creation_flags(int val)149   void set_creation_flags(int val) { creation_flags_ = val; }
150 
source_file()151   const base::FilePath& source_file() const { return source_file_; }
152 
install_source()153   Manifest::Location install_source() const {
154     return install_source_;
155   }
set_install_source(Manifest::Location source)156   void set_install_source(Manifest::Location source) {
157     install_source_ = source;
158   }
159 
expected_id()160   const std::string& expected_id() const { return expected_id_; }
set_expected_id(const std::string & val)161   void set_expected_id(const std::string& val) { expected_id_ = val; }
162 
163   // Expected SHA256 hash sum for the package.
expected_hash()164   const std::string& expected_hash() const { return expected_hash_; }
set_expected_hash(const std::string & val)165   void set_expected_hash(const std::string& val) { expected_hash_ = val; }
166 
verification_check_failed()167   bool verification_check_failed() const { return verification_check_failed_; }
set_verification_check_failed(bool val)168   void set_verification_check_failed(bool val) {
169     verification_check_failed_ = val;
170   }
171 
172   // Set the exact version the installed extension should have. If
173   // |fail_install_if_unexpected| is true, installation will fail if the actual
174   // version doesn't match. If it is false, the installation will still
175   // be performed, but the extension will not be granted any permissions.
set_expected_version(const base::Version & val,bool fail_install_if_unexpected)176   void set_expected_version(const base::Version& val,
177                             bool fail_install_if_unexpected) {
178     expected_version_ = val;
179     fail_install_if_unexpected_version_ = fail_install_if_unexpected;
180   }
181 
delete_source()182   bool delete_source() const { return delete_source_; }
set_delete_source(bool val)183   void set_delete_source(bool val) { delete_source_ = val; }
184 
allow_silent_install()185   bool allow_silent_install() const { return allow_silent_install_; }
set_allow_silent_install(bool val)186   void set_allow_silent_install(bool val) { allow_silent_install_ = val; }
187 
grant_permissions()188   bool grant_permissions() const { return grant_permissions_; }
set_grant_permissions(bool val)189   void set_grant_permissions(bool val) { grant_permissions_ = val; }
190 
is_gallery_install()191   bool is_gallery_install() const {
192     return (creation_flags_ & Extension::FROM_WEBSTORE) > 0;
193   }
set_is_gallery_install(bool val)194   void set_is_gallery_install(bool val) {
195     if (val)
196       creation_flags_ |= Extension::FROM_WEBSTORE;
197     else
198       creation_flags_ &= ~Extension::FROM_WEBSTORE;
199   }
200 
201   // If |apps_require_extension_mime_type_| is set to true, be sure to set
202   // |original_mime_type_| as well.
set_apps_require_extension_mime_type(bool apps_require_extension_mime_type)203   void set_apps_require_extension_mime_type(
204       bool apps_require_extension_mime_type) {
205     apps_require_extension_mime_type_ = apps_require_extension_mime_type;
206   }
207 
set_original_mime_type(const std::string & original_mime_type)208   void set_original_mime_type(const std::string& original_mime_type) {
209     original_mime_type_ = original_mime_type;
210   }
211 
install_cause()212   extension_misc::CrxInstallCause install_cause() const {
213     return install_cause_;
214   }
set_install_cause(extension_misc::CrxInstallCause install_cause)215   void set_install_cause(extension_misc::CrxInstallCause install_cause) {
216     install_cause_ = install_cause;
217   }
218 
off_store_install_allow_reason()219   OffStoreInstallAllowReason off_store_install_allow_reason() const {
220     return off_store_install_allow_reason_;
221   }
set_off_store_install_allow_reason(OffStoreInstallAllowReason reason)222   void set_off_store_install_allow_reason(OffStoreInstallAllowReason reason) {
223     off_store_install_allow_reason_ = reason;
224   }
225 
set_page_ordinal(const syncer::StringOrdinal & page_ordinal)226   void set_page_ordinal(const syncer::StringOrdinal& page_ordinal) {
227     page_ordinal_ = page_ordinal;
228   }
229 
set_error_on_unsupported_requirements(bool val)230   void set_error_on_unsupported_requirements(bool val) {
231     error_on_unsupported_requirements_ = val;
232   }
233 
set_install_immediately(bool val)234   void set_install_immediately(bool val) {
235     set_install_flag(kInstallFlagInstallImmediately, val);
236   }
set_do_not_sync(bool val)237   void set_do_not_sync(bool val) {
238     set_install_flag(kInstallFlagDoNotSync, val);
239   }
240 
241   // Virtual for testing.
242   virtual void set_installer_callback(InstallerResultCallback callback);
243 
244   // Callback to be invoked when the crx file has passed the expectations check
245   // after unpack success and the ownership of the crx file lies with the
246   // installer. The callback is passed the ownership of the crx file.
247   void set_expectations_verified_callback(
248       ExpectationsVerifiedCallback callback);
249 
did_handle_successfully()250   bool did_handle_successfully() const { return did_handle_successfully_; }
251 
profile()252   Profile* profile() { return profile_; }
253 
extension()254   const Extension* extension() { return extension_.get(); }
255 
256   // The currently installed version of the extension, for updates. Will be
257   // invalid if this isn't an update.
current_version()258   const base::Version& current_version() const { return current_version_; }
259 
260  private:
261   friend class ::ExtensionServiceTest;
262   friend class BookmarkAppInstallFinalizerTest;
263   friend class ExtensionUpdaterTest;
264 
265   CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
266                std::unique_ptr<ExtensionInstallPrompt> client,
267                const WebstoreInstaller::Approval* approval);
268   ~CrxInstaller() override;
269 
270   // Converts the source user script to an extension.
271   void ConvertUserScriptOnSharedFileThread();
272 
273   // Converts the source web app to an extension.
274   void ConvertWebAppOnSharedFileThread(const WebApplicationInfo& web_app);
275 
276   // Called after OnUnpackSuccess check to see whether the install expectations
277   // are met and the install process should continue.
278   base::Optional<CrxInstallError> CheckExpectations(const Extension* extension);
279 
280   // Called after OnUnpackSuccess as a last check to see whether the install
281   // should complete.
282   base::Optional<CrxInstallError> AllowInstall(const Extension* extension);
283 
284   // To check whether we need to compute hashes or not, we have to make a query
285   // to ContentVerifier, and that should be done on the UI thread.
286   void ShouldComputeHashesOnUI(scoped_refptr<const Extension> extension,
287                                base::OnceCallback<void(bool)> callback);
288 
289   // SandboxedUnpackerClient
290   void ShouldComputeHashesForOffWebstoreExtension(
291       scoped_refptr<const Extension> extension,
292       base::OnceCallback<void(bool)> callback) override;
293   void OnUnpackFailure(const CrxInstallError& error) override;
294   void OnUnpackSuccess(const base::FilePath& temp_dir,
295                        const base::FilePath& extension_dir,
296                        std::unique_ptr<base::DictionaryValue> original_manifest,
297                        const Extension* extension,
298                        const SkBitmap& install_icon,
299                        declarative_net_request::RulesetInstallPrefs
300                            ruleset_install_prefs) override;
301   void OnStageChanged(InstallationStage stage) override;
302 
303   // Called on the UI thread to start the requirements, policy and blocklist
304   // checks on the extension.
305   void CheckInstall();
306 
307   // Runs on the UI thread. Callback from PreloadCheckGroup.
308   void OnInstallChecksComplete(const PreloadCheck::Errors& errors);
309 
310   // Runs on the UI thread. Confirms the installation to the ExtensionService.
311   void ConfirmInstall();
312 
313   // Runs on the UI thread. Updates the creation flags for the extension and
314   // calls CompleteInstall().
315   void UpdateCreationFlagsAndCompleteInstall(
316       WithholdingBehavior withholding_behavior);
317 
318   // Runs on File thread. Install the unpacked extension into the profile and
319   // notify the frontend.
320   void CompleteInstall();
321 
322   // Reloads extension on File thread and reports installation result back
323   // to UI thread.
324   void ReloadExtensionAfterInstall(const base::FilePath& version_dir);
325 
326   // Result reporting.
327   void ReportFailureFromSharedFileThread(const CrxInstallError& error);
328   void ReportFailureFromUIThread(const CrxInstallError& error);
329   void ReportSuccessFromSharedFileThread();
330   void ReportSuccessFromUIThread();
331   // Always report from the UI thread.
332   void ReportInstallationStage(InstallationStage stage);
333   void NotifyCrxInstallBegin();
334   void NotifyCrxInstallComplete(const base::Optional<CrxInstallError>& error);
335 
336   // Deletes temporary directory and crx file if needed.
337   void CleanupTempFiles();
338 
339   // Checks whether the current installation is initiated by the user from
340   // the extension settings page to update an existing extension or app.
341   void CheckUpdateFromSettingsPage();
342 
343   // Show re-enable prompt if the update is initiated from the settings page
344   // and needs additional permissions.
345   void ConfirmReEnable();
346 
347   // OnUnpackSuccess() gets called on the unpacker sequence. It calls this
348   // method on the shared file sequence, to avoid race conditions.
349   virtual void OnUnpackSuccessOnSharedFileThread(
350       base::FilePath temp_dir,
351       base::FilePath extension_dir,
352       std::unique_ptr<base::DictionaryValue> original_manifest,
353       scoped_refptr<const Extension> extension,
354       SkBitmap install_icon,
355       declarative_net_request::RulesetInstallPrefs ruleset_install_prefs);
356 
set_install_flag(int flag,bool val)357   void set_install_flag(int flag, bool val) {
358     if (val)
359       install_flags_ |= flag;
360     else
361       install_flags_ &= ~flag;
362   }
363 
364   // Returns |unpacker_task_runner_|. Initializes it if it's still nullptr.
365   base::SequencedTaskRunner* GetUnpackerTaskRunner();
366 
367   // The Profile the extension is being installed in.
368   Profile* profile_;
369 
370   // The extension being installed.
371   scoped_refptr<const Extension> extension_;
372 
373   // The file we're installing.
374   base::FilePath source_file_;
375 
376   // The URL the file was downloaded from.
377   GURL download_url_;
378 
379   // The directory extensions are installed to.
380   const base::FilePath install_directory_;
381 
382   // The location the installation came from (bundled with Chromium, registry,
383   // manual install, etc). This metadata is saved with the installation if
384   // successful. Defaults to INTERNAL.
385   Manifest::Location install_source_;
386 
387   // Indicates whether the user has already approved the extension to be
388   // installed. If true, |expected_manifest_| and |expected_id_| must match
389   // those of the CRX.
390   bool approved_;
391 
392   // For updates, external and webstore installs we have an ID we're expecting
393   // the extension to contain.
394   std::string expected_id_;
395 
396   // An expected hash sum for the .crx file.
397   std::string expected_hash_;
398 
399   // True if installation failed due to a hash sum mismatch or expectations
400   // mismatch.
401   bool verification_check_failed_;
402 
403   // A parsed copy of the expected manifest, before any transformations like
404   // localization have taken place. If |approved_| is true, then the
405   // extension's manifest must match this for the install to proceed.
406   std::unique_ptr<Manifest> expected_manifest_;
407 
408   // The level of checking when comparing the actual manifest against
409   // the |expected_manifest_|.
410   WebstoreInstaller::ManifestCheckLevel expected_manifest_check_level_;
411 
412   // If valid, specifies the minimum version we'll install. Installation will
413   // fail if the actual version is smaller.
414   base::Version minimum_version_;
415 
416   // If valid, contains the expected version of the extension we're installing.
417   // Important for external sources, where claiming the wrong version could
418   // cause unnecessary unpacking of an extension at every restart.
419   // See also |fail_install_if_unexpected_version_|!
420   base::Version expected_version_;
421 
422   // If true, installation will fail if the actual version doesn't match
423   // |expected_version_|. If false, the extension will still be installed, but
424   // not granted any permissions.
425   bool fail_install_if_unexpected_version_;
426 
427   // Whether manual extension installation is enabled. We can't just check this
428   // before trying to install because themes and bookmark apps are special-cased
429   // to always be allowed.
430   bool extensions_enabled_;
431 
432   // Whether we're supposed to delete the source file on destruction. Defaults
433   // to false.
434   bool delete_source_;
435 
436   // The ordinal of the NTP apps page |extension_| will be shown on.
437   syncer::StringOrdinal page_ordinal_;
438 
439   // A parsed copy of the unmodified original manifest, before any
440   // transformations like localization have taken place.
441   std::unique_ptr<Manifest> original_manifest_;
442 
443   // If valid, contains the current version of the extension we're
444   // installing (for upgrades).
445   base::Version current_version_;
446 
447   // The icon we will display in the installation UI, if any.
448   std::unique_ptr<SkBitmap> install_icon_;
449 
450   // The temp directory extension resources were unpacked to. We own this and
451   // must delete it when we are done with it.
452   base::FilePath temp_dir_;
453 
454   // The frontend we will report results back to.
455   base::WeakPtr<ExtensionService> service_weak_;
456 
457   // The client we will work with to do the installation. This can be NULL, in
458   // which case the install is silent.
459   std::unique_ptr<ExtensionInstallPrompt> client_;
460 
461   // The root of the unpacked extension directory. This is a subdirectory of
462   // temp_dir_, so we don't have to delete it explicitly.
463   base::FilePath unpacked_extension_root_;
464 
465   // True when the CRX being installed was just downloaded.
466   // Used to trigger extra checks before installing.
467   bool apps_require_extension_mime_type_;
468 
469   // Allows for the possibility of a normal install (one in which a |client|
470   // is provided in the ctor) to proceed without showing the permissions prompt
471   // dialog.
472   bool allow_silent_install_;
473 
474   // Allows for the possibility of an installation without granting any
475   // permissions to the extension.
476   bool grant_permissions_;
477 
478   // The value of the content type header sent with the CRX.
479   // Ignorred unless |require_extension_mime_type_| is true.
480   std::string original_mime_type_;
481 
482   // What caused this install?  Used only for histograms that report
483   // on failure rates, broken down by the cause of the install.
484   extension_misc::CrxInstallCause install_cause_;
485 
486   // Creation flags to use for the extension.  These flags will be used
487   // when calling Extension::Create() by the crx installer.
488   int creation_flags_;
489 
490   // Whether to allow off store installation.
491   OffStoreInstallAllowReason off_store_install_allow_reason_;
492 
493   // Whether the installation was handled successfully. This is used to
494   // indicate to the client whether the file should be removed and any UI
495   // initiating the installation can be removed. This is different than whether
496   // there was an error; if there was an error that rejects installation we
497   // still consider the installation 'handled'.
498   bool did_handle_successfully_;
499 
500   // Whether we should produce an error if the manifest declares requirements
501   // that are not met. If false and there is an unmet requirement, the install
502   // will continue but the extension will be distabled.
503   bool error_on_unsupported_requirements_;
504 
505   // Sequenced task runner where most file I/O operations will be performed.
506   scoped_refptr<base::SequencedTaskRunner> shared_file_task_runner_;
507 
508   // Sequenced task runner where the SandboxedUnpacker will run. Because the
509   // unpacker uses its own temp dir, it won't hit race conditions, and can use a
510   // separate task runner per instance (for better performance).
511   //
512   // Lazily initialized by GetUnpackerTaskRunner().
513   scoped_refptr<base::SequencedTaskRunner> unpacker_task_runner_ = nullptr;
514 
515   // Used to show the install dialog.
516   ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback_;
517 
518   // Whether the update is initiated by the user from the extension settings
519   // page.
520   bool update_from_settings_page_;
521 
522   // The flags for ExtensionService::OnExtensionInstalled.
523   int install_flags_;
524 
525   // Install prefs needed for the Declarative Net Request API.
526   declarative_net_request::RulesetInstallPrefs ruleset_install_prefs_;
527 
528   // Checks that may run before installing the extension.
529   std::unique_ptr<PreloadCheck> policy_check_;
530   std::unique_ptr<PreloadCheck> requirements_check_;
531   std::unique_ptr<PreloadCheck> blocklist_check_;
532 
533   // Runs the above checks.
534   std::unique_ptr<PreloadCheckGroup> check_group_;
535 
536   // Invoked when the install is completed.
537   InstallerResultCallback installer_callback_;
538 
539   // Invoked when the expectations from CRXFileInfo match with the crx file
540   // after unpack success.
541   ExpectationsVerifiedCallback expectations_verified_callback_;
542 
543   DISALLOW_COPY_AND_ASSIGN(CrxInstaller);
544 };
545 
546 }  // namespace extensions
547 
548 #endif  // CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
549