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