Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(518)

Side by Side Diff: chrome/browser/extensions/crx_installer.cc

Issue 381553002: Update the CrxInstaller and UnpackedInstaller to use the ExtensionInstallChecker (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comment Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/crx_installer.h" 5 #include "chrome/browser/extensions/crx_installer.h"
6 6
7 #include <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 27 matching lines...) Expand all
38 #include "chrome/common/chrome_paths.h" 38 #include "chrome/common/chrome_paths.h"
39 #include "chrome/common/extensions/extension_constants.h" 39 #include "chrome/common/extensions/extension_constants.h"
40 #include "chrome/common/extensions/manifest_url_handler.h" 40 #include "chrome/common/extensions/manifest_url_handler.h"
41 #include "content/public/browser/browser_thread.h" 41 #include "content/public/browser/browser_thread.h"
42 #include "content/public/browser/notification_service.h" 42 #include "content/public/browser/notification_service.h"
43 #include "content/public/browser/resource_dispatcher_host.h" 43 #include "content/public/browser/resource_dispatcher_host.h"
44 #include "content/public/browser/user_metrics.h" 44 #include "content/public/browser/user_metrics.h"
45 #include "extensions/browser/extension_prefs.h" 45 #include "extensions/browser/extension_prefs.h"
46 #include "extensions/browser/extension_system.h" 46 #include "extensions/browser/extension_system.h"
47 #include "extensions/browser/install_flag.h" 47 #include "extensions/browser/install_flag.h"
48 #include "extensions/browser/management_policy.h"
asargent_no_longer_on_chrome 2014/07/09 23:54:16 Do you actually use anything from this header file
tmdiep 2014/07/10 00:26:24 You're right, it's not used in this file. I intend
48 #include "extensions/common/extension_icon_set.h" 49 #include "extensions/common/extension_icon_set.h"
49 #include "extensions/common/feature_switch.h" 50 #include "extensions/common/feature_switch.h"
50 #include "extensions/common/file_util.h" 51 #include "extensions/common/file_util.h"
51 #include "extensions/common/manifest.h" 52 #include "extensions/common/manifest.h"
52 #include "extensions/common/manifest_handlers/kiosk_mode_info.h" 53 #include "extensions/common/manifest_handlers/kiosk_mode_info.h"
53 #include "extensions/common/manifest_handlers/shared_module_info.h" 54 #include "extensions/common/manifest_handlers/shared_module_info.h"
54 #include "extensions/common/permissions/permission_message_provider.h" 55 #include "extensions/common/permissions/permission_message_provider.h"
55 #include "extensions/common/permissions/permission_set.h" 56 #include "extensions/common/permissions/permission_set.h"
56 #include "extensions/common/permissions/permissions_data.h" 57 #include "extensions/common/permissions/permissions_data.h"
57 #include "extensions/common/user_script.h" 58 #include "extensions/common/user_script.h"
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 apps_require_extension_mime_type_(false), 127 apps_require_extension_mime_type_(false),
127 allow_silent_install_(false), 128 allow_silent_install_(false),
128 grant_permissions_(true), 129 grant_permissions_(true),
129 install_cause_(extension_misc::INSTALL_CAUSE_UNSET), 130 install_cause_(extension_misc::INSTALL_CAUSE_UNSET),
130 creation_flags_(Extension::NO_FLAGS), 131 creation_flags_(Extension::NO_FLAGS),
131 off_store_install_allow_reason_(OffStoreInstallDisallowed), 132 off_store_install_allow_reason_(OffStoreInstallDisallowed),
132 did_handle_successfully_(true), 133 did_handle_successfully_(true),
133 error_on_unsupported_requirements_(false), 134 error_on_unsupported_requirements_(false),
134 update_from_settings_page_(false), 135 update_from_settings_page_(false),
135 install_flags_(kInstallFlagNone), 136 install_flags_(kInstallFlagNone),
136 installer_(service_weak->profile()) { 137 install_checker_(service_weak->profile()) {
137 installer_task_runner_ = service_weak->GetFileTaskRunner(); 138 installer_task_runner_ = service_weak->GetFileTaskRunner();
138 if (!approval) 139 if (!approval)
139 return; 140 return;
140 141
141 CHECK(profile()->IsSameProfile(approval->profile)); 142 CHECK(profile()->IsSameProfile(approval->profile));
142 if (client_) { 143 if (client_) {
143 client_->install_ui()->SetUseAppInstalledBubble( 144 client_->install_ui()->SetUseAppInstalledBubble(
144 approval->use_app_installed_bubble); 145 approval->use_app_installed_bubble);
145 client_->install_ui()->set_skip_post_install_ui( 146 client_->install_ui()->set_skip_post_install_ui(
146 approval->skip_post_install_ui); 147 approval->skip_post_install_ui);
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 did_handle_successfully_ = false; 363 did_handle_successfully_ = false;
363 364
364 return CrxInstallerError( 365 return CrxInstallerError(
365 CrxInstallerError::ERROR_OFF_STORE, 366 CrxInstallerError::ERROR_OFF_STORE,
366 l10n_util::GetStringUTF16( 367 l10n_util::GetStringUTF16(
367 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE)); 368 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE));
368 } 369 }
369 } 370 }
370 } 371 }
371 372
372 if (installer_.extension()->is_app()) { 373 if (install_checker_.extension()->is_app()) {
373 // If the app was downloaded, apps_require_extension_mime_type_ 374 // If the app was downloaded, apps_require_extension_mime_type_
374 // will be set. In this case, check that it was served with the 375 // will be set. In this case, check that it was served with the
375 // right mime type. Make an exception for file URLs, which come 376 // right mime type. Make an exception for file URLs, which come
376 // from the users computer and have no headers. 377 // from the users computer and have no headers.
377 if (!download_url_.SchemeIsFile() && 378 if (!download_url_.SchemeIsFile() &&
378 apps_require_extension_mime_type_ && 379 apps_require_extension_mime_type_ &&
379 original_mime_type_ != Extension::kMimeType) { 380 original_mime_type_ != Extension::kMimeType) {
380 return CrxInstallerError( 381 return CrxInstallerError(
381 l10n_util::GetStringFUTF16( 382 l10n_util::GetStringFUTF16(
382 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE, 383 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE,
(...skipping 14 matching lines...) Expand all
397 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE))); 398 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)));
398 } 399 }
399 400
400 // For self-hosted apps, verify that the entire extent is on the same 401 // For self-hosted apps, verify that the entire extent is on the same
401 // host (or a subdomain of the host) the download happened from. There's 402 // host (or a subdomain of the host) the download happened from. There's
402 // no way for us to verify that the app controls any other hosts. 403 // no way for us to verify that the app controls any other hosts.
403 URLPattern pattern(UserScript::ValidUserScriptSchemes()); 404 URLPattern pattern(UserScript::ValidUserScriptSchemes());
404 pattern.SetHost(download_url_.host()); 405 pattern.SetHost(download_url_.host());
405 pattern.SetMatchSubdomains(true); 406 pattern.SetMatchSubdomains(true);
406 407
407 URLPatternSet patterns = installer_.extension()->web_extent(); 408 URLPatternSet patterns = install_checker_.extension()->web_extent();
408 for (URLPatternSet::const_iterator i = patterns.begin(); 409 for (URLPatternSet::const_iterator i = patterns.begin();
409 i != patterns.end(); ++i) { 410 i != patterns.end(); ++i) {
410 if (!pattern.MatchesHost(i->host())) { 411 if (!pattern.MatchesHost(i->host())) {
411 return CrxInstallerError( 412 return CrxInstallerError(
412 l10n_util::GetStringUTF16( 413 l10n_util::GetStringUTF16(
413 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST)); 414 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST));
414 } 415 }
415 } 416 }
416 } 417 }
417 } 418 }
(...skipping 23 matching lines...) Expand all
441 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); 442 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
442 443
443 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource", 444 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource",
444 install_source(), Manifest::NUM_LOCATIONS); 445 install_source(), Manifest::NUM_LOCATIONS);
445 446
446 447
447 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause", 448 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause",
448 install_cause(), 449 install_cause(),
449 extension_misc::NUM_INSTALL_CAUSES); 450 extension_misc::NUM_INSTALL_CAUSES);
450 451
451 installer_.set_extension(extension); 452 install_checker_.set_extension(extension);
452 temp_dir_ = temp_dir; 453 temp_dir_ = temp_dir;
453 if (!install_icon.empty()) 454 if (!install_icon.empty())
454 install_icon_.reset(new SkBitmap(install_icon)); 455 install_icon_.reset(new SkBitmap(install_icon));
455 456
456 if (original_manifest) 457 if (original_manifest)
457 original_manifest_.reset(new Manifest( 458 original_manifest_.reset(new Manifest(
458 Manifest::INVALID_LOCATION, 459 Manifest::INVALID_LOCATION,
459 scoped_ptr<base::DictionaryValue>(original_manifest->DeepCopy()))); 460 scoped_ptr<base::DictionaryValue>(original_manifest->DeepCopy())));
460 461
461 // We don't have to delete the unpack dir explicity since it is a child of 462 // We don't have to delete the unpack dir explicity since it is a child of
462 // the temp dir. 463 // the temp dir.
463 unpacked_extension_root_ = extension_dir; 464 unpacked_extension_root_ = extension_dir;
464 465
465 CrxInstallerError error = AllowInstall(extension); 466 CrxInstallerError error = AllowInstall(extension);
466 if (error.type() != CrxInstallerError::ERROR_NONE) { 467 if (error.type() != CrxInstallerError::ERROR_NONE) {
467 ReportFailureFromFileThread(error); 468 ReportFailureFromFileThread(error);
468 return; 469 return;
469 } 470 }
470 471
471 if (!BrowserThread::PostTask( 472 if (!BrowserThread::PostTask(BrowserThread::UI,
472 BrowserThread::UI, FROM_HERE, 473 FROM_HERE,
473 base::Bind(&CrxInstaller::CheckImportsAndRequirements, this))) 474 base::Bind(&CrxInstaller::CheckInstall, this)))
474 NOTREACHED(); 475 NOTREACHED();
475 } 476 }
476 477
477 void CrxInstaller::CheckImportsAndRequirements() { 478 void CrxInstaller::CheckInstall() {
478 DCHECK_CURRENTLY_ON(BrowserThread::UI); 479 DCHECK_CURRENTLY_ON(BrowserThread::UI);
479 ExtensionService* service = service_weak_.get(); 480 ExtensionService* service = service_weak_.get();
480 if (!service || service->browser_terminating()) 481 if (!service || service->browser_terminating())
481 return; 482 return;
482 483
483 if (SharedModuleInfo::ImportsModules(extension())) { 484 if (SharedModuleInfo::ImportsModules(extension())) {
484 const std::vector<SharedModuleInfo::ImportInfo>& imports = 485 const std::vector<SharedModuleInfo::ImportInfo>& imports =
485 SharedModuleInfo::GetImports(extension()); 486 SharedModuleInfo::GetImports(extension());
486 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; 487 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
487 for (i = imports.begin(); i != imports.end(); ++i) { 488 for (i = imports.begin(); i != imports.end(); ++i) {
(...skipping 10 matching lines...) Expand all
498 !SharedModuleInfo::IsExportAllowedByWhitelist(imported_module, 499 !SharedModuleInfo::IsExportAllowedByWhitelist(imported_module,
499 extension()->id())) { 500 extension()->id())) {
500 ReportFailureFromUIThread( 501 ReportFailureFromUIThread(
501 CrxInstallerError(l10n_util::GetStringFUTF16( 502 CrxInstallerError(l10n_util::GetStringFUTF16(
502 IDS_EXTENSION_INSTALL_DEPENDENCY_NOT_WHITELISTED, 503 IDS_EXTENSION_INSTALL_DEPENDENCY_NOT_WHITELISTED,
503 base::ASCIIToUTF16(i->extension_id)))); 504 base::ASCIIToUTF16(i->extension_id))));
504 return; 505 return;
505 } 506 }
506 } 507 }
507 } 508 }
508 installer_.CheckRequirements(base::Bind(&CrxInstaller::OnRequirementsChecked, 509
509 this)); 510 // Run the policy, requirements and blacklist checks in parallel.
511 install_checker_.Start(
512 ExtensionInstallChecker::CHECK_ALL,
513 false /* fail fast */,
514 base::Bind(&CrxInstaller::OnInstallChecksComplete, this));
510 } 515 }
511 516
512 void CrxInstaller::OnRequirementsChecked( 517 void CrxInstaller::OnInstallChecksComplete(int failed_checks) {
513 std::vector<std::string> requirement_errors) {
514 DCHECK_CURRENTLY_ON(BrowserThread::UI); 518 DCHECK_CURRENTLY_ON(BrowserThread::UI);
515 if (!service_weak_) 519 if (!service_weak_)
516 return; 520 return;
517 521
518 if (!requirement_errors.empty()) { 522 // Check for requirement errors.
523 if (!install_checker_.requirement_errors().empty()) {
519 if (error_on_unsupported_requirements_) { 524 if (error_on_unsupported_requirements_) {
520 ReportFailureFromUIThread(CrxInstallerError( 525 ReportFailureFromUIThread(CrxInstallerError(base::UTF8ToUTF16(
521 base::UTF8ToUTF16(JoinString(requirement_errors, ' ')))); 526 JoinString(install_checker_.requirement_errors(), ' '))));
522 return; 527 return;
523 } 528 }
524 install_flags_ |= kInstallFlagHasRequirementErrors; 529 install_flags_ |= kInstallFlagHasRequirementErrors;
525 } 530 }
526 531
527 ExtensionSystem::Get(profile())->blacklist()->IsBlacklisted( 532 // Check the blacklist state.
528 extension()->id(), 533 if (install_checker_.blacklist_state() == extensions::BLACKLISTED_MALWARE) {
529 base::Bind(&CrxInstaller::OnBlacklistChecked, this));
530 }
531
532 void CrxInstaller::OnBlacklistChecked(
533 extensions::BlacklistState blacklist_state) {
534 DCHECK_CURRENTLY_ON(BrowserThread::UI);
535 if (!service_weak_)
536 return;
537
538 if (blacklist_state == extensions::BLACKLISTED_MALWARE) {
539 install_flags_ |= kInstallFlagIsBlacklistedForMalware; 534 install_flags_ |= kInstallFlagIsBlacklistedForMalware;
540 } 535 }
541 536
542 if ((blacklist_state == extensions::BLACKLISTED_MALWARE || 537 if ((install_checker_.blacklist_state() == extensions::BLACKLISTED_MALWARE ||
543 blacklist_state == extensions::BLACKLISTED_UNKNOWN) && 538 install_checker_.blacklist_state() == extensions::BLACKLISTED_UNKNOWN) &&
544 !allow_silent_install_) { 539 !allow_silent_install_) {
545 // User tried to install a blacklisted extension. Show an error and 540 // User tried to install a blacklisted extension. Show an error and
546 // refuse to install it. 541 // refuse to install it.
547 ReportFailureFromUIThread(extensions::CrxInstallerError( 542 ReportFailureFromUIThread(extensions::CrxInstallerError(
548 l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED, 543 l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED,
549 base::UTF8ToUTF16(extension()->name())))); 544 base::UTF8ToUTF16(extension()->name()))));
550 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX", 545 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX",
551 extension()->location(), 546 extension()->location(),
552 Manifest::NUM_LOCATIONS); 547 Manifest::NUM_LOCATIONS);
553 return; 548 return;
554 } 549 }
555 550
556 // NOTE: extension may still be blacklisted, but we're forced to silently 551 // NOTE: extension may still be blacklisted, but we're forced to silently
557 // install it. In this case, ExtensionService::OnExtensionInstalled needs to 552 // install it. In this case, ExtensionService::OnExtensionInstalled needs to
558 // deal with it. 553 // deal with it.
554
555 // Check for policy errors.
556 if (!install_checker_.policy_error().empty()) {
557 // We don't want to show the error infobar for installs from the WebStore,
558 // because the WebStore already shows an error dialog itself.
559 // Note: |client_| can be NULL in unit_tests!
560 if (extension()->from_webstore() && client_)
561 client_->install_ui()->set_skip_post_install_ui(true);
562 ReportFailureFromUIThread(
563 CrxInstallerError(base::UTF8ToUTF16(install_checker_.policy_error())));
564 return;
565 }
566
559 ConfirmInstall(); 567 ConfirmInstall();
560 } 568 }
561 569
562 void CrxInstaller::ConfirmInstall() { 570 void CrxInstaller::ConfirmInstall() {
563 DCHECK_CURRENTLY_ON(BrowserThread::UI); 571 DCHECK_CURRENTLY_ON(BrowserThread::UI);
564 ExtensionService* service = service_weak_.get(); 572 ExtensionService* service = service_weak_.get();
565 if (!service || service->browser_terminating()) 573 if (!service || service->browser_terminating())
566 return; 574 return;
567 575
568 if (KioskModeInfo::IsKioskOnly(installer_.extension())) { 576 if (KioskModeInfo::IsKioskOnly(install_checker_.extension())) {
569 bool in_kiosk_mode = false; 577 bool in_kiosk_mode = false;
570 #if defined(OS_CHROMEOS) 578 #if defined(OS_CHROMEOS)
571 chromeos::UserManager* user_manager = chromeos::UserManager::Get(); 579 chromeos::UserManager* user_manager = chromeos::UserManager::Get();
572 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp(); 580 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp();
573 #endif 581 #endif
574 if (!in_kiosk_mode) { 582 if (!in_kiosk_mode) {
575 ReportFailureFromUIThread(CrxInstallerError( 583 ReportFailureFromUIThread(CrxInstallerError(
576 l10n_util::GetStringUTF16( 584 l10n_util::GetStringUTF16(
577 IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY))); 585 IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY)));
578 return; 586 return;
579 } 587 }
580 } 588 }
581 589
582 base::string16 error = installer_.CheckManagementPolicy();
583 if (!error.empty()) {
584 // We don't want to show the error infobar for installs from the WebStore,
585 // because the WebStore already shows an error dialog itself.
586 // Note: |client_| can be NULL in unit_tests!
587 if (extension()->from_webstore() && client_)
588 client_->install_ui()->set_skip_post_install_ui(true);
589 ReportFailureFromUIThread(CrxInstallerError(error));
590 return;
591 }
592
593 // Check whether this install is initiated from the settings page to 590 // Check whether this install is initiated from the settings page to
594 // update an existing extension or app. 591 // update an existing extension or app.
595 CheckUpdateFromSettingsPage(); 592 CheckUpdateFromSettingsPage();
596 593
597 GURL overlapping_url; 594 GURL overlapping_url;
598 const Extension* overlapping_extension = 595 const Extension* overlapping_extension =
599 service->extensions()->GetHostedAppByOverlappingWebExtent( 596 service->extensions()->GetHostedAppByOverlappingWebExtent(
600 extension()->web_extent()); 597 extension()->web_extent());
601 if (overlapping_extension && 598 if (overlapping_extension &&
602 overlapping_extension->id() != extension()->id()) { 599 overlapping_extension->id() != extension()->id()) {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 712
716 // This is lame, but we must reload the extension because absolute paths 713 // This is lame, but we must reload the extension because absolute paths
717 // inside the content scripts are established inside InitFromValue() and we 714 // inside the content scripts are established inside InitFromValue() and we
718 // just moved the extension. 715 // just moved the extension.
719 // TODO(aa): All paths to resources inside extensions should be created 716 // TODO(aa): All paths to resources inside extensions should be created
720 // lazily and based on the Extension's root path at that moment. 717 // lazily and based on the Extension's root path at that moment.
721 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing 718 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing
722 // with base::string16 719 // with base::string16
723 std::string extension_id = extension()->id(); 720 std::string extension_id = extension()->id();
724 std::string error; 721 std::string error;
725 installer_.set_extension( 722 install_checker_.set_extension(
726 file_util::LoadExtension( 723 file_util::LoadExtension(
727 version_dir, 724 version_dir,
728 install_source_, 725 install_source_,
729 extension()->creation_flags() | Extension::REQUIRE_KEY, 726 extension()->creation_flags() | Extension::REQUIRE_KEY,
730 &error).get()); 727 &error).get());
731 728
732 if (extension()) { 729 if (extension()) {
733 ReportSuccessFromFileThread(); 730 ReportSuccessFromFileThread();
734 } else { 731 } else {
735 LOG(ERROR) << error << " " << extension_id << " " << download_url_; 732 LOG(ERROR) << error << " " << extension_id << " " << download_url_;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 if (!prefs->DidExtensionEscalatePermissions(extension()->id())) 895 if (!prefs->DidExtensionEscalatePermissions(extension()->id()))
899 return; 896 return;
900 897
901 if (client_) { 898 if (client_) {
902 AddRef(); // Balanced in InstallUIProceed() and InstallUIAbort(). 899 AddRef(); // Balanced in InstallUIProceed() and InstallUIAbort().
903 client_->ConfirmReEnable(this, extension()); 900 client_->ConfirmReEnable(this, extension());
904 } 901 }
905 } 902 }
906 903
907 } // namespace extensions 904 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/crx_installer.h ('k') | chrome/browser/extensions/crx_installer_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698