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 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 23 matching lines...) Expand all Loading... | |
34 #include "chrome/browser/extensions/webstore_installer.h" | 34 #include "chrome/browser/extensions/webstore_installer.h" |
35 #include "chrome/browser/profiles/profile.h" | 35 #include "chrome/browser/profiles/profile.h" |
36 #include "chrome/browser/shell_integration.h" | 36 #include "chrome/browser/shell_integration.h" |
37 #include "chrome/browser/web_applications/web_app.h" | 37 #include "chrome/browser/web_applications/web_app.h" |
38 #include "chrome/common/chrome_notification_types.h" | 38 #include "chrome/common/chrome_notification_types.h" |
39 #include "chrome/common/chrome_paths.h" | 39 #include "chrome/common/chrome_paths.h" |
40 #include "chrome/common/extensions/extension_constants.h" | 40 #include "chrome/common/extensions/extension_constants.h" |
41 #include "chrome/common/extensions/extension_file_util.h" | 41 #include "chrome/common/extensions/extension_file_util.h" |
42 #include "chrome/common/extensions/extension_icon_set.h" | 42 #include "chrome/common/extensions/extension_icon_set.h" |
43 #include "chrome/common/extensions/feature_switch.h" | 43 #include "chrome/common/extensions/feature_switch.h" |
44 #include "chrome/common/extensions/permissions/permission_set.h" | |
Joe Thomas
2013/02/27 20:55:39
This is not required.
| |
44 #include "content/public/browser/browser_thread.h" | 45 #include "content/public/browser/browser_thread.h" |
45 #include "content/public/browser/notification_service.h" | 46 #include "content/public/browser/notification_service.h" |
46 #include "content/public/browser/resource_dispatcher_host.h" | 47 #include "content/public/browser/resource_dispatcher_host.h" |
47 #include "content/public/browser/user_metrics.h" | 48 #include "content/public/browser/user_metrics.h" |
48 #include "grit/chromium_strings.h" | 49 #include "grit/chromium_strings.h" |
49 #include "grit/generated_resources.h" | 50 #include "grit/generated_resources.h" |
50 #include "grit/theme_resources.h" | 51 #include "grit/theme_resources.h" |
51 #include "third_party/skia/include/core/SkBitmap.h" | 52 #include "third_party/skia/include/core/SkBitmap.h" |
52 #include "ui/base/l10n/l10n_util.h" | 53 #include "ui/base/l10n/l10n_util.h" |
53 #include "ui/base/resource/resource_bundle.h" | 54 #include "ui/base/resource/resource_bundle.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 allow_silent_install_(false), | 102 allow_silent_install_(false), |
102 bypass_blacklist_for_test_(false), | 103 bypass_blacklist_for_test_(false), |
103 install_cause_(extension_misc::INSTALL_CAUSE_UNSET), | 104 install_cause_(extension_misc::INSTALL_CAUSE_UNSET), |
104 creation_flags_(Extension::NO_FLAGS), | 105 creation_flags_(Extension::NO_FLAGS), |
105 off_store_install_allow_reason_(OffStoreInstallDisallowed), | 106 off_store_install_allow_reason_(OffStoreInstallDisallowed), |
106 did_handle_successfully_(true), | 107 did_handle_successfully_(true), |
107 record_oauth2_grant_(false), | 108 record_oauth2_grant_(false), |
108 error_on_unsupported_requirements_(false), | 109 error_on_unsupported_requirements_(false), |
109 requirements_checker_(new extensions::RequirementsChecker()), | 110 requirements_checker_(new extensions::RequirementsChecker()), |
110 has_requirement_errors_(false), | 111 has_requirement_errors_(false), |
111 install_wait_for_idle_(true) { | 112 install_wait_for_idle_(true), |
113 update_from_settings_page_(false) { | |
112 installer_task_runner_ = frontend_weak->GetFileTaskRunner(); | 114 installer_task_runner_ = frontend_weak->GetFileTaskRunner(); |
113 if (!approval) | 115 if (!approval) |
114 return; | 116 return; |
115 | 117 |
116 CHECK(profile_->IsSameProfile(approval->profile)); | 118 CHECK(profile_->IsSameProfile(approval->profile)); |
117 if (client_) { | 119 if (client_) { |
118 client_->install_ui()->SetUseAppInstalledBubble( | 120 client_->install_ui()->SetUseAppInstalledBubble( |
119 approval->use_app_installed_bubble); | 121 approval->use_app_installed_bubble); |
120 client_->install_ui()->SetSkipPostInstallUI(approval->skip_post_install_ui); | 122 client_->install_ui()->SetSkipPostInstallUI(approval->skip_post_install_ui); |
121 } | 123 } |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
421 } | 423 } |
422 | 424 |
423 ConfirmInstall(); | 425 ConfirmInstall(); |
424 } | 426 } |
425 | 427 |
426 void CrxInstaller::ConfirmInstall() { | 428 void CrxInstaller::ConfirmInstall() { |
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
428 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) | 430 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
429 return; | 431 return; |
430 | 432 |
433 // Check whether this install is initiated from the settings page to | |
434 // update an existing extension or app. | |
435 CheckUpdateFromSettingsPage(); | |
436 | |
431 string16 error; | 437 string16 error; |
432 if (!ExtensionSystem::Get(profile_)->management_policy()-> | 438 if (!ExtensionSystem::Get(profile_)->management_policy()-> |
433 UserMayLoad(extension_, &error)) { | 439 UserMayLoad(extension_, &error)) { |
434 ReportFailureFromUIThread(CrxInstallerError(error)); | 440 ReportFailureFromUIThread(CrxInstallerError(error)); |
435 return; | 441 return; |
436 } | 442 } |
437 | 443 |
438 GURL overlapping_url; | 444 GURL overlapping_url; |
439 const Extension* overlapping_extension = | 445 const Extension* overlapping_extension = |
440 frontend_weak_->extensions()-> | 446 frontend_weak_->extensions()-> |
441 GetHostedAppByOverlappingWebExtent(extension_->web_extent()); | 447 GetHostedAppByOverlappingWebExtent(extension_->web_extent()); |
442 if (overlapping_extension && | 448 if (overlapping_extension && |
443 overlapping_extension->id() != extension_->id()) { | 449 overlapping_extension->id() != extension_->id()) { |
444 ReportFailureFromUIThread( | 450 ReportFailureFromUIThread( |
445 CrxInstallerError( | 451 CrxInstallerError( |
446 l10n_util::GetStringFUTF16( | 452 l10n_util::GetStringFUTF16( |
447 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT, | 453 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT, |
448 UTF8ToUTF16(overlapping_extension->name())))); | 454 UTF8ToUTF16(overlapping_extension->name())))); |
449 return; | 455 return; |
450 } | 456 } |
451 | 457 |
452 current_version_ = | 458 current_version_ = |
453 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); | 459 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); |
454 | 460 |
455 if (client_ && (!allow_silent_install_ || !approved_)) { | 461 if (client_ && |
462 (!allow_silent_install_ || !approved_) && | |
463 !update_from_settings_page_) { | |
456 AddRef(); // Balanced in Proceed() and Abort(). | 464 AddRef(); // Balanced in Proceed() and Abort(). |
457 client_->ConfirmInstall(this, extension_.get(), show_dialog_callback_); | 465 client_->ConfirmInstall(this, extension_.get(), show_dialog_callback_); |
458 } else { | 466 } else { |
459 if (!installer_task_runner_->PostTask( | 467 if (!installer_task_runner_->PostTask( |
460 FROM_HERE, | 468 FROM_HERE, |
461 base::Bind(&CrxInstaller::CompleteInstall, this))) | 469 base::Bind(&CrxInstaller::CompleteInstall, this))) |
462 NOTREACHED(); | 470 NOTREACHED(); |
463 } | 471 } |
464 return; | 472 return; |
465 } | 473 } |
466 | 474 |
467 void CrxInstaller::InstallUIProceed() { | 475 void CrxInstaller::InstallUIProceed() { |
468 if (!installer_task_runner_->PostTask( | 476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
469 FROM_HERE, | |
470 base::Bind(&CrxInstaller::CompleteInstall, this))) | |
471 NOTREACHED(); | |
472 | 477 |
473 Release(); // balanced in ConfirmInstall(). | 478 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
479 return; | |
480 | |
481 if (update_from_settings_page_) { | |
Matt Perry
2013/02/28 01:13:27
could you add a comment here that explains we're g
Joe Thomas
2013/02/28 02:01:16
Done.
| |
482 frontend_weak_->GrantPermissionsAndEnableExtension( | |
483 extension_.get(), client_->record_oauth2_grant()); | |
484 } else { | |
485 if (!installer_task_runner_->PostTask( | |
486 FROM_HERE, | |
487 base::Bind(&CrxInstaller::CompleteInstall, this))) | |
488 NOTREACHED(); | |
489 } | |
490 | |
491 Release(); // balanced in ConfirmInstall() or ConfirmReEnable(). | |
474 } | 492 } |
475 | 493 |
476 void CrxInstaller::InstallUIAbort(bool user_initiated) { | 494 void CrxInstaller::InstallUIAbort(bool user_initiated) { |
477 std::string histogram_name = user_initiated ? | 495 if (!update_from_settings_page_) { |
478 "Extensions.Permissions_InstallCancel" : | 496 std::string histogram_name = user_initiated ? |
479 "Extensions.Permissions_InstallAbort"; | 497 "Extensions.Permissions_InstallCancel" : |
480 ExtensionService::RecordPermissionMessagesHistogram( | 498 "Extensions.Permissions_InstallAbort"; |
481 extension_, histogram_name.c_str()); | 499 ExtensionService::RecordPermissionMessagesHistogram( |
500 extension_, histogram_name.c_str()); | |
482 | 501 |
483 // Kill the theme loading bubble. | 502 // Kill the theme loading bubble. |
484 content::NotificationService* service = | 503 content::NotificationService* service = |
485 content::NotificationService::current(); | 504 content::NotificationService::current(); |
486 service->Notify(chrome::NOTIFICATION_NO_THEME_DETECTED, | 505 service->Notify(chrome::NOTIFICATION_NO_THEME_DETECTED, |
487 content::Source<CrxInstaller>(this), | 506 content::Source<CrxInstaller>(this), |
488 content::NotificationService::NoDetails()); | 507 content::NotificationService::NoDetails()); |
489 | 508 |
490 NotifyCrxInstallComplete(false); | 509 NotifyCrxInstallComplete(false); |
510 } | |
491 | 511 |
492 Release(); // balanced in ConfirmInstall(). | 512 Release(); // balanced in ConfirmInstall() or ConfirmReEnable(). |
493 | 513 |
494 // We're done. Since we don't post any more tasks to ourself, our ref count | 514 // We're done. Since we don't post any more tasks to ourself, our ref count |
495 // should go to zero and we die. The destructor will clean up the temp dir. | 515 // should go to zero and we die. The destructor will clean up the temp dir. |
496 } | 516 } |
497 | 517 |
498 void CrxInstaller::CompleteInstall() { | 518 void CrxInstaller::CompleteInstall() { |
499 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); | 519 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); |
500 | 520 |
501 if (!current_version_.empty()) { | 521 if (!current_version_.empty()) { |
502 Version current_version(current_version_); | 522 Version current_version(current_version_); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
604 // Delete temporary files. | 624 // Delete temporary files. |
605 CleanupTempFiles(); | 625 CleanupTempFiles(); |
606 } | 626 } |
607 | 627 |
608 void CrxInstaller::ReportSuccessFromUIThread() { | 628 void CrxInstaller::ReportSuccessFromUIThread() { |
609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
610 | 630 |
611 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) | 631 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) |
612 return; | 632 return; |
613 | 633 |
614 // If there is a client, tell the client about installation. | 634 if (!update_from_settings_page_) { |
615 if (client_) { | 635 // If there is a client, tell the client about installation. |
616 client_->OnInstallSuccess(extension_.get(), install_icon_.get()); | 636 if (client_) |
617 } | 637 client_->OnInstallSuccess(extension_.get(), install_icon_.get()); |
618 | 638 |
619 if (client_ && !approved_) | 639 if (client_ && !approved_) |
620 record_oauth2_grant_ = client_->record_oauth2_grant(); | 640 record_oauth2_grant_ = client_->record_oauth2_grant(); |
Matt Perry
2013/02/28 01:13:27
indent
Joe Thomas
2013/02/28 02:01:16
Done.
| |
621 | 641 |
622 // We update the extension's granted permissions if the user already approved | 642 // We update the extension's granted permissions if the user already |
623 // the install (client_ is non NULL), or we are allowed to install this | 643 // approved the install (client_ is non NULL), or we are allowed to install |
624 // silently. | 644 // this silently. |
625 if (client_ || allow_silent_install_) { | 645 if (client_ || allow_silent_install_) { |
626 PermissionsUpdater perms_updater(profile()); | 646 PermissionsUpdater perms_updater(profile()); |
627 perms_updater.GrantActivePermissions(extension_, record_oauth2_grant_); | 647 perms_updater.GrantActivePermissions(extension_, record_oauth2_grant_); |
648 } | |
628 } | 649 } |
629 | 650 |
630 // Install the extension if it's not blacklisted, but notify either way. | 651 // Install the extension if it's not blacklisted, but notify either way. |
631 base::Closure on_success = | 652 base::Closure on_success = |
632 base::Bind(&ExtensionService::OnExtensionInstalled, | 653 base::Bind(&ExtensionService::OnExtensionInstalled, |
633 frontend_weak_, | 654 frontend_weak_, |
634 extension_, | 655 extension_, |
635 page_ordinal_, | 656 page_ordinal_, |
636 has_requirement_errors_, | 657 has_requirement_errors_, |
637 install_wait_for_idle_); | 658 install_wait_for_idle_); |
(...skipping 29 matching lines...) Expand all Loading... | |
667 // Some users (such as the download shelf) need to know when a | 688 // Some users (such as the download shelf) need to know when a |
668 // CRXInstaller is done. Listening for the EXTENSION_* events | 689 // CRXInstaller is done. Listening for the EXTENSION_* events |
669 // is problematic because they don't know anything about the | 690 // is problematic because they don't know anything about the |
670 // extension before it is unpacked, so they cannot filter based | 691 // extension before it is unpacked, so they cannot filter based |
671 // on the extension. | 692 // on the extension. |
672 content::NotificationService::current()->Notify( | 693 content::NotificationService::current()->Notify( |
673 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 694 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
674 content::Source<CrxInstaller>(this), | 695 content::Source<CrxInstaller>(this), |
675 content::Details<const Extension>(success ? extension_.get() : NULL)); | 696 content::Details<const Extension>(success ? extension_.get() : NULL)); |
676 | 697 |
677 // We're done. We don't post any more tasks to ourselves so we are deleted | 698 if (success) |
678 // soon. | 699 ConfirmReEnable(); |
679 extension_ = NULL; | 700 |
Matt Perry
2013/02/28 01:13:27
Don't delete this code. You should still NULL-out
Joe Thomas
2013/02/28 02:01:16
This code is not required. If we dont call client_
Matt Perry
2013/02/28 20:02:08
OK
| |
680 } | 701 } |
681 | 702 |
682 void CrxInstaller::CleanupTempFiles() { | 703 void CrxInstaller::CleanupTempFiles() { |
683 if (!installer_task_runner_->RunsTasksOnCurrentThread()) { | 704 if (!installer_task_runner_->RunsTasksOnCurrentThread()) { |
684 if (!installer_task_runner_->PostTask( | 705 if (!installer_task_runner_->PostTask( |
685 FROM_HERE, | 706 FROM_HERE, |
686 base::Bind(&CrxInstaller::CleanupTempFiles, this))) { | 707 base::Bind(&CrxInstaller::CleanupTempFiles, this))) { |
687 NOTREACHED(); | 708 NOTREACHED(); |
688 } | 709 } |
689 return; | 710 return; |
690 } | 711 } |
691 | 712 |
692 // Delete the temp directory and crx file as necessary. | 713 // Delete the temp directory and crx file as necessary. |
693 if (!temp_dir_.value().empty()) { | 714 if (!temp_dir_.value().empty()) { |
694 extension_file_util::DeleteFile(temp_dir_, true); | 715 extension_file_util::DeleteFile(temp_dir_, true); |
695 temp_dir_ = base::FilePath(); | 716 temp_dir_ = base::FilePath(); |
696 } | 717 } |
697 | 718 |
698 if (delete_source_ && !source_file_.value().empty()) { | 719 if (delete_source_ && !source_file_.value().empty()) { |
699 extension_file_util::DeleteFile(source_file_, false); | 720 extension_file_util::DeleteFile(source_file_, false); |
700 source_file_ = base::FilePath(); | 721 source_file_ = base::FilePath(); |
701 } | 722 } |
702 } | 723 } |
703 | 724 |
725 void CrxInstaller::CheckUpdateFromSettingsPage() { | |
726 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
727 | |
728 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) | |
729 return; | |
730 | |
731 if (off_store_install_allow_reason_ != OffStoreInstallAllowedFromSettingsPage) | |
732 return; | |
733 | |
734 const Extension* installed_extension = | |
735 frontend_weak_->GetInstalledExtension(extension_->id()); | |
736 if (installed_extension) { | |
737 // Previous version of the extension exists. | |
738 update_from_settings_page_ = true; | |
739 expected_id_ = installed_extension->id(); | |
740 install_source_ = installed_extension->location(); | |
741 install_cause_ = extension_misc::INSTALL_CAUSE_UPDATE; | |
742 } | |
743 } | |
744 | |
745 void CrxInstaller::ConfirmReEnable() { | |
746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
747 | |
748 if (!frontend_weak_.get() || frontend_weak_->browser_terminating()) | |
749 return; | |
750 | |
751 if (!update_from_settings_page_) | |
752 return; | |
753 | |
754 extensions::ExtensionPrefs* prefs = frontend_weak_->extension_prefs(); | |
755 if (!prefs->DidExtensionEscalatePermissions(extension_->id())) | |
756 return; | |
757 | |
758 if (client_) { | |
759 AddRef(); // Balanced in Proceed() and Abort(). | |
Matt Perry
2013/02/28 01:13:27
nit: balanced in InstallUIProceed* ...
Joe Thomas
2013/02/28 02:01:16
Done.
| |
760 client_->ConfirmReEnable(this, extension_.get()); | |
761 } | |
762 } | |
763 | |
704 } // namespace extensions | 764 } // namespace extensions |
OLD | NEW |