OLD | NEW |
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 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 // manually if they want. | 349 // manually if they want. |
350 delete_source_ = false; | 350 delete_source_ = false; |
351 did_handle_successfully_ = false; | 351 did_handle_successfully_ = false; |
352 | 352 |
353 return CrxInstallError( | 353 return CrxInstallError( |
354 CrxInstallError::ERROR_OFF_STORE, | 354 CrxInstallError::ERROR_OFF_STORE, |
355 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE)); | 355 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE)); |
356 } | 356 } |
357 } | 357 } |
358 | 358 |
359 if (install_checker_.extension()->is_app()) { | 359 if (extension->is_app()) { |
360 // If the app was downloaded, apps_require_extension_mime_type_ | 360 // If the app was downloaded, apps_require_extension_mime_type_ |
361 // will be set. In this case, check that it was served with the | 361 // will be set. In this case, check that it was served with the |
362 // right mime type. Make an exception for file URLs, which come | 362 // right mime type. Make an exception for file URLs, which come |
363 // from the users computer and have no headers. | 363 // from the users computer and have no headers. |
364 if (!download_url_.SchemeIsFile() && | 364 if (!download_url_.SchemeIsFile() && |
365 apps_require_extension_mime_type_ && | 365 apps_require_extension_mime_type_ && |
366 original_mime_type_ != Extension::kMimeType) { | 366 original_mime_type_ != Extension::kMimeType) { |
367 return CrxInstallError(l10n_util::GetStringFUTF16( | 367 return CrxInstallError(l10n_util::GetStringFUTF16( |
368 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE, | 368 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE, |
369 base::ASCIIToUTF16(Extension::kMimeType))); | 369 base::ASCIIToUTF16(Extension::kMimeType))); |
(...skipping 12 matching lines...) Expand all Loading... |
382 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE))); | 382 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE))); |
383 } | 383 } |
384 | 384 |
385 // For self-hosted apps, verify that the entire extent is on the same | 385 // For self-hosted apps, verify that the entire extent is on the same |
386 // host (or a subdomain of the host) the download happened from. There's | 386 // host (or a subdomain of the host) the download happened from. There's |
387 // no way for us to verify that the app controls any other hosts. | 387 // no way for us to verify that the app controls any other hosts. |
388 URLPattern pattern(UserScript::ValidUserScriptSchemes()); | 388 URLPattern pattern(UserScript::ValidUserScriptSchemes()); |
389 pattern.SetHost(download_url_.host()); | 389 pattern.SetHost(download_url_.host()); |
390 pattern.SetMatchSubdomains(true); | 390 pattern.SetMatchSubdomains(true); |
391 | 391 |
392 URLPatternSet patterns = install_checker_.extension()->web_extent(); | 392 URLPatternSet patterns = extension->web_extent(); |
393 for (URLPatternSet::const_iterator i = patterns.begin(); | 393 for (URLPatternSet::const_iterator i = patterns.begin(); |
394 i != patterns.end(); ++i) { | 394 i != patterns.end(); ++i) { |
395 if (!pattern.MatchesHost(i->host())) { | 395 if (!pattern.MatchesHost(i->host())) { |
396 return CrxInstallError(l10n_util::GetStringUTF16( | 396 return CrxInstallError(l10n_util::GetStringUTF16( |
397 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST)); | 397 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST)); |
398 } | 398 } |
399 } | 399 } |
400 } | 400 } |
401 } | 401 } |
402 | 402 |
(...skipping 22 matching lines...) Expand all Loading... |
425 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); | 425 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); |
426 | 426 |
427 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource", | 427 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource", |
428 install_source(), Manifest::NUM_LOCATIONS); | 428 install_source(), Manifest::NUM_LOCATIONS); |
429 | 429 |
430 | 430 |
431 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause", | 431 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause", |
432 install_cause(), | 432 install_cause(), |
433 extension_misc::NUM_INSTALL_CAUSES); | 433 extension_misc::NUM_INSTALL_CAUSES); |
434 | 434 |
435 install_checker_.set_extension(extension); | 435 extension_ = extension; |
436 temp_dir_ = temp_dir; | 436 temp_dir_ = temp_dir; |
437 if (!install_icon.empty()) | 437 if (!install_icon.empty()) |
438 install_icon_.reset(new SkBitmap(install_icon)); | 438 install_icon_.reset(new SkBitmap(install_icon)); |
439 | 439 |
440 if (original_manifest) | 440 if (original_manifest) |
441 original_manifest_.reset(new Manifest( | 441 original_manifest_.reset(new Manifest( |
442 Manifest::INVALID_LOCATION, | 442 Manifest::INVALID_LOCATION, |
443 std::unique_ptr<base::DictionaryValue>(original_manifest->DeepCopy()))); | 443 std::unique_ptr<base::DictionaryValue>(original_manifest->DeepCopy()))); |
444 | 444 |
445 // We don't have to delete the unpack dir explicity since it is a child of | 445 // We don't have to delete the unpack dir explicity since it is a child of |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 } | 507 } |
508 } | 508 } |
509 } | 509 } |
510 | 510 |
511 // Run the policy, requirements and blacklist checks in parallel. Skip the | 511 // Run the policy, requirements and blacklist checks in parallel. Skip the |
512 // checks if the extension is a bookmark app. | 512 // checks if the extension is a bookmark app. |
513 if (extension()->from_bookmark()) { | 513 if (extension()->from_bookmark()) { |
514 CrxInstaller::OnInstallChecksComplete(0); | 514 CrxInstaller::OnInstallChecksComplete(0); |
515 } else { | 515 } else { |
516 install_checker_.Start( | 516 install_checker_.Start( |
| 517 extension_, |
517 ExtensionInstallChecker::CHECK_ALL, | 518 ExtensionInstallChecker::CHECK_ALL, |
518 false /* fail fast */, | 519 false /* fail fast */, |
519 base::Bind(&CrxInstaller::OnInstallChecksComplete, this)); | 520 base::Bind(&CrxInstaller::OnInstallChecksComplete, this)); |
520 } | 521 } |
521 } | 522 } |
522 | 523 |
523 void CrxInstaller::OnInstallChecksComplete(int failed_checks) { | 524 void CrxInstaller::OnInstallChecksComplete(int failed_checks) { |
524 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 525 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
525 if (!service_weak_) | 526 if (!service_weak_) |
526 return; | 527 return; |
527 | 528 |
528 // Check for requirement errors. | 529 // Check for requirement errors. |
529 if (!install_checker_.requirement_errors().empty()) { | 530 if (!install_checker_.requirement_error_message().empty()) { |
530 if (error_on_unsupported_requirements_) { | 531 if (error_on_unsupported_requirements_) { |
531 ReportFailureFromUIThread( | 532 ReportFailureFromUIThread( |
532 CrxInstallError(CrxInstallError::ERROR_DECLINED, | 533 CrxInstallError(CrxInstallError::ERROR_DECLINED, |
533 base::UTF8ToUTF16(base::JoinString( | 534 install_checker_.requirement_error_message())); |
534 install_checker_.requirement_errors(), " ")))); | |
535 return; | 535 return; |
536 } | 536 } |
537 install_flags_ |= kInstallFlagHasRequirementErrors; | 537 install_flags_ |= kInstallFlagHasRequirementErrors; |
538 } | 538 } |
539 | 539 |
540 // Check the blacklist state. | 540 // Check the blacklist state. |
541 if (install_checker_.blacklist_error() == PreloadCheck::BLACKLISTED_ID) { | 541 if (install_checker_.blacklist_error() == PreloadCheck::BLACKLISTED_ID) { |
542 install_flags_ |= kInstallFlagIsBlacklistedForMalware; | 542 install_flags_ |= kInstallFlagIsBlacklistedForMalware; |
543 } | 543 } |
544 | 544 |
545 if ((install_checker_.blacklist_error() == PreloadCheck::BLACKLISTED_ID || | 545 if (install_checker_.blacklist_error() != PreloadCheck::NONE && |
546 install_checker_.blacklist_error() == | |
547 PreloadCheck::BLACKLISTED_UNKNOWN) && | |
548 !allow_silent_install_) { | 546 !allow_silent_install_) { |
549 // User tried to install a blacklisted extension. Show an error and | 547 // User tried to install a blacklisted extension. Show an error and |
550 // refuse to install it. | 548 // refuse to install it. |
551 ReportFailureFromUIThread(CrxInstallError( | 549 ReportFailureFromUIThread(CrxInstallError( |
552 CrxInstallError::ERROR_DECLINED, | 550 CrxInstallError::ERROR_DECLINED, |
553 l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED, | 551 l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED, |
554 base::UTF8ToUTF16(extension()->name())))); | 552 base::UTF8ToUTF16(extension()->name())))); |
555 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX", | 553 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX", |
556 extension()->location(), | 554 extension()->location(), |
557 Manifest::NUM_LOCATIONS); | 555 Manifest::NUM_LOCATIONS); |
558 return; | 556 return; |
559 } | 557 } |
560 | 558 |
561 // NOTE: extension may still be blacklisted, but we're forced to silently | 559 // NOTE: extension may still be blacklisted, but we're forced to silently |
562 // install it. In this case, ExtensionService::OnExtensionInstalled needs to | 560 // install it. In this case, ExtensionService::OnExtensionInstalled needs to |
563 // deal with it. | 561 // deal with it. |
564 | 562 |
565 // Check for policy errors. | 563 // Check for policy errors. |
566 if (!install_checker_.policy_error().empty()) { | 564 if (!install_checker_.policy_error().empty()) { |
567 // We don't want to show the error infobar for installs from the WebStore, | 565 // We don't want to show the error infobar for installs from the WebStore, |
568 // because the WebStore already shows an error dialog itself. | 566 // because the WebStore already shows an error dialog itself. |
569 // Note: |client_| can be NULL in unit_tests! | 567 // Note: |client_| can be NULL in unit_tests! |
570 if (extension()->from_webstore() && client_) | 568 if (extension()->from_webstore() && client_) |
571 client_->install_ui()->SetSkipPostInstallUI(true); | 569 client_->install_ui()->SetSkipPostInstallUI(true); |
572 ReportFailureFromUIThread( | 570 ReportFailureFromUIThread( |
573 CrxInstallError(CrxInstallError::ERROR_DECLINED, | 571 CrxInstallError(CrxInstallError::ERROR_DECLINED, |
574 base::UTF8ToUTF16(install_checker_.policy_error()))); | 572 install_checker_.policy_error())); |
575 return; | 573 return; |
576 } | 574 } |
577 | 575 |
578 ConfirmInstall(); | 576 ConfirmInstall(); |
579 } | 577 } |
580 | 578 |
581 void CrxInstaller::ConfirmInstall() { | 579 void CrxInstaller::ConfirmInstall() { |
582 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 580 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
583 ExtensionService* service = service_weak_.get(); | 581 ExtensionService* service = service_weak_.get(); |
584 if (!service || service->browser_terminating()) | 582 if (!service || service->browser_terminating()) |
585 return; | 583 return; |
586 | 584 |
587 if (KioskModeInfo::IsKioskOnly(install_checker_.extension().get())) { | 585 if (KioskModeInfo::IsKioskOnly(extension())) { |
588 bool in_kiosk_mode = false; | 586 bool in_kiosk_mode = false; |
589 #if defined(OS_CHROMEOS) | 587 #if defined(OS_CHROMEOS) |
590 user_manager::UserManager* user_manager = user_manager::UserManager::Get(); | 588 user_manager::UserManager* user_manager = user_manager::UserManager::Get(); |
591 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp(); | 589 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp(); |
592 #endif | 590 #endif |
593 if (!in_kiosk_mode) { | 591 if (!in_kiosk_mode) { |
594 ReportFailureFromUIThread(CrxInstallError( | 592 ReportFailureFromUIThread(CrxInstallError( |
595 CrxInstallError::ERROR_DECLINED, | 593 CrxInstallError::ERROR_DECLINED, |
596 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY))); | 594 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY))); |
597 return; | 595 return; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 | 714 |
717 // This is lame, but we must reload the extension because absolute paths | 715 // This is lame, but we must reload the extension because absolute paths |
718 // inside the content scripts are established inside InitFromValue() and we | 716 // inside the content scripts are established inside InitFromValue() and we |
719 // just moved the extension. | 717 // just moved the extension. |
720 // TODO(aa): All paths to resources inside extensions should be created | 718 // TODO(aa): All paths to resources inside extensions should be created |
721 // lazily and based on the Extension's root path at that moment. | 719 // lazily and based on the Extension's root path at that moment. |
722 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing | 720 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing |
723 // with base::string16 | 721 // with base::string16 |
724 std::string extension_id = extension()->id(); | 722 std::string extension_id = extension()->id(); |
725 std::string error; | 723 std::string error; |
726 install_checker_.set_extension( | 724 extension_ = |
727 file_util::LoadExtension( | 725 file_util::LoadExtension( |
728 version_dir, | 726 version_dir, |
729 install_source_, | 727 install_source_, |
730 // Note: modified by UpdateCreationFlagsAndCompleteInstall. | 728 // Note: modified by UpdateCreationFlagsAndCompleteInstall. |
731 creation_flags_, | 729 creation_flags_, |
732 &error).get()); | 730 &error).get(); |
733 | 731 |
734 if (extension()) { | 732 if (extension()) { |
735 ReportSuccessFromFileThread(); | 733 ReportSuccessFromFileThread(); |
736 } else { | 734 } else { |
737 LOG(ERROR) << error << " " << extension_id << " " << download_url_; | 735 LOG(ERROR) << error << " " << extension_id << " " << download_url_; |
738 ReportFailureFromFileThread(CrxInstallError(base::UTF8ToUTF16(error))); | 736 ReportFailureFromFileThread(CrxInstallError(base::UTF8ToUTF16(error))); |
739 } | 737 } |
740 } | 738 } |
741 | 739 |
742 void CrxInstaller::ReportFailureFromFileThread(const CrxInstallError& error) { | 740 void CrxInstaller::ReportFailureFromFileThread(const CrxInstallError& error) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 ExtensionInstallPrompt::GetReEnablePromptTypeForExtension( | 908 ExtensionInstallPrompt::GetReEnablePromptTypeForExtension( |
911 service->profile(), extension()); | 909 service->profile(), extension()); |
912 client_->ShowDialog(base::Bind(&CrxInstaller::OnInstallPromptDone, this), | 910 client_->ShowDialog(base::Bind(&CrxInstaller::OnInstallPromptDone, this), |
913 extension(), nullptr, | 911 extension(), nullptr, |
914 base::MakeUnique<ExtensionInstallPrompt::Prompt>(type), | 912 base::MakeUnique<ExtensionInstallPrompt::Prompt>(type), |
915 ExtensionInstallPrompt::GetDefaultShowDialogCallback()); | 913 ExtensionInstallPrompt::GetDefaultShowDialogCallback()); |
916 } | 914 } |
917 } | 915 } |
918 | 916 |
919 } // namespace extensions | 917 } // namespace extensions |
OLD | NEW |