diff options
47 files changed, 1267 insertions, 1037 deletions
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc index 3431344..ddf9e2a 100644 --- a/chrome/browser/automation/testing_automation_provider.cc +++ b/chrome/browser/automation/testing_automation_provider.cc @@ -3975,8 +3975,8 @@ void TestingAutomationProvider::InstallExtension( // If the given path has a 'crx' extension, assume it is a packed extension // and install it. Otherwise load it as an unpacked extension. if (extension_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) { - ExtensionInstallUI* client = - (with_ui ? new ExtensionInstallUI(browser->profile()) : NULL); + ExtensionInstallPrompt* client = + (with_ui ? new ExtensionInstallPrompt(browser->profile()) : NULL); scoped_refptr<CrxInstaller> installer( CrxInstaller::Create(service, client)); if (!with_ui) diff --git a/chrome/browser/chromeos/extensions/file_manager_util.cc b/chrome/browser/chromeos/extensions/file_manager_util.cc index 70bb50f..6280db6 100644 --- a/chrome/browser/chromeos/extensions/file_manager_util.cc +++ b/chrome/browser/chromeos/extensions/file_manager_util.cc @@ -20,7 +20,7 @@ #include "chrome/browser/chromeos/gdata/gdata_util.h" #include "chrome/browser/chromeos/media/media_player.h" #include "chrome/browser/extensions/crx_installer.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/plugin_prefs.h" #include "chrome/browser/profiles/profile.h" @@ -689,8 +689,8 @@ void InstallCRX(Profile* profile, const FilePath& path) { if (!service) return; - scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service, - new ExtensionInstallUI(profile))); + scoped_refptr<CrxInstaller> installer( + CrxInstaller::Create(service, new ExtensionInstallPrompt(profile))); installer->set_is_gallery_install(false); installer->set_allow_silent_install(false); installer->InstallCrx(path); diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index d3db30b..a49d2b6 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc @@ -28,7 +28,7 @@ #include "chrome/browser/download/download_shelf.h" #include "chrome/browser/download/download_test_observer.h" #include "chrome/browser/download/download_util.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/history/history.h" #include "chrome/browser/net/url_request_mock_util.h" @@ -154,9 +154,9 @@ class DownloadsHistoryDataCollector { // Mock that simulates a permissions dialog where the user denies // permission to install. TODO(skerner): This could be shared with // extensions tests. Find a common place for this class. -class MockAbortExtensionInstallUI : public ExtensionInstallUI { +class MockAbortExtensionInstallPrompt : public ExtensionInstallPrompt { public: - MockAbortExtensionInstallUI() : ExtensionInstallUI(NULL) {} + MockAbortExtensionInstallPrompt() : ExtensionInstallPrompt(NULL) {} // Simulate a user abort on an extension installation. virtual void ConfirmInstall(Delegate* delegate, const Extension* extension) { @@ -170,10 +170,10 @@ class MockAbortExtensionInstallUI : public ExtensionInstallUI { // Mock that simulates a permissions dialog where the user allows // installation. -class MockAutoConfirmExtensionInstallUI : public ExtensionInstallUI { +class MockAutoConfirmExtensionInstallPrompt : public ExtensionInstallPrompt { public: - explicit MockAutoConfirmExtensionInstallUI(Profile* profile) - : ExtensionInstallUI(profile) {} + explicit MockAutoConfirmExtensionInstallPrompt(Profile* profile) + : ExtensionInstallPrompt(profile) {} // Proceed without confirmation prompt. virtual void ConfirmInstall(Delegate* delegate, const Extension* extension) { @@ -1685,8 +1685,8 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, CrxInstallDenysPermissions) { // Install a mock install UI that simulates a user denying permission to // finish the install. - download_crx_util::SetMockInstallUIForTesting( - new MockAbortExtensionInstallUI()); + download_crx_util::SetMockInstallPromptForTesting( + new MockAbortExtensionInstallPrompt()); scoped_ptr<DownloadTestObserver> observer( DangerousDownloadWaiter( @@ -1718,8 +1718,8 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, CrxInstallAcceptPermissions) { // Install a mock install UI that simulates a user allowing permission to // finish the install. - download_crx_util::SetMockInstallUIForTesting( - new MockAutoConfirmExtensionInstallUI(browser()->profile())); + download_crx_util::SetMockInstallPromptForTesting( + new MockAutoConfirmExtensionInstallPrompt(browser()->profile())); scoped_ptr<DownloadTestObserver> observer( DangerousDownloadWaiter( @@ -1749,8 +1749,8 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, CrxInvalid) { // Install a mock install UI that simulates a user allowing permission to // finish the install, and dismisses any error message. We check that the // install failed below. - download_crx_util::SetMockInstallUIForTesting( - new MockAutoConfirmExtensionInstallUI(browser()->profile())); + download_crx_util::SetMockInstallPromptForTesting( + new MockAutoConfirmExtensionInstallPrompt(browser()->profile())); scoped_ptr<DownloadTestObserver> observer( DangerousDownloadWaiter( @@ -1777,8 +1777,8 @@ IN_PROC_BROWSER_TEST_F(DownloadTest, CrxLargeTheme) { // Install a mock install UI that simulates a user allowing permission to // finish the install. - download_crx_util::SetMockInstallUIForTesting( - new MockAutoConfirmExtensionInstallUI(browser()->profile())); + download_crx_util::SetMockInstallPromptForTesting( + new MockAutoConfirmExtensionInstallPrompt(browser()->profile())); scoped_ptr<DownloadTestObserver> observer( DangerousDownloadWaiter( diff --git a/chrome/browser/download/download_crx_util.cc b/chrome/browser/download/download_crx_util.cc index b019f82..08f8d2e 100644 --- a/chrome/browser/download/download_crx_util.cc +++ b/chrome/browser/download/download_crx_util.cc @@ -6,7 +6,7 @@ #include "chrome/browser/download/download_util.h" #include "chrome/browser/extensions/crx_installer.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/webstore_installer.h" #include "chrome/browser/profiles/profile.h" @@ -22,22 +22,22 @@ namespace download_crx_util { namespace { -// Hold a mock ExtensionInstallUI object that will be used when the +// Hold a mock ExtensionInstallPrompt object that will be used when the // download system opens a CRX. -ExtensionInstallUI* mock_install_ui_for_testing = NULL; +ExtensionInstallPrompt* mock_install_prompt_for_testing = NULL; // Called to get an extension install UI object. In tests, will return // a mock if the test calls download_util::SetMockInstallUIForTesting() // to set one. -ExtensionInstallUI* CreateExtensionInstallUI(Profile* profile) { +ExtensionInstallPrompt* CreateExtensionInstallPrompt(Profile* profile) { // Use a mock if one is present. Otherwise, create a real extensions // install UI. - ExtensionInstallUI* result = NULL; - if (mock_install_ui_for_testing) { - result = mock_install_ui_for_testing; - mock_install_ui_for_testing = NULL; + ExtensionInstallPrompt* result = NULL; + if (mock_install_prompt_for_testing) { + result = mock_install_prompt_for_testing; + mock_install_prompt_for_testing = NULL; } else { - result = new ExtensionInstallUI(profile); + result = new ExtensionInstallPrompt(profile); } return result; @@ -45,10 +45,10 @@ ExtensionInstallUI* CreateExtensionInstallUI(Profile* profile) { } // namespace -// Tests can call this method to inject a mock ExtensionInstallUI +// Tests can call this method to inject a mock ExtensionInstallPrompt // to be used to confirm permissions on a downloaded CRX. -void SetMockInstallUIForTesting(ExtensionInstallUI* mock_ui) { - mock_install_ui_for_testing = mock_ui; +void SetMockInstallPromptForTesting(ExtensionInstallPrompt* mock_prompt) { + mock_install_prompt_for_testing = mock_prompt; } scoped_refptr<CrxInstaller> OpenChromeExtension( @@ -62,7 +62,7 @@ scoped_refptr<CrxInstaller> OpenChromeExtension( scoped_refptr<CrxInstaller> installer( CrxInstaller::Create( service, - CreateExtensionInstallUI(profile), + CreateExtensionInstallPrompt(profile), WebstoreInstaller::GetAssociatedApproval(download_item))); installer->set_delete_source(true); diff --git a/chrome/browser/download/download_crx_util.h b/chrome/browser/download/download_crx_util.h index 8f1f347..7115f22 100644 --- a/chrome/browser/download/download_crx_util.h +++ b/chrome/browser/download/download_crx_util.h @@ -13,7 +13,7 @@ #include "base/memory/ref_counted.h" class CrxInstaller; -class ExtensionInstallUI; +class ExtensionInstallPrompt; class Profile; namespace content { @@ -22,12 +22,12 @@ class DownloadItem; namespace download_crx_util { -// Allow tests to install a mock extension install UI object, to fake +// Allow tests to install a mock ExtensionInstallPrompt object, to fake // user clicks on the permissions dialog. Each installed mock object // is only used once. If you want to return a mock for two different // installs, you need to call this function once before the first // install, and again after the first install and before the second. -void SetMockInstallUIForTesting(ExtensionInstallUI* mock_ui); +void SetMockInstallPromptForTesting(ExtensionInstallPrompt* mock_prompt); // Start installing a downloaded item item as a CRX (extension, theme, app, // ...). The installer does work on the file thread, so the installation diff --git a/chrome/browser/extensions/api/permissions/permissions_api.cc b/chrome/browser/extensions/api/permissions/permissions_api.cc index 2c2f391..0af5db5 100644 --- a/chrome/browser/extensions/api/permissions/permissions_api.cc +++ b/chrome/browser/extensions/api/permissions/permissions_api.cc @@ -203,7 +203,7 @@ bool RequestPermissionsFunction::RunImpl() { InstallUIAbort(true); } else { CHECK_EQ(DO_NOT_SKIP, auto_confirm_for_tests); - install_ui_.reset(new ExtensionInstallUI(profile())); + install_ui_.reset(new ExtensionInstallPrompt(profile())); install_ui_->ConfirmPermissions( this, GetExtension(), requested_permissions_.get()); } diff --git a/chrome/browser/extensions/api/permissions/permissions_api.h b/chrome/browser/extensions/api/permissions/permissions_api.h index c954cc7..662b8c2 100644 --- a/chrome/browser/extensions/api/permissions/permissions_api.h +++ b/chrome/browser/extensions/api/permissions/permissions_api.h @@ -10,7 +10,7 @@ #include "base/compiler_specific.h" #include "chrome/browser/extensions/extension_function.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/common/extensions/extension_permission_set.h" class ExtensionPermissionSet; @@ -54,7 +54,7 @@ class RemovePermissionsFunction : public SyncExtensionFunction { // chrome.permissions.request class RequestPermissionsFunction : public AsyncExtensionFunction, - public ExtensionInstallUI::Delegate { + public ExtensionInstallPrompt::Delegate { public: DECLARE_EXTENSION_FUNCTION_NAME("permissions.request") @@ -64,7 +64,7 @@ class RequestPermissionsFunction : public AsyncExtensionFunction, static void SetAutoConfirmForTests(bool should_proceed); static void SetIgnoreUserGestureForTests(bool ignore); - // ExtensionInstallUI::Delegate: + // ExtensionInstallPrompt::Delegate: virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -75,7 +75,7 @@ class RequestPermissionsFunction : public AsyncExtensionFunction, virtual bool RunImpl() OVERRIDE; private: - scoped_ptr<ExtensionInstallUI> install_ui_; + scoped_ptr<ExtensionInstallPrompt> install_ui_; scoped_refptr<ExtensionPermissionSet> requested_permissions_; }; diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc index df32a2f..00f7e85 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc @@ -358,7 +358,7 @@ void BeginInstallWithManifestFunction::OnWebstoreParseSuccess( parsed_manifest_.reset(parsed_manifest); std::string error; - dummy_extension_ = ExtensionInstallUI::GetLocalizedExtensionForDisplay( + dummy_extension_ = ExtensionInstallPrompt::GetLocalizedExtensionForDisplay( parsed_manifest_.get(), id, localized_name_, "", &error); if (!dummy_extension_) { @@ -367,8 +367,8 @@ void BeginInstallWithManifestFunction::OnWebstoreParseSuccess( return; } - install_ui_.reset(new ExtensionInstallUI(profile())); - install_ui_->ConfirmWebstoreInstall(this, dummy_extension_, &icon_); + install_prompt_.reset(new ExtensionInstallPrompt(profile())); + install_prompt_->ConfirmWebstoreInstall(this, dummy_extension_, &icon_); // Control flow finishes up in InstallUIProceed or InstallUIAbort. } diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h index cb890ad..f65b5d1 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h @@ -10,7 +10,7 @@ #include "chrome/browser/extensions/bundle_installer.h" #include "chrome/browser/extensions/extension_function.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/webstore_install_helper.h" #include "chrome/browser/extensions/webstore_installer.h" #include "chrome/common/net/gaia/google_service_auth_error.h" @@ -75,7 +75,7 @@ class InstallBundleFunction : public AsyncExtensionFunction, class BeginInstallWithManifestFunction : public AsyncExtensionFunction, - public ExtensionInstallUI::Delegate, + public ExtensionInstallPrompt::Delegate, public WebstoreInstallHelper::Delegate { public: DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.beginInstallWithManifest3"); @@ -120,7 +120,7 @@ class BeginInstallWithManifestFunction InstallHelperResultCode result_code, const std::string& error_message) OVERRIDE; - // ExtensionInstallUI::Delegate: + // ExtensionInstallPrompt::Delegate: virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -146,11 +146,11 @@ class BeginInstallWithManifestFunction SkBitmap icon_; // A dummy Extension object we create for the purposes of using - // ExtensionInstallUI to prompt for confirmation of the install. + // ExtensionInstallPrompt to prompt for confirmation of the install. scoped_refptr<extensions::Extension> dummy_extension_; // The class that displays the install prompt. - scoped_ptr<ExtensionInstallUI> install_ui_; + scoped_ptr<ExtensionInstallPrompt> install_prompt_; }; class CompleteInstallFunction : public SyncExtensionFunction { diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc index 98df25a..9fe1a4d 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc @@ -11,6 +11,7 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/extension_install_dialog.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h" diff --git a/chrome/browser/extensions/bundle_installer.cc b/chrome/browser/extensions/bundle_installer.cc index 6552cdb..5cfa4f0 100644 --- a/chrome/browser/extensions/bundle_installer.cc +++ b/chrome/browser/extensions/bundle_installer.cc @@ -267,7 +267,7 @@ void BundleInstaller::ShowPrompt() { } else if (g_auto_approve_for_test == ABORT) { InstallUIAbort(true); } else { - install_ui_.reset(new ExtensionInstallUI(profile_)); + install_ui_.reset(new ExtensionInstallPrompt(profile_)); install_ui_->ConfirmBundleInstall(this, permissions); } } diff --git a/chrome/browser/extensions/bundle_installer.h b/chrome/browser/extensions/bundle_installer.h index 4732042..168581e 100644 --- a/chrome/browser/extensions/bundle_installer.h +++ b/chrome/browser/extensions/bundle_installer.h @@ -12,7 +12,7 @@ #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "base/string16.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/webstore_installer.h" #include "chrome/browser/extensions/webstore_install_helper.h" #include "chrome/browser/ui/browser_list.h" @@ -38,7 +38,7 @@ namespace extensions { // 2) CompleteInstall: install the CRXs and show confirmation bubble // class BundleInstaller : public WebstoreInstallHelper::Delegate, - public ExtensionInstallUI::Delegate, + public ExtensionInstallPrompt::Delegate, public WebstoreInstaller::Delegate, public BrowserList::Observer, public base::RefCountedThreadSafe<BundleInstaller> { @@ -154,7 +154,7 @@ class BundleInstaller : public WebstoreInstallHelper::Delegate, InstallHelperResultCode result_code, const std::string& error_message) OVERRIDE; - // ExtensionInstallUI::Delegate implementation: + // ExtensionInstallPrompt::Delegate implementation: virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -187,7 +187,7 @@ class BundleInstaller : public WebstoreInstallHelper::Delegate, Profile* profile_; // The UI that shows the confirmation prompt. - scoped_ptr<ExtensionInstallUI> install_ui_; + scoped_ptr<ExtensionInstallPrompt> install_ui_; Delegate* delegate_; diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index 4b9602f..a7137a9 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -25,6 +25,7 @@ #include "chrome/browser/extensions/convert_web_app.h" #include "chrome/browser/extensions/default_apps_trial.h" #include "chrome/browser/extensions/extension_error_reporter.h" +#include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/permissions_updater.h" @@ -69,20 +70,20 @@ enum OffStoreInstallDecision { // static scoped_refptr<CrxInstaller> CrxInstaller::Create( ExtensionService* frontend, - ExtensionInstallUI* client) { + ExtensionInstallPrompt* client) { return new CrxInstaller(frontend->AsWeakPtr(), client, NULL); } // static scoped_refptr<CrxInstaller> CrxInstaller::Create( ExtensionService* frontend, - ExtensionInstallUI* client, + ExtensionInstallPrompt* client, const WebstoreInstaller::Approval* approval) { return new CrxInstaller(frontend->AsWeakPtr(), client, approval); } CrxInstaller::CrxInstaller(base::WeakPtr<ExtensionService> frontend_weak, - ExtensionInstallUI* client, + ExtensionInstallPrompt* client, const WebstoreInstaller::Approval* approval) : install_directory_(frontend_weak->install_directory()), install_source_(Extension::INTERNAL), @@ -102,8 +103,9 @@ CrxInstaller::CrxInstaller(base::WeakPtr<ExtensionService> frontend_weak, return; CHECK(profile_->IsSameProfile(approval->profile)); - client_->set_use_app_installed_bubble(approval->use_app_installed_bubble); - client_->set_skip_post_install_ui(approval->skip_post_install_ui); + client_->install_ui()->SetUseAppInstalledBubble( + approval->use_app_installed_bubble); + client_->install_ui()->SetSkipPostInstallUI(approval->skip_post_install_ui); if (approval->skip_install_dialog) { // Mark the extension as approved, but save the expected manifest and ID @@ -566,8 +568,9 @@ void CrxInstaller::ReportSuccessFromUIThread() { return; // If there is a client, tell the client about installation. - if (client_) + if (client_) { client_->OnInstallSuccess(extension_.get(), install_icon_.get()); + } // We update the extension's granted permissions if the user already approved // the install (client_ is non NULL), or we are allowed to install this diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h index 5a9d51b..9d9ad3b 100644 --- a/chrome/browser/extensions/crx_installer.h +++ b/chrome/browser/extensions/crx_installer.h @@ -13,7 +13,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/version.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" #include "chrome/browser/extensions/webstore_installer.h" #include "chrome/common/extensions/extension.h" @@ -52,20 +52,20 @@ class ExtensionUpdaterTest; // installer->InstallCrx(...); class CrxInstaller : public SandboxedExtensionUnpackerClient, - public ExtensionInstallUI::Delegate { + public ExtensionInstallPrompt::Delegate { public: // Extensions will be installed into frontend->install_directory(), // then registered with |frontend|. Any install UI will be displayed // using |client|. Pass NULL for |client| for silent install static scoped_refptr<CrxInstaller> Create( ExtensionService* frontend, - ExtensionInstallUI* client); + ExtensionInstallPrompt* client); // Same as the previous method, except use the |approval| to bypass the // prompt. Note that the caller retains ownership of |approval|. static scoped_refptr<CrxInstaller> Create( ExtensionService* frontend, - ExtensionInstallUI* client, + ExtensionInstallPrompt* client, const WebstoreInstaller::Approval* approval); // Install the crx in |source_file|. @@ -78,7 +78,7 @@ class CrxInstaller // Convert the specified web app into an extension and install it. void InstallWebApp(const WebApplicationInfo& web_app); - // Overridden from ExtensionInstallUI::Delegate: + // Overridden from ExtensionInstallPrompt::Delegate: virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -159,7 +159,7 @@ class CrxInstaller friend class extensions::ExtensionUpdaterTest; CrxInstaller(base::WeakPtr<ExtensionService> frontend_weak, - ExtensionInstallUI* client, + ExtensionInstallPrompt* client, const WebstoreInstaller::Approval* approval); virtual ~CrxInstaller(); @@ -184,8 +184,8 @@ class CrxInstaller // whitelisted. bool CanSkipConfirmation(); - // Runs on the UI thread. Confirms with the user (via ExtensionInstallUI) that - // it is OK to install this extension. + // Runs on the UI thread. Confirms with the user (via ExtensionInstallPrompt) + // that it is OK to install this extension. void ConfirmInstall(); // Runs on File thread. Install the unpacked extension into the profile and @@ -282,7 +282,7 @@ class CrxInstaller // which case the install is silent. // NOTE: we may be deleted on the file thread. To ensure the UI is deleted on // the main thread we don't use a scoped_ptr here. - ExtensionInstallUI* client_; + ExtensionInstallPrompt* client_; // The root of the unpacked extension directory. This is a subdirectory of // temp_dir_, so we don't have to delete it explicitly. diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc index 01f16d2..8e86a1c 100644 --- a/chrome/browser/extensions/crx_installer_browsertest.cc +++ b/chrome/browser/extensions/crx_installer_browsertest.cc @@ -8,7 +8,7 @@ #include "chrome/browser/download/download_test_observer.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_browsertest.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -25,10 +25,10 @@ namespace { // Observer waits for exactly one download to finish. -class MockInstallUI : public ExtensionInstallUI { +class MockInstallPrompt : public ExtensionInstallPrompt { public: - explicit MockInstallUI(Profile* profile) : - ExtensionInstallUI(profile), + explicit MockInstallPrompt(Profile* profile) : + ExtensionInstallPrompt(profile), did_succeed_(false), confirmation_requested_(false) {} @@ -68,7 +68,8 @@ class ExtensionCrxInstallerTest : public ExtensionBrowserTest { bool DidWhitelistInstallPrompt(const std::string& ext_relpath, const std::string& id) { ExtensionService* service = browser()->profile()->GetExtensionService(); - MockInstallUI* mock_install_ui = new MockInstallUI(browser()->profile()); + MockInstallPrompt* mock_install_prompt = + new MockInstallPrompt(browser()->profile()); FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath); std::string error; @@ -85,15 +86,15 @@ class ExtensionCrxInstallerTest : public ExtensionBrowserTest { scoped_refptr<CrxInstaller> installer( CrxInstaller::Create(service, - mock_install_ui, /* ownership transferred */ - approval.get() /* keep ownership */)); + mock_install_prompt, /* ownership transferred */ + approval.get() /* keep ownership */)); installer->set_allow_silent_install(true); installer->set_is_gallery_install(true); installer->InstallCrx(PackExtension(ext_path)); ui_test_utils::RunMessageLoop(); - EXPECT_TRUE(mock_install_ui->did_succeed()); - return mock_install_ui->confirmation_requested(); + EXPECT_TRUE(mock_install_prompt->did_succeed()); + return mock_install_prompt->confirmation_requested(); } }; @@ -159,8 +160,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, std::string crx_path_string(crx_path.value().begin(), crx_path.value().end()); GURL url = GURL(std::string("file:///").append(crx_path_string)); - MockInstallUI* mock_ui = new MockInstallUI(browser()->profile()); - download_crx_util::SetMockInstallUIForTesting(mock_ui); + MockInstallPrompt* mock_prompt = new MockInstallPrompt(browser()->profile()); + download_crx_util::SetMockInstallPromptForTesting(mock_prompt); LOG(ERROR) << "PackAndInstallExtension: Getting download manager"; content::DownloadManager* download_manager = @@ -177,7 +178,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, EXPECT_TRUE(WaitForExtensionInstall()); LOG(ERROR) << "PackAndInstallExtension: Extension install"; - EXPECT_TRUE(mock_ui->confirmation_requested()); + EXPECT_TRUE(mock_prompt->confirmation_requested()); LOG(ERROR) << "PackAndInstallExtension: Extension install confirmed"; } @@ -192,23 +193,25 @@ IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, MAYBE_AllowOffStore) { const bool kTestData[] = {false, true}; for (size_t i = 0; i < arraysize(kTestData); ++i) { - MockInstallUI* mock_ui = new MockInstallUI(browser()->profile()); + MockInstallPrompt* mock_prompt = + new MockInstallPrompt(browser()->profile()); scoped_refptr<CrxInstaller> crx_installer( - CrxInstaller::Create(service, mock_ui)); + CrxInstaller::Create(service, mock_prompt)); crx_installer->set_install_cause( extension_misc::INSTALL_CAUSE_USER_DOWNLOAD); crx_installer->set_allow_off_store_install(kTestData[i]); crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx")); EXPECT_EQ(kTestData[i], WaitForExtensionInstall()) << kTestData[i]; - EXPECT_EQ(kTestData[i], mock_ui->did_succeed()); - EXPECT_EQ(kTestData[i], mock_ui->confirmation_requested()) << kTestData[i]; + EXPECT_EQ(kTestData[i], mock_prompt->did_succeed()); + EXPECT_EQ(kTestData[i], mock_prompt->confirmation_requested()) << + kTestData[i]; if (kTestData[i]) { - EXPECT_EQ(string16(), mock_ui->error()) << kTestData[i]; + EXPECT_EQ(string16(), mock_prompt->error()) << kTestData[i]; } else { EXPECT_EQ(l10n_util::GetStringUTF16( IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE), - mock_ui->error()) << kTestData[i]; + mock_prompt->error()) << kTestData[i]; } } } diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index 5faf4b3..385f5b2 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc @@ -18,7 +18,7 @@ #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_creator.h" #include "chrome/browser/extensions/extension_error_reporter.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/profiles/profile.h" @@ -228,9 +228,9 @@ FilePath ExtensionBrowserTest::PackExtensionWithOptions( } // This class is used to simulate an installation abort by the user. -class MockAbortExtensionInstallUI : public ExtensionInstallUI { +class MockAbortExtensionInstallPrompt : public ExtensionInstallPrompt { public: - MockAbortExtensionInstallUI() : ExtensionInstallUI(NULL) {} + MockAbortExtensionInstallPrompt() : ExtensionInstallPrompt(NULL) {} // Simulate a user abort on an extension installation. virtual void ConfirmInstall(Delegate* delegate, const Extension* extension) { @@ -243,10 +243,10 @@ class MockAbortExtensionInstallUI : public ExtensionInstallUI { virtual void OnInstallFailure(const string16& error) {} }; -class MockAutoConfirmExtensionInstallUI : public ExtensionInstallUI { +class MockAutoConfirmExtensionInstallPrompt : public ExtensionInstallPrompt { public: - explicit MockAutoConfirmExtensionInstallUI(Profile* profile) : - ExtensionInstallUI(profile) {} + explicit MockAutoConfirmExtensionInstallPrompt(Profile* profile) : + ExtensionInstallPrompt(profile) {} // Proceed without confirmation prompt. virtual void ConfirmInstall(Delegate* delegate, const Extension* extension) { @@ -283,13 +283,13 @@ const Extension* ExtensionBrowserTest::InstallOrUpdateExtension( size_t num_before = service->extensions()->size(); { - ExtensionInstallUI* install_ui = NULL; + ExtensionInstallPrompt* install_ui = NULL; if (ui_type == INSTALL_UI_TYPE_CANCEL) - install_ui = new MockAbortExtensionInstallUI(); + install_ui = new MockAbortExtensionInstallPrompt(); else if (ui_type == INSTALL_UI_TYPE_NORMAL) - install_ui = new ExtensionInstallUI(profile); + install_ui = new ExtensionInstallPrompt(profile); else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) - install_ui = new MockAutoConfirmExtensionInstallUI(profile); + install_ui = new MockAutoConfirmExtensionInstallPrompt(profile); // TODO(tessamac): Update callers to always pass an unpacked extension // and then always pack the extension here. diff --git a/chrome/browser/extensions/extension_disabled_ui.cc b/chrome/browser/extensions/extension_disabled_ui.cc index e1af856..7a023a4 100644 --- a/chrome/browser/extensions/extension_disabled_ui.cc +++ b/chrome/browser/extensions/extension_disabled_ui.cc @@ -14,7 +14,7 @@ #include "base/metrics/histogram.h" #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/profiles/profile.h" @@ -68,7 +68,7 @@ void ReleaseMenuCommandID(int id) { // ExtensionDisabledDialogDelegate -------------------------------------------- class ExtensionDisabledDialogDelegate - : public ExtensionInstallUI::Delegate, + : public ExtensionInstallPrompt::Delegate, public base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate> { public: ExtensionDisabledDialogDelegate(Profile* profile, @@ -80,12 +80,12 @@ class ExtensionDisabledDialogDelegate virtual ~ExtensionDisabledDialogDelegate(); - // ExtensionInstallUI::Delegate: + // ExtensionInstallPrompt::Delegate: virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; // The UI for showing the install dialog when enabling. - scoped_ptr<ExtensionInstallUI> install_ui_; + scoped_ptr<ExtensionInstallPrompt> install_ui_; ExtensionService* service_; const Extension* extension_; @@ -98,7 +98,7 @@ ExtensionDisabledDialogDelegate::ExtensionDisabledDialogDelegate( : service_(service), extension_(extension) { AddRef(); // Balanced in Proceed or Abort. - install_ui_.reset(new ExtensionInstallUI(profile)); + install_ui_.reset(new ExtensionInstallPrompt(profile)); install_ui_->ConfirmReEnable(this, extension_); } diff --git a/chrome/browser/extensions/extension_install_dialog.cc b/chrome/browser/extensions/extension_install_dialog.cc index b404e53..3f40064 100644 --- a/chrome/browser/extensions/extension_install_dialog.cc +++ b/chrome/browser/extensions/extension_install_dialog.cc @@ -24,7 +24,7 @@ enum AutoConfirmForTest { ABORT }; -void AutoConfirmTask(ExtensionInstallUI::Delegate* delegate, bool proceed) { +void AutoConfirmTask(ExtensionInstallPrompt::Delegate* delegate, bool proceed) { if (proceed) delegate->InstallUIProceed(); else @@ -32,7 +32,7 @@ void AutoConfirmTask(ExtensionInstallUI::Delegate* delegate, bool proceed) { } void DoAutoConfirm(AutoConfirmForTest setting, - ExtensionInstallUI::Delegate* delegate) { + ExtensionInstallPrompt::Delegate* delegate) { bool proceed = (setting == PROCEED); // We use PostTask instead of calling the delegate directly here, because in // the real implementations it's highly likely the message loop will be @@ -60,8 +60,8 @@ AutoConfirmForTest CheckAutoConfirmCommandLineSwitch() { } // namespace void ShowExtensionInstallDialog(Profile* profile, - ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt) { + ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt) { AutoConfirmForTest auto_confirm = CheckAutoConfirmCommandLineSwitch(); if (auto_confirm != DO_NOT_SKIP) { DoAutoConfirm(auto_confirm, delegate); diff --git a/chrome/browser/extensions/extension_install_dialog.h b/chrome/browser/extensions/extension_install_dialog.h index 7f3439e..77d84ed 100644 --- a/chrome/browser/extensions/extension_install_dialog.h +++ b/chrome/browser/extensions/extension_install_dialog.h @@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/string16.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" class Profile; @@ -19,12 +19,13 @@ class DictionaryValue; } void ShowExtensionInstallDialog(Profile* profile, - ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt); + ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt); // The implementations of this function are platform-specific. -void ShowExtensionInstallDialogImpl(Profile* profile, - ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt); +void ShowExtensionInstallDialogImpl( + Profile* profile, + ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt); #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_DIALOG_H_ diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc new file mode 100644 index 0000000..be5cbc2 --- /dev/null +++ b/chrome/browser/extensions/extension_install_prompt.cc @@ -0,0 +1,409 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_install_prompt.h" + +#include <map> + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/string_number_conversions.h" +#include "base/string_util.h" +#include "base/stringprintf.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/extensions/bundle_installer.h" +#include "chrome/browser/extensions/extension_install_dialog.h" +#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_icon_set.h" +#include "chrome/common/extensions/extension_manifest_constants.h" +#include "chrome/common/extensions/extension_resource.h" +#include "chrome/common/extensions/extension_switch_utils.h" +#include "chrome/common/extensions/url_pattern.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image.h" + +#if defined(USE_ASH) +#include "ash/shell.h" +#endif + +using extensions::BundleInstaller; +using extensions::Extension; + +static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = { + 0, // The regular install prompt depends on what's being installed. + IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE, + IDS_EXTENSION_INSTALL_PROMPT_TITLE, + IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE, + IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE +}; +static const int kHeadingIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = { + IDS_EXTENSION_INSTALL_PROMPT_HEADING, + 0, // Inline installs use the extension name. + 0, // Heading for bundle installs depends on the bundle contents. + IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING, + IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING +}; +static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = { + IDS_EXTENSION_PROMPT_INSTALL_BUTTON, + IDS_EXTENSION_PROMPT_INSTALL_BUTTON, + IDS_EXTENSION_PROMPT_INSTALL_BUTTON, + IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON, + IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON +}; +static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = { + 0, // These all use the platform's default cancel label. + 0, + 0, + 0, + IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON +}; +static const int kPermissionsHeaderIds[ + ExtensionInstallPrompt::NUM_PROMPT_TYPES] = { + IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO, + IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO, + IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO, + IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO, + IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO, +}; + +namespace { + +// Size of extension icon in top left of dialog. +const int kIconSize = 69; + +} // namespace + +ExtensionInstallPrompt::Prompt::Prompt(PromptType type) + : type_(type), + extension_(NULL), + bundle_(NULL), + average_rating_(0.0), + rating_count_(0) { +} + +ExtensionInstallPrompt::Prompt::~Prompt() { +} + +void ExtensionInstallPrompt::Prompt::SetPermissions( + const std::vector<string16>& permissions) { + permissions_ = permissions; +} + +void ExtensionInstallPrompt::Prompt::SetInlineInstallWebstoreData( + const std::string& localized_user_count, + double average_rating, + int rating_count) { + CHECK_EQ(INLINE_INSTALL_PROMPT, type_); + localized_user_count_ = localized_user_count; + average_rating_ = average_rating; + rating_count_ = rating_count; +} + +string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const { + + int resource_id = kTitleIds[type_]; + + if (type_ == INSTALL_PROMPT) { + if (extension_->is_app()) + resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE; + else if (extension_->is_theme()) + resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE; + else + resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE; + } + + return l10n_util::GetStringUTF16(resource_id); +} + +string16 ExtensionInstallPrompt::Prompt::GetHeading() const { + if (type_ == INLINE_INSTALL_PROMPT) { + return UTF8ToUTF16(extension_->name()); + } else if (type_ == BUNDLE_INSTALL_PROMPT) { + return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING); + } else { + return l10n_util::GetStringFUTF16( + kHeadingIds[type_], UTF8ToUTF16(extension_->name())); + } +} + +string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const { + return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]); +} + +bool ExtensionInstallPrompt::Prompt::HasAbortButtonLabel() const { + return kAbortButtonIds[type_] > 0; +} + +string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const { + CHECK(HasAbortButtonLabel()); + return l10n_util::GetStringUTF16(kAbortButtonIds[type_]); +} + +string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading() const { + return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]); +} + +void ExtensionInstallPrompt::Prompt::AppendRatingStars( + StarAppender appender, void* data) const { + CHECK(appender); + CHECK_EQ(INLINE_INSTALL_PROMPT, type_); + int rating_integer = floor(average_rating_); + double rating_fractional = average_rating_ - rating_integer; + + if (rating_fractional > 0.66) { + rating_integer++; + } + + if (rating_fractional < 0.33 || rating_fractional > 0.66) { + rating_fractional = 0; + } + + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + int i; + for (i = 0; i < rating_integer; i++) { + appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data); + } + if (rating_fractional) { + appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data); + i++; + } + for (; i < kMaxExtensionRating; i++) { + appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data); + } +} + +string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const { + CHECK_EQ(INLINE_INSTALL_PROMPT, type_); + return l10n_util::GetStringFUTF16( + IDS_EXTENSION_RATING_COUNT, + UTF8ToUTF16(base::IntToString(rating_count_))); +} + +string16 ExtensionInstallPrompt::Prompt::GetUserCount() const { + CHECK_EQ(INLINE_INSTALL_PROMPT, type_); + return l10n_util::GetStringFUTF16( + IDS_EXTENSION_USER_COUNT, + UTF8ToUTF16(localized_user_count_)); +} + +size_t ExtensionInstallPrompt::Prompt::GetPermissionCount() const { + return permissions_.size(); +} + +string16 ExtensionInstallPrompt::Prompt::GetPermission(size_t index) const { + CHECK_LT(index, permissions_.size()); + return l10n_util::GetStringFUTF16( + IDS_EXTENSION_PERMISSION_LINE, permissions_[index]); +} + +// static +scoped_refptr<Extension> + ExtensionInstallPrompt::GetLocalizedExtensionForDisplay( + const DictionaryValue* manifest, + const std::string& id, + const std::string& localized_name, + const std::string& localized_description, + std::string* error) { + scoped_ptr<DictionaryValue> localized_manifest; + if (!localized_name.empty() || !localized_description.empty()) { + localized_manifest.reset(manifest->DeepCopy()); + if (!localized_name.empty()) { + localized_manifest->SetString(extension_manifest_keys::kName, + localized_name); + } + if (!localized_description.empty()) { + localized_manifest->SetString(extension_manifest_keys::kDescription, + localized_description); + } + } + + return Extension::Create( + FilePath(), + Extension::INTERNAL, + localized_manifest.get() ? *localized_manifest.get() : *manifest, + Extension::NO_FLAGS, + id, + error); +} + +ExtensionInstallPrompt::ExtensionInstallPrompt(Profile* profile) + : profile_(profile), + ui_loop_(MessageLoop::current()), + extension_(NULL), + install_ui_(ExtensionInstallUI::Create(profile)), + delegate_(NULL), + prompt_(UNSET_PROMPT_TYPE), + prompt_type_(UNSET_PROMPT_TYPE), + ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { +} + +ExtensionInstallPrompt::~ExtensionInstallPrompt() { +} + +void ExtensionInstallPrompt::ConfirmBundleInstall( + extensions::BundleInstaller* bundle, + const ExtensionPermissionSet* permissions) { + DCHECK(ui_loop_ == MessageLoop::current()); + bundle_ = bundle; + permissions_ = permissions; + delegate_ = bundle; + prompt_type_ = BUNDLE_INSTALL_PROMPT; + + ShowConfirmation(); +} + +void ExtensionInstallPrompt::ConfirmInlineInstall( + Delegate* delegate, + const Extension* extension, + SkBitmap* icon, + const ExtensionInstallPrompt::Prompt& prompt) { + DCHECK(ui_loop_ == MessageLoop::current()); + extension_ = extension; + permissions_ = extension->GetActivePermissions(); + delegate_ = delegate; + prompt_ = prompt; + prompt_type_ = INLINE_INSTALL_PROMPT; + + SetIcon(icon); + ShowConfirmation(); +} + +void ExtensionInstallPrompt::ConfirmWebstoreInstall(Delegate* delegate, + const Extension* extension, + const SkBitmap* icon) { + // SetIcon requires |extension_| to be set. ConfirmInstall will setup the + // remaining fields. + extension_ = extension; + SetIcon(icon); + ConfirmInstall(delegate, extension); +} + +void ExtensionInstallPrompt::ConfirmInstall(Delegate* delegate, + const Extension* extension) { + DCHECK(ui_loop_ == MessageLoop::current()); + extension_ = extension; + permissions_ = extension->GetActivePermissions(); + delegate_ = delegate; + prompt_type_ = INSTALL_PROMPT; + + // We special-case themes to not show any confirm UI. Instead they are + // immediately installed, and then we show an infobar (see OnInstallSuccess) + // to allow the user to revert if they don't like it. + // + // We don't do this in the case where off-store extension installs are + // disabled because in that case, we don't show the dangerous download UI, so + // we need the UI confirmation. + if (extension->is_theme()) { + if (extension->from_webstore() || + extensions::switch_utils::IsEasyOffStoreInstallEnabled()) { + delegate->InstallUIProceed(); + return; + } + } + + LoadImageIfNeeded(); +} + +void ExtensionInstallPrompt::ConfirmReEnable(Delegate* delegate, + const Extension* extension) { + DCHECK(ui_loop_ == MessageLoop::current()); + extension_ = extension; + permissions_ = extension->GetActivePermissions(); + delegate_ = delegate; + prompt_type_ = RE_ENABLE_PROMPT; + + LoadImageIfNeeded(); +} + +void ExtensionInstallPrompt::ConfirmPermissions( + Delegate* delegate, + const Extension* extension, + const ExtensionPermissionSet* permissions) { + DCHECK(ui_loop_ == MessageLoop::current()); + extension_ = extension; + permissions_ = permissions; + delegate_ = delegate; + prompt_type_ = PERMISSIONS_PROMPT; + + LoadImageIfNeeded(); +} + +void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension, + SkBitmap* icon) { + extension_ = extension; + SetIcon(icon); + + install_ui_->OnInstallSuccess(extension, &icon_); +} + +void ExtensionInstallPrompt::OnInstallFailure(const string16& error) { + install_ui_->OnInstallFailure(error); +} + +void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) { + if (image) + icon_ = *image; + else + icon_ = SkBitmap(); + if (icon_.empty()) + icon_ = Extension::GetDefaultIcon(extension_->is_app()); +} + +void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) { + SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap()); + ShowConfirmation(); +} + +void ExtensionInstallPrompt::LoadImageIfNeeded() { + // Bundle install prompts do not have an icon. + if (!icon_.empty()) { + ShowConfirmation(); + return; + } + + // Load the image asynchronously. For the response, check OnImageLoaded. + ExtensionResource image = + extension_->GetIconResource(ExtensionIconSet::EXTENSION_ICON_LARGE, + ExtensionIconSet::MATCH_BIGGER); + tracker_.LoadImage(extension_, image, + gfx::Size(kIconSize, kIconSize), + ImageLoadingTracker::DONT_CACHE); +} + +void ExtensionInstallPrompt::ShowConfirmation() { + prompt_.set_type(prompt_type_); + prompt_.SetPermissions(permissions_->GetWarningMessages()); + + switch (prompt_type_) { + case PERMISSIONS_PROMPT: + case RE_ENABLE_PROMPT: + case INLINE_INSTALL_PROMPT: + case INSTALL_PROMPT: { + prompt_.set_extension(extension_); + prompt_.set_icon(gfx::Image(icon_)); + ShowExtensionInstallDialog(profile_, delegate_, prompt_); + break; + } + case BUNDLE_INSTALL_PROMPT: { + prompt_.set_bundle(bundle_); + ShowExtensionInstallDialog(profile_, delegate_, prompt_); + break; + } + default: + NOTREACHED() << "Unknown message"; + break; + } +} diff --git a/chrome/browser/extensions/extension_install_prompt.h b/chrome/browser/extensions/extension_install_prompt.h new file mode 100644 index 0000000..a77c2dc --- /dev/null +++ b/chrome/browser/extensions/extension_install_prompt.h @@ -0,0 +1,266 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/string16.h" +#include "chrome/browser/extensions/image_loading_tracker.h" +#include "chrome/common/extensions/url_pattern.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/native_widget_types.h" + +class ExtensionInstallUI; +class ExtensionPermissionSet; +class MessageLoop; +class Profile; +class InfoBarDelegate; + +namespace base { +class DictionaryValue; +} // namespace base + +namespace extensions { +class BundleInstaller; +class Extension; +class ExtensionWebstorePrivateApiTest; +} // namespace extensions + +// Displays all the UI around extension installation. +class ExtensionInstallPrompt : public ImageLoadingTracker::Observer { + public: + enum PromptType { + UNSET_PROMPT_TYPE = -1, + INSTALL_PROMPT = 0, + INLINE_INSTALL_PROMPT, + BUNDLE_INSTALL_PROMPT, + RE_ENABLE_PROMPT, + PERMISSIONS_PROMPT, + NUM_PROMPT_TYPES + }; + + // Extra information needed to display an installation or uninstallation + // prompt. Gets populated with raw data and exposes getters for formatted + // strings so that the GTK/views/Cocoa install dialogs don't have to repeat + // that logic. + class Prompt { + public: + explicit Prompt(PromptType type); + ~Prompt(); + + void SetPermissions(const std::vector<string16>& permissions); + void SetInlineInstallWebstoreData(const std::string& localized_user_count, + double average_rating, + int rating_count); + + PromptType type() const { return type_; } + void set_type(PromptType type) { type_ = type; } + + // Getters for UI element labels. + string16 GetDialogTitle() const; + string16 GetHeading() const; + string16 GetAcceptButtonLabel() const; + bool HasAbortButtonLabel() const; + string16 GetAbortButtonLabel() const; + string16 GetPermissionsHeading() const; + + // Getters for webstore metadata. Only populated when the type is + // INLINE_INSTALL_PROMPT. + + // The star display logic replicates the one used by the webstore (from + // components.ratingutils.setFractionalYellowStars). Callers pass in an + // "appender", which will be repeatedly called back with the star images + // that they append to the star display area. + typedef void(*StarAppender)(const gfx::ImageSkia*, void*); + void AppendRatingStars(StarAppender appender, void* data) const; + string16 GetRatingCount() const; + string16 GetUserCount() const; + size_t GetPermissionCount() const; + string16 GetPermission(size_t index) const; + + // Populated for BUNDLE_INSTALL_PROMPT. + const extensions::BundleInstaller* bundle() const { return bundle_; } + void set_bundle(const extensions::BundleInstaller* bundle) { + bundle_ = bundle; + } + + // Populated for all other types. + const extensions::Extension* extension() const { return extension_; } + void set_extension(const extensions::Extension* extension) { + extension_ = extension; + } + + const gfx::Image& icon() const { return icon_; } + void set_icon(const gfx::Image& icon) { icon_ = icon; } + + private: + PromptType type_; + // Permissions that are being requested (may not be all of an extension's + // permissions if only additional ones are being requested) + std::vector<string16> permissions_; + + // The extension or bundle being installed. + const extensions::Extension* extension_; + const extensions::BundleInstaller* bundle_; + + // The icon to be displayed. + gfx::Image icon_; + + // These fields are populated only when the prompt type is + // INLINE_INSTALL_PROMPT + // Already formatted to be locale-specific. + std::string localized_user_count_; + // Range is kMinExtensionRating to kMaxExtensionRating + double average_rating_; + int rating_count_; + }; + + static const int kMinExtensionRating = 0; + static const int kMaxExtensionRating = 5; + + class Delegate { + public: + // We call this method to signal that the installation should continue. + virtual void InstallUIProceed() = 0; + + // We call this method to signal that the installation should stop, with + // |user_initiated| true if the installation was stopped by the user. + virtual void InstallUIAbort(bool user_initiated) = 0; + + protected: + virtual ~Delegate() {} + }; + + // Creates a dummy extension from the |manifest|, replacing the name and + // description with the localizations if provided. + static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay( + const base::DictionaryValue* manifest, + const std::string& id, + const std::string& localized_name, + const std::string& localized_description, + std::string* error); + + explicit ExtensionInstallPrompt(Profile* profile); + virtual ~ExtensionInstallPrompt(); + + ExtensionInstallUI* install_ui() const { return install_ui_.get(); } + + // This is called by the bundle installer to verify whether the bundle + // should be installed. + // + // We *MUST* eventually call either Proceed() or Abort() on |delegate|. + virtual void ConfirmBundleInstall(extensions::BundleInstaller* bundle, + const ExtensionPermissionSet* permissions); + + // This is called by the inline installer to verify whether the inline + // install from the webstore should proceed. + // + // We *MUST* eventually call either Proceed() or Abort() on |delegate|. + virtual void ConfirmInlineInstall(Delegate* delegate, + const extensions::Extension* extension, + SkBitmap* icon, + const Prompt& prompt); + + // This is called by the installer to verify whether the installation from + // the webstore should proceed. + // + // We *MUST* eventually call either Proceed() or Abort() on |delegate|. + virtual void ConfirmWebstoreInstall(Delegate* delegate, + const extensions::Extension* extension, + const SkBitmap* icon); + + // This is called by the installer to verify whether the installation should + // proceed. This is declared virtual for testing. + // + // We *MUST* eventually call either Proceed() or Abort() on |delegate|. + virtual void ConfirmInstall(Delegate* delegate, + const extensions::Extension* extension); + + // This is called by the app handler launcher to verify whether the app + // should be re-enabled. This is declared virtual for testing. + // + // We *MUST* eventually call either Proceed() or Abort() on |delegate|. + virtual void ConfirmReEnable(Delegate* delegate, + const extensions::Extension* extension); + + // This is called by the extension permissions API to verify whether an + // extension may be granted additional permissions. + // + // We *MUST* eventually call either Proceed() or Abort() on |delegate|. + virtual void ConfirmPermissions(Delegate* delegate, + const extensions::Extension* extension, + const ExtensionPermissionSet* permissions); + + // Installation was successful. This is declared virtual for testing. + virtual void OnInstallSuccess(const extensions::Extension* extension, + SkBitmap* icon); + + // Installation failed. This is declared virtual for testing. + virtual void OnInstallFailure(const string16& error); + + // ImageLoadingTracker::Observer: + virtual void OnImageLoaded(const gfx::Image& image, + const std::string& extension_id, + int index) OVERRIDE; + + protected: + friend class extensions::ExtensionWebstorePrivateApiTest; + friend class WebstoreInlineInstallUnpackFailureTest; + + private: + friend class GalleryInstallApiTestObserver; + + // Sets the icon that will be used in any UI. If |icon| is NULL, or contains + // an empty bitmap, then a default icon will be used instead. + void SetIcon(const SkBitmap* icon); + + // Starts the process of showing a confirmation UI, which is split into two. + // 1) Set off a 'load icon' task. + // 2) Handle the load icon response and show the UI (OnImageLoaded). + void LoadImageIfNeeded(); + + // Shows the actual UI (the icon should already be loaded). + void ShowConfirmation(); + + Profile* profile_; + MessageLoop* ui_loop_; + + // The extensions installation icon. + SkBitmap icon_; + + // The extension we are showing the UI for. + const extensions::Extension* extension_; + + // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT. + const extensions::BundleInstaller* bundle_; + + // The permissions being prompted for. + scoped_refptr<const ExtensionPermissionSet> permissions_; + + // The object responsible for doing the UI specific actions. + scoped_ptr<ExtensionInstallUI> install_ui_; + + // The delegate we will call Proceed/Abort on after confirmation UI. + Delegate* delegate_; + + // A pre-filled prompt. + Prompt prompt_; + + // The type of prompt we are going to show. + PromptType prompt_type_; + + // Keeps track of extension images being loaded on the File thread for the + // purpose of showing the install UI. + ImageLoadingTracker tracker_; +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_ diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc index 105c368..6382635f 100644 --- a/chrome/browser/extensions/extension_install_ui.cc +++ b/chrome/browser/extensions/extension_install_ui.cc @@ -3,562 +3,8 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_install_ui.h" - -#include <map> - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/message_loop.h" -#include "base/string_number_conversions.h" -#include "base/string_util.h" -#include "base/stringprintf.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/extensions/bundle_installer.h" -#include "chrome/browser/extensions/extension_install_dialog.h" -#include "chrome/browser/extensions/theme_installed_infobar_delegate.h" -#include "chrome/browser/infobars/infobar_tab_helper.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/themes/theme_service.h" -#include "chrome/browser/themes/theme_service_factory.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_dialogs.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/browser_navigator.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/simple_message_box.h" -#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/webui/ntp/new_tab_ui.h" -#include "chrome/common/chrome_notification_types.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_icon_set.h" -#include "chrome/common/extensions/extension_manifest_constants.h" -#include "chrome/common/extensions/extension_resource.h" -#include "chrome/common/extensions/extension_switch_utils.h" -#include "chrome/common/extensions/url_pattern.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/notification_service.h" -#include "grit/chromium_strings.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/image/image.h" - -#if defined(USE_ASH) -#include "ash/shell.h" -#endif - -using content::WebContents; -using extensions::BundleInstaller; -using extensions::Extension; - -static const int kTitleIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { - 0, // The regular install prompt depends on what's being installed. - IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE, - IDS_EXTENSION_INSTALL_PROMPT_TITLE, - IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE, - IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE -}; -static const int kHeadingIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { - IDS_EXTENSION_INSTALL_PROMPT_HEADING, - 0, // Inline installs use the extension name. - 0, // Heading for bundle installs depends on the bundle contents. - IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING, - IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING -}; -static const int kAcceptButtonIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { - IDS_EXTENSION_PROMPT_INSTALL_BUTTON, - IDS_EXTENSION_PROMPT_INSTALL_BUTTON, - IDS_EXTENSION_PROMPT_INSTALL_BUTTON, - IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON, - IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON -}; -static const int kAbortButtonIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { - 0, // These all use the platform's default cancel label. - 0, - 0, - 0, - IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON -}; -static const int kPermissionsHeaderIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { - IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO, - IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO, - IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO, - IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO, - IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO, -}; - -namespace { - -// Size of extension icon in top left of dialog. -const int kIconSize = 69; - -} // namespace - -ExtensionInstallUI::Prompt::Prompt(PromptType type) - : type_(type), - extension_(NULL), - bundle_(NULL), - average_rating_(0.0), - rating_count_(0) { -} - -ExtensionInstallUI::Prompt::~Prompt() { -} - -void ExtensionInstallUI::Prompt::SetPermissions( - const std::vector<string16>& permissions) { - permissions_ = permissions; -} - -void ExtensionInstallUI::Prompt::SetInlineInstallWebstoreData( - const std::string& localized_user_count, - double average_rating, - int rating_count) { - CHECK_EQ(INLINE_INSTALL_PROMPT, type_); - localized_user_count_ = localized_user_count; - average_rating_ = average_rating; - rating_count_ = rating_count; -} - -string16 ExtensionInstallUI::Prompt::GetDialogTitle() const { - int resource_id = kTitleIds[type_]; - - if (type_ == INSTALL_PROMPT) { - if (extension_->is_app()) - resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE; - else if (extension_->is_theme()) - resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE; - else - resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE; - } - - return l10n_util::GetStringUTF16(resource_id); -} - -string16 ExtensionInstallUI::Prompt::GetHeading() const { - if (type_ == INLINE_INSTALL_PROMPT) { - return UTF8ToUTF16(extension_->name()); - } else if (type_ == BUNDLE_INSTALL_PROMPT) { - return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING); - } else { - return l10n_util::GetStringFUTF16( - kHeadingIds[type_], UTF8ToUTF16(extension_->name())); - } -} - -string16 ExtensionInstallUI::Prompt::GetAcceptButtonLabel() const { - return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]); -} - -bool ExtensionInstallUI::Prompt::HasAbortButtonLabel() const { - return kAbortButtonIds[type_] > 0; -} - -string16 ExtensionInstallUI::Prompt::GetAbortButtonLabel() const { - CHECK(HasAbortButtonLabel()); - return l10n_util::GetStringUTF16(kAbortButtonIds[type_]); -} - -string16 ExtensionInstallUI::Prompt::GetPermissionsHeading() const { - return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]); -} - -void ExtensionInstallUI::Prompt::AppendRatingStars( - StarAppender appender, void* data) const { - CHECK(appender); - CHECK_EQ(INLINE_INSTALL_PROMPT, type_); - int rating_integer = floor(average_rating_); - double rating_fractional = average_rating_ - rating_integer; - - if (rating_fractional > 0.66) { - rating_integer++; - } - - if (rating_fractional < 0.33 || rating_fractional > 0.66) { - rating_fractional = 0; - } - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - int i; - for (i = 0; i < rating_integer; i++) { - appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data); - } - if (rating_fractional) { - appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data); - i++; - } - for (; i < kMaxExtensionRating; i++) { - appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data); - } -} - -string16 ExtensionInstallUI::Prompt::GetRatingCount() const { - CHECK_EQ(INLINE_INSTALL_PROMPT, type_); - return l10n_util::GetStringFUTF16( - IDS_EXTENSION_RATING_COUNT, - UTF8ToUTF16(base::IntToString(rating_count_))); -} - -string16 ExtensionInstallUI::Prompt::GetUserCount() const { - CHECK_EQ(INLINE_INSTALL_PROMPT, type_); - return l10n_util::GetStringFUTF16( - IDS_EXTENSION_USER_COUNT, - UTF8ToUTF16(localized_user_count_)); -} - -size_t ExtensionInstallUI::Prompt::GetPermissionCount() const { - return permissions_.size(); -} - -string16 ExtensionInstallUI::Prompt::GetPermission(size_t index) const { - CHECK_LT(index, permissions_.size()); - return l10n_util::GetStringFUTF16( - IDS_EXTENSION_PERMISSION_LINE, permissions_[index]); -} - -// static -scoped_refptr<Extension> ExtensionInstallUI::GetLocalizedExtensionForDisplay( - const DictionaryValue* manifest, - const std::string& id, - const std::string& localized_name, - const std::string& localized_description, - std::string* error) { - scoped_ptr<DictionaryValue> localized_manifest; - if (!localized_name.empty() || !localized_description.empty()) { - localized_manifest.reset(manifest->DeepCopy()); - if (!localized_name.empty()) { - localized_manifest->SetString(extension_manifest_keys::kName, - localized_name); - } - if (!localized_description.empty()) { - localized_manifest->SetString(extension_manifest_keys::kDescription, - localized_description); - } - } - - return Extension::Create( - FilePath(), - Extension::INTERNAL, - localized_manifest.get() ? *localized_manifest.get() : *manifest, - Extension::NO_FLAGS, - id, - error); -} - -ExtensionInstallUI::ExtensionInstallUI(Profile* profile) - : profile_(profile), - ui_loop_(MessageLoop::current()), - previous_using_native_theme_(false), - extension_(NULL), - delegate_(NULL), - prompt_(UNSET_PROMPT_TYPE), - prompt_type_(UNSET_PROMPT_TYPE), - ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)), - use_app_installed_bubble_(false), - skip_post_install_ui_(false) { - // Remember the current theme in case the user presses undo. - if (profile_) { - const Extension* previous_theme = - ThemeServiceFactory::GetThemeForProfile(profile_); - if (previous_theme) - previous_theme_id_ = previous_theme->id(); - previous_using_native_theme_ = - ThemeServiceFactory::GetForProfile(profile_)->UsingNativeTheme(); - } +ExtensionInstallUI::ExtensionInstallUI() { } ExtensionInstallUI::~ExtensionInstallUI() { } - -void ExtensionInstallUI::ConfirmBundleInstall( - extensions::BundleInstaller* bundle, - const ExtensionPermissionSet* permissions) { - DCHECK(ui_loop_ == MessageLoop::current()); - bundle_ = bundle; - permissions_ = permissions; - delegate_ = bundle; - prompt_type_ = BUNDLE_INSTALL_PROMPT; - - ShowConfirmation(); -} - -void ExtensionInstallUI::ConfirmInlineInstall( - Delegate* delegate, - const Extension* extension, - SkBitmap* icon, - const ExtensionInstallUI::Prompt& prompt) { - DCHECK(ui_loop_ == MessageLoop::current()); - extension_ = extension; - permissions_ = extension->GetActivePermissions(); - delegate_ = delegate; - prompt_ = prompt; - prompt_type_ = INLINE_INSTALL_PROMPT; - - SetIcon(icon); - ShowConfirmation(); -} - -void ExtensionInstallUI::ConfirmWebstoreInstall(Delegate* delegate, - const Extension* extension, - const SkBitmap* icon) { - // SetIcon requires |extension_| to be set. ConfirmInstall will setup the - // remaining fields. - extension_ = extension; - SetIcon(icon); - ConfirmInstall(delegate, extension); -} - -void ExtensionInstallUI::ConfirmInstall(Delegate* delegate, - const Extension* extension) { - DCHECK(ui_loop_ == MessageLoop::current()); - extension_ = extension; - permissions_ = extension->GetActivePermissions(); - delegate_ = delegate; - prompt_type_ = INSTALL_PROMPT; - - // We special-case themes to not show any confirm UI. Instead they are - // immediately installed, and then we show an infobar (see OnInstallSuccess) - // to allow the user to revert if they don't like it. - // - // We don't do this in the case where off-store extension installs are - // disabled because in that case, we don't show the dangerous download UI, so - // we need the UI confirmation. - if (extension->is_theme()) { - if (extension->from_webstore() || - extensions::switch_utils::IsEasyOffStoreInstallEnabled()) { - delegate->InstallUIProceed(); - return; - } - } - - LoadImageIfNeeded(); -} - -void ExtensionInstallUI::ConfirmReEnable(Delegate* delegate, - const Extension* extension) { - DCHECK(ui_loop_ == MessageLoop::current()); - extension_ = extension; - permissions_ = extension->GetActivePermissions(); - delegate_ = delegate; - prompt_type_ = RE_ENABLE_PROMPT; - - LoadImageIfNeeded(); -} - -void ExtensionInstallUI::ConfirmPermissions( - Delegate* delegate, - const Extension* extension, - const ExtensionPermissionSet* permissions) { - DCHECK(ui_loop_ == MessageLoop::current()); - extension_ = extension; - permissions_ = permissions; - delegate_ = delegate; - prompt_type_ = PERMISSIONS_PROMPT; - - LoadImageIfNeeded(); -} - -void ExtensionInstallUI::OnInstallSuccess(const Extension* extension, - SkBitmap* icon) { - if (skip_post_install_ui_) - return; - - extension_ = extension; - SetIcon(icon); - - if (extension->is_theme()) { - ShowThemeInfoBar(previous_theme_id_, previous_using_native_theme_, - extension, profile_); - return; - } - - // Extensions aren't enabled by default in incognito so we confirm - // the install in a normal window. - Profile* profile = profile_->GetOriginalProfile(); - Browser* browser = browser::FindOrCreateTabbedBrowser(profile); - if (browser->tab_count() == 0) - browser->AddBlankTab(true); - browser->window()->Show(); - - bool use_bubble_for_apps = false; - -#if defined(TOOLKIT_VIEWS) - CommandLine* cmdline = CommandLine::ForCurrentProcess(); - use_bubble_for_apps = (use_app_installed_bubble_ || - cmdline->HasSwitch(switches::kAppsNewInstallBubble)); -#endif - - if (extension->is_app() && !use_bubble_for_apps) { - ExtensionInstallUI::OpenAppInstalledUI(browser, extension->id()); - return; - } - - browser::ShowExtensionInstalledBubble(extension, browser, icon_, profile); -} - -namespace { - -bool disable_failure_ui_for_tests = false; - -} // namespace - -void ExtensionInstallUI::OnInstallFailure(const string16& error) { - DCHECK(ui_loop_ == MessageLoop::current()); - if (disable_failure_ui_for_tests || skip_post_install_ui_) - return; - - Browser* browser = browser::FindLastActiveWithProfile(profile_); - browser::ShowMessageBox(browser ? browser->window()->GetNativeWindow() : NULL, - l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_FAILURE_TITLE), error, - browser::MESSAGE_BOX_TYPE_WARNING); -} - -void ExtensionInstallUI::SetIcon(const SkBitmap* image) { - if (image) - icon_ = *image; - else - icon_ = SkBitmap(); - if (icon_.empty()) - icon_ = Extension::GetDefaultIcon(extension_->is_app()); -} - -void ExtensionInstallUI::OnImageLoaded(const gfx::Image& image, - const std::string& extension_id, - int index) { - SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap()); - ShowConfirmation(); -} - -// static -void ExtensionInstallUI::OpenAppInstalledUI(Browser* browser, - const std::string& app_id) { - if (NewTabUI::ShouldShowApps()) { - browser::NavigateParams params = browser->GetSingletonTabNavigateParams( - GURL(chrome::kChromeUINewTabURL)); - browser::Navigate(¶ms); - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_APP_INSTALLED_TO_NTP, - content::Source<WebContents>(params.target_contents->web_contents()), - content::Details<const std::string>(&app_id)); - } else { -#if defined(USE_ASH) - ash::Shell::GetInstance()->ToggleAppList(); - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST, - content::Source<Profile>(browser->profile()), - content::Details<const std::string>(&app_id)); -#else - NOTREACHED(); -#endif - } -} - -// static -void ExtensionInstallUI::DisableFailureUIForTests() { - disable_failure_ui_for_tests = true; -} - -void ExtensionInstallUI::ShowThemeInfoBar(const std::string& previous_theme_id, - bool previous_using_native_theme, - const Extension* new_theme, - Profile* profile) { - if (!new_theme->is_theme()) - return; - - // Get last active tabbed browser of profile. - Browser* browser = browser::FindTabbedBrowser(profile, true); - if (!browser) - return; - - TabContentsWrapper* tab_contents = browser->GetSelectedTabContentsWrapper(); - if (!tab_contents) - return; - InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); - - // First find any previous theme preview infobars. - InfoBarDelegate* old_delegate = NULL; - for (size_t i = 0; i < infobar_helper->infobar_count(); ++i) { - InfoBarDelegate* delegate = infobar_helper->GetInfoBarDelegateAt(i); - ThemeInstalledInfoBarDelegate* theme_infobar = - delegate->AsThemePreviewInfobarDelegate(); - if (theme_infobar) { - // If the user installed the same theme twice, ignore the second install - // and keep the first install info bar, so that they can easily undo to - // get back the previous theme. - if (theme_infobar->MatchesTheme(new_theme)) - return; - old_delegate = delegate; - break; - } - } - - // Then either replace that old one or add a new one. - InfoBarDelegate* new_delegate = GetNewThemeInstalledInfoBarDelegate( - tab_contents, new_theme, previous_theme_id, previous_using_native_theme); - - if (old_delegate) - infobar_helper->ReplaceInfoBar(old_delegate, new_delegate); - else - infobar_helper->AddInfoBar(new_delegate); -} - -void ExtensionInstallUI::LoadImageIfNeeded() { - // Bundle install prompts do not have an icon. - if (!icon_.empty()) { - ShowConfirmation(); - return; - } - - // Load the image asynchronously. For the response, check OnImageLoaded. - ExtensionResource image = - extension_->GetIconResource(ExtensionIconSet::EXTENSION_ICON_LARGE, - ExtensionIconSet::MATCH_BIGGER); - tracker_.LoadImage(extension_, image, - gfx::Size(kIconSize, kIconSize), - ImageLoadingTracker::DONT_CACHE); -} - -void ExtensionInstallUI::ShowConfirmation() { - prompt_.set_type(prompt_type_); - prompt_.SetPermissions(permissions_->GetWarningMessages()); - - switch (prompt_type_) { - case PERMISSIONS_PROMPT: - case RE_ENABLE_PROMPT: - case INLINE_INSTALL_PROMPT: - case INSTALL_PROMPT: { - prompt_.set_extension(extension_); - prompt_.set_icon(gfx::Image(icon_)); - ShowExtensionInstallDialog(profile_, delegate_, prompt_); - break; - } - case BUNDLE_INSTALL_PROMPT: { - prompt_.set_bundle(bundle_); - ShowExtensionInstallDialog(profile_, delegate_, prompt_); - break; - } - default: - NOTREACHED() << "Unknown message"; - break; - } -} - -InfoBarDelegate* ExtensionInstallUI::GetNewThemeInstalledInfoBarDelegate( - TabContentsWrapper* tab_contents, - const Extension* new_theme, - const std::string& previous_theme_id, - bool previous_using_native_theme) { - Profile* profile = tab_contents->profile(); - return new ThemeInstalledInfoBarDelegate( - tab_contents->infobar_tab_helper(), - profile->GetExtensionService(), - ThemeServiceFactory::GetForProfile(profile), - new_theme, - previous_theme_id, - previous_using_native_theme); -} diff --git a/chrome/browser/extensions/extension_install_ui.h b/chrome/browser/extensions/extension_install_ui.h index 1f46eec..b908259 100644 --- a/chrome/browser/extensions/extension_install_ui.h +++ b/chrome/browser/extensions/extension_install_ui.h @@ -7,302 +7,51 @@ #pragma once #include <string> -#include <vector> #include "base/compiler_specific.h" #include "base/string16.h" -#include "chrome/browser/extensions/image_loading_tracker.h" -#include "chrome/common/extensions/url_pattern.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/gfx/native_widget_types.h" class Browser; -class ExtensionPermissionSet; -class MessageLoop; class Profile; -class InfoBarDelegate; -class TabContents; -typedef TabContents TabContentsWrapper; - -namespace base { -class DictionaryValue; -} +class SkBitmap; namespace extensions { -class BundleInstaller; class Extension; class ExtensionWebstorePrivateApiTest; } // namespace extensions -// Displays all the UI around extension installation. -class ExtensionInstallUI : public ImageLoadingTracker::Observer { +// Interface that should be implemented for each platform to display all the UI +// around extension installation. +class ExtensionInstallUI { public: - enum PromptType { - UNSET_PROMPT_TYPE = -1, - INSTALL_PROMPT = 0, - INLINE_INSTALL_PROMPT, - BUNDLE_INSTALL_PROMPT, - RE_ENABLE_PROMPT, - PERMISSIONS_PROMPT, - NUM_PROMPT_TYPES - }; - - // Extra information needed to display an installation or uninstallation - // prompt. Gets populated with raw data and exposes getters for formatted - // strings so that the GTK/views/Cocoa install dialogs don't have to repeat - // that logic. - class Prompt { - public: - explicit Prompt(PromptType type); - ~Prompt(); - - void SetPermissions(const std::vector<string16>& permissions); - void SetInlineInstallWebstoreData(const std::string& localized_user_count, - double average_rating, - int rating_count); - - PromptType type() const { return type_; } - void set_type(PromptType type) { type_ = type; } - - // Getters for UI element labels. - string16 GetDialogTitle() const; - string16 GetHeading() const; - string16 GetAcceptButtonLabel() const; - bool HasAbortButtonLabel() const; - string16 GetAbortButtonLabel() const; - string16 GetPermissionsHeading() const; - - // Getters for webstore metadata. Only populated when the type is - // INLINE_INSTALL_PROMPT. - - // The star display logic replicates the one used by the webstore (from - // components.ratingutils.setFractionalYellowStars). Callers pass in an - // "appender", which will be repeatedly called back with the star images - // that they append to the star display area. - typedef void(*StarAppender)(const gfx::ImageSkia*, void*); - void AppendRatingStars(StarAppender appender, void* data) const; - string16 GetRatingCount() const; - string16 GetUserCount() const; - size_t GetPermissionCount() const; - string16 GetPermission(size_t index) const; - - // Populated for BUNDLE_INSTALL_PROMPT. - const extensions::BundleInstaller* bundle() const { return bundle_; } - void set_bundle(const extensions::BundleInstaller* bundle) { - bundle_ = bundle; - } - - // Populated for all other types. - const extensions::Extension* extension() const { return extension_; } - void set_extension(const extensions::Extension* extension) { - extension_ = extension; - } - - const gfx::Image& icon() const { return icon_; } - void set_icon(const gfx::Image& icon) { icon_ = icon; } - - private: - PromptType type_; - // Permissions that are being requested (may not be all of an extension's - // permissions if only additional ones are being requested) - std::vector<string16> permissions_; - - // The extension or bundle being installed. - const extensions::Extension* extension_; - const extensions::BundleInstaller* bundle_; - - // The icon to be displayed. - gfx::Image icon_; - - // These fields are populated only when the prompt type is - // INLINE_INSTALL_PROMPT - // Already formatted to be locale-specific. - std::string localized_user_count_; - // Range is kMinExtensionRating to kMaxExtensionRating - double average_rating_; - int rating_count_; - }; + static ExtensionInstallUI* Create(Profile* profile); - static const int kMinExtensionRating = 0; - static const int kMaxExtensionRating = 5; - - class Delegate { - public: - // We call this method to signal that the installation should continue. - virtual void InstallUIProceed() = 0; - - // We call this method to signal that the installation should stop, with - // |user_initiated| true if the installation was stopped by the user. - virtual void InstallUIAbort(bool user_initiated) = 0; - - protected: - virtual ~Delegate() {} - }; + virtual ~ExtensionInstallUI(); - // Creates a dummy extension from the |manifest|, replacing the name and - // description with the localizations if provided. - static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay( - const base::DictionaryValue* manifest, - const std::string& id, - const std::string& localized_name, - const std::string& localized_description, - std::string* error); + // Called when an extension was installed. + virtual void OnInstallSuccess(const extensions::Extension* extension, + SkBitmap* icon) = 0; + // Called when an extension failed to install. + virtual void OnInstallFailure(const string16& error) = 0; - explicit ExtensionInstallUI(Profile* profile); - virtual ~ExtensionInstallUI(); + // Whether or not to show the default UI after completing the installation. + virtual void SetSkipPostInstallUI(bool skip_ui) = 0; // TODO(asargent) Normally we navigate to the new tab page when an app is // installed, but we're experimenting with instead showing a bubble when // an app is installed which points to the new tab button. This may become // the default behavior in the future. - void set_use_app_installed_bubble(bool use_bubble) { - use_app_installed_bubble_ = use_bubble; - } - - // Whether or not to show the default UI after completing the installation. - void set_skip_post_install_ui(bool skip_ui) { - skip_post_install_ui_ = skip_ui; - } - - // This is called by the bundle installer to verify whether the bundle - // should be installed. - // - // We *MUST* eventually call either Proceed() or Abort() on |delegate|. - virtual void ConfirmBundleInstall(extensions::BundleInstaller* bundle, - const ExtensionPermissionSet* permissions); - - // This is called by the inline installer to verify whether the inline - // install from the webstore should proceed. - // - // We *MUST* eventually call either Proceed() or Abort() on |delegate|. - virtual void ConfirmInlineInstall(Delegate* delegate, - const extensions::Extension* extension, - SkBitmap* icon, - const Prompt& prompt); - - // This is called by the installer to verify whether the installation from - // the webstore should proceed. - // - // We *MUST* eventually call either Proceed() or Abort() on |delegate|. - virtual void ConfirmWebstoreInstall(Delegate* delegate, - const extensions::Extension* extension, - const SkBitmap* icon); - - // This is called by the installer to verify whether the installation should - // proceed. This is declared virtual for testing. - // - // We *MUST* eventually call either Proceed() or Abort() on |delegate|. - virtual void ConfirmInstall(Delegate* delegate, - const extensions::Extension* extension); - - // This is called by the app handler launcher to verify whether the app - // should be re-enabled. This is declared virtual for testing. - // - // We *MUST* eventually call either Proceed() or Abort() on |delegate|. - virtual void ConfirmReEnable(Delegate* delegate, - const extensions::Extension* extension); - - // This is called by the extension permissions API to verify whether an - // extension may be granted additional permissions. - // - // We *MUST* eventually call either Proceed() or Abort() on |delegate|. - virtual void ConfirmPermissions(Delegate* delegate, - const extensions::Extension* extension, - const ExtensionPermissionSet* permissions); - - // Installation was successful. This is declared virtual for testing. - virtual void OnInstallSuccess(const extensions::Extension* extension, - SkBitmap* icon); - - // Installation failed. This is declared virtual for testing. - virtual void OnInstallFailure(const string16& error); - - // ImageLoadingTracker::Observer: - virtual void OnImageLoaded(const gfx::Image& image, - const std::string& extension_id, - int index) OVERRIDE; + virtual void SetUseAppInstalledBubble(bool use_bubble) = 0; // Opens apps UI and animates the app icon for the app with id |app_id|. static void OpenAppInstalledUI(Browser* browser, const std::string& app_id); - protected: - friend class extensions::ExtensionWebstorePrivateApiTest; - friend class WebstoreInlineInstallUnpackFailureTest; - // Disables showing UI (ErrorBox, etc.) for install failures. To be used only // in tests. static void DisableFailureUIForTests(); - private: - friend class GalleryInstallApiTestObserver; - - // Show an infobar for a newly-installed theme. previous_theme_id - // should be empty if the previous theme was the system/default - // theme. - static void ShowThemeInfoBar( - const std::string& previous_theme_id, bool previous_using_native_theme, - const extensions::Extension* new_theme, Profile* profile); - - // Sets the icon that will be used in any UI. If |icon| is NULL, or contains - // an empty bitmap, then a default icon will be used instead. - void SetIcon(const SkBitmap* icon); - - // Starts the process of showing a confirmation UI, which is split into two. - // 1) Set off a 'load icon' task. - // 2) Handle the load icon response and show the UI (OnImageLoaded). - void LoadImageIfNeeded(); - - // Shows the actual UI (the icon should already be loaded). - void ShowConfirmation(); - - // Returns the delegate to control the browser's info bar. This is - // within its own function due to its platform-specific nature. - static InfoBarDelegate* GetNewThemeInstalledInfoBarDelegate( - TabContentsWrapper* tab_contents, - const extensions::Extension* new_theme, - const std::string& previous_theme_id, - bool previous_using_native_theme); - - Profile* profile_; - MessageLoop* ui_loop_; - - // Used to undo theme installation. - std::string previous_theme_id_; - bool previous_using_native_theme_; - - // The extensions installation icon. - SkBitmap icon_; - - // The extension we are showing the UI for. - const extensions::Extension* extension_; - - // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT. - const extensions::BundleInstaller* bundle_; - - // The permissions being prompted for. - scoped_refptr<const ExtensionPermissionSet> permissions_; - - // The delegate we will call Proceed/Abort on after confirmation UI. - Delegate* delegate_; - - // A pre-filled prompt. - Prompt prompt_; - - // The type of prompt we are going to show. - PromptType prompt_type_; - - // Keeps track of extension images being loaded on the File thread for the - // purpose of showing the install UI. - ImageLoadingTracker tracker_; - - // Whether to show an installed bubble on app install, or use the default - // action of opening a new tab page. - bool use_app_installed_bubble_; - - // Whether or not to show the default UI after completing the installation. - bool skip_post_install_ui_; + protected: + ExtensionInstallUI(); }; #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_H_ diff --git a/chrome/browser/extensions/extension_install_ui_android.cc b/chrome/browser/extensions/extension_install_ui_android.cc new file mode 100644 index 0000000..f67c67d --- /dev/null +++ b/chrome/browser/extensions/extension_install_ui_android.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_install_ui.h" + +#include "base/logging.h" + +void ExtensionInstallUIAndroid::OnInstallSuccess(const Extension* extension, + SkBitmap* icon) { + NOTIMPLEMENTED(); +} + +void ExtensionInstallUIAndroid::OnInstallFailure(const string16& error) { + NOTIMPLEMENTED(); +} + +void ExtensionInstallUIAndroid::SetSkipPostInstallUI(bool skip_ui) { + NOTIMPLEMENTED(); +} + +// static +ExtensionInstallUI* ExtensionInstallUI::Create(Profile* profile) { + NOTIMPLEMENTED(); + return NULL; +} + +// static +void ExtensionInstallUI::OpenAppInstalledUI( + Browser* browser, const std::string& app_id) { + NOTIMPLEMENTED(); +} + +// static +void ExtensionInstallUI::DisableFailureUIForTests() { + NOTIMPLEMENTED(); +} diff --git a/chrome/browser/extensions/extension_install_ui_android.h b/chrome/browser/extensions/extension_install_ui_android.h new file mode 100644 index 0000000..eb207ad --- /dev/null +++ b/chrome/browser/extensions/extension_install_ui_android.h @@ -0,0 +1,29 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_ANDROID_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_ANDROID_H_ +#pragma once + +#include "chrome/browser/extensions/extension_install_ui.h" + +class InfoBarDelegate; +class TabContentsWrapper; + +class ExtensionInstallUIAndroid : public ExtensionInstallUI { + public: + ExtensionInstallUIAndroid(); + virtual ~ExtensionInstallUIAndroid(); + + // ExtensionInstallUI implementation: + virtual void OnInstallSuccess(const extensions::Extension* extension, + SkBitmap* icon); + virtual void OnInstallFailure(const string16& error); + virtual void SetSkipPostInstallUI(bool skip_ui); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(ExtensionInstallUIAndroid); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_ANDROID_H_ diff --git a/chrome/browser/extensions/extension_install_ui_default.cc b/chrome/browser/extensions/extension_install_ui_default.cc new file mode 100644 index 0000000..885e85e --- /dev/null +++ b/chrome/browser/extensions/extension_install_ui_default.cc @@ -0,0 +1,214 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_install_ui_default.h" + +#include "base/command_line.h" +#include "chrome/browser/extensions/extension_install_prompt.h" +#include "chrome/browser/extensions/theme_installed_infobar_delegate.h" +#include "chrome/browser/infobars/infobar_tab_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/themes/theme_service_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/simple_message_box.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/browser/ui/webui/ntp/new_tab_ui.h" +#include "chrome/common/chrome_notification_types.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/url_constants.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_service.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" + +#if defined(USE_ASH) +#include "ash/shell.h" +#endif + +using content::BrowserThread; +using content::WebContents; +using extensions::Extension; + +namespace { + +bool disable_failure_ui_for_tests = false; + +} // namespace + +ExtensionInstallUIDefault::ExtensionInstallUIDefault(Profile* profile) + : profile_(profile), + skip_post_install_ui_(false), + previous_using_native_theme_(false), + use_app_installed_bubble_(false) { + // Remember the current theme in case the user presses undo. + if (profile) { + const Extension* previous_theme = + ThemeServiceFactory::GetThemeForProfile(profile); + if (previous_theme) + previous_theme_id_ = previous_theme->id(); + previous_using_native_theme_ = + ThemeServiceFactory::GetForProfile(profile)->UsingNativeTheme(); + } +} + +ExtensionInstallUIDefault::~ExtensionInstallUIDefault() { +} + +void ExtensionInstallUIDefault::OnInstallSuccess(const Extension* extension, + SkBitmap* icon) { + if (skip_post_install_ui_) + return; + + if (extension->is_theme()) { + ShowThemeInfoBar(previous_theme_id_, previous_using_native_theme_, + extension, profile_); + return; + } + + // Extensions aren't enabled by default in incognito so we confirm + // the install in a normal window. + Profile* current_profile = profile_->GetOriginalProfile(); + Browser* browser = browser::FindOrCreateTabbedBrowser(current_profile); + if (browser->tab_count() == 0) + browser->AddBlankTab(true); + browser->window()->Show(); + + bool use_bubble_for_apps = false; + +#if defined(TOOLKIT_VIEWS) + CommandLine* cmdline = CommandLine::ForCurrentProcess(); + use_bubble_for_apps = (use_app_installed_bubble_ || + cmdline->HasSwitch(switches::kAppsNewInstallBubble)); +#endif + + if (extension->is_app() && !use_bubble_for_apps) { + ExtensionInstallUI::OpenAppInstalledUI(browser, extension->id()); + return; + } + + browser::ShowExtensionInstalledBubble(extension, browser, *icon, + current_profile); +} + +void ExtensionInstallUIDefault::OnInstallFailure(const string16& error) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (disable_failure_ui_for_tests || skip_post_install_ui_) + return; + + Browser* browser = browser::FindLastActiveWithProfile(profile_); + browser::ShowMessageBox(browser ? browser->window()->GetNativeWindow() : NULL, + l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_FAILURE_TITLE), error, + browser::MESSAGE_BOX_TYPE_WARNING); +} + +void ExtensionInstallUIDefault::SetSkipPostInstallUI(bool skip_ui) { + skip_post_install_ui_ = skip_ui; +} + +void ExtensionInstallUIDefault::SetUseAppInstalledBubble(bool use_bubble) { + use_app_installed_bubble_ = use_bubble; +} + +// static +void ExtensionInstallUIDefault::ShowThemeInfoBar( + const std::string& previous_theme_id, bool previous_using_native_theme, + const Extension* new_theme, Profile* profile) { + if (!new_theme->is_theme()) + return; + + // Get last active tabbed browser of profile. + Browser* browser = browser::FindTabbedBrowser(profile, true); + if (!browser) + return; + + TabContentsWrapper* tab_contents = browser->GetSelectedTabContentsWrapper(); + if (!tab_contents) + return; + InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); + + // First find any previous theme preview infobars. + InfoBarDelegate* old_delegate = NULL; + for (size_t i = 0; i < infobar_helper->infobar_count(); ++i) { + InfoBarDelegate* delegate = infobar_helper->GetInfoBarDelegateAt(i); + ThemeInstalledInfoBarDelegate* theme_infobar = + delegate->AsThemePreviewInfobarDelegate(); + if (theme_infobar) { + // If the user installed the same theme twice, ignore the second install + // and keep the first install info bar, so that they can easily undo to + // get back the previous theme. + if (theme_infobar->MatchesTheme(new_theme)) + return; + old_delegate = delegate; + break; + } + } + + // Then either replace that old one or add a new one. + InfoBarDelegate* new_delegate = GetNewThemeInstalledInfoBarDelegate( + tab_contents, new_theme, previous_theme_id, previous_using_native_theme); + + if (old_delegate) + infobar_helper->ReplaceInfoBar(old_delegate, new_delegate); + else + infobar_helper->AddInfoBar(new_delegate); +} + +InfoBarDelegate* ExtensionInstallUIDefault::GetNewThemeInstalledInfoBarDelegate( + TabContentsWrapper* tab_contents, + const Extension* new_theme, + const std::string& previous_theme_id, + bool previous_using_native_theme) { + Profile* profile = tab_contents->profile(); + return new ThemeInstalledInfoBarDelegate( + tab_contents->infobar_tab_helper(), + profile->GetExtensionService(), + ThemeServiceFactory::GetForProfile(profile), + new_theme, + previous_theme_id, + previous_using_native_theme); +} + +// static +ExtensionInstallUI* ExtensionInstallUI::Create(Profile* profile) { + return new ExtensionInstallUIDefault(profile); +} + +// static +void ExtensionInstallUI::OpenAppInstalledUI(Browser* browser, + const std::string& app_id) { + if (NewTabUI::ShouldShowApps()) { + browser::NavigateParams params = browser->GetSingletonTabNavigateParams( + GURL(chrome::kChromeUINewTabURL)); + browser::Navigate(¶ms); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_APP_INSTALLED_TO_NTP, + content::Source<WebContents>(params.target_contents->web_contents()), + content::Details<const std::string>(&app_id)); + } else { +#if defined(USE_ASH) + ash::Shell::GetInstance()->ToggleAppList(); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST, + content::Source<Profile>(browser->profile()), + content::Details<const std::string>(&app_id)); +#else + NOTREACHED(); +#endif + } +} + +// static +void ExtensionInstallUI::DisableFailureUIForTests() { + disable_failure_ui_for_tests = true; +} diff --git a/chrome/browser/extensions/extension_install_ui_default.h b/chrome/browser/extensions/extension_install_ui_default.h new file mode 100644 index 0000000..5e37d06 --- /dev/null +++ b/chrome/browser/extensions/extension_install_ui_default.h @@ -0,0 +1,59 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_DEFAULT_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_DEFAULT_H_ +#pragma once + +#include "chrome/browser/extensions/extension_install_ui.h" + +class InfoBarDelegate; +class TabContents; +typedef TabContents TabContentsWrapper; + +class ExtensionInstallUIDefault : public ExtensionInstallUI { + public: + explicit ExtensionInstallUIDefault(Profile* profile); + virtual ~ExtensionInstallUIDefault(); + + // ExtensionInstallUI implementation: + virtual void OnInstallSuccess(const extensions::Extension* extension, + SkBitmap* icon) OVERRIDE; + virtual void OnInstallFailure(const string16& error) OVERRIDE; + virtual void SetSkipPostInstallUI(bool skip_ui) OVERRIDE; + virtual void SetUseAppInstalledBubble(bool use_bubble) OVERRIDE; + + private: + // Shows an infobar for a newly-installed theme. previous_theme_id should be + // empty if the previous theme was the system/default theme. + static void ShowThemeInfoBar(const std::string& previous_theme_id, + bool previous_using_native_theme, + const extensions::Extension* new_theme, + Profile* profile); + + // Returns the delegate to control the browser's info bar. This is + // within its own function due to its platform-specific nature. + static InfoBarDelegate* GetNewThemeInstalledInfoBarDelegate( + TabContentsWrapper* tab_contents, + const extensions::Extension* new_theme, + const std::string& previous_theme_id, + bool previous_using_native_theme); + + Profile* profile_; + + // Whether or not to show the default UI after completing the installation. + bool skip_post_install_ui_; + + // Used to undo theme installation. + std::string previous_theme_id_; + bool previous_using_native_theme_; + + // Whether to show an installed bubble on app install, or use the default + // action of opening a new tab page. + bool use_app_installed_bubble_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(ExtensionInstallUIDefault); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_DEFAULT_H_ diff --git a/chrome/browser/extensions/extension_management_api.cc b/chrome/browser/extensions/extension_management_api.cc index 3f508d2..ac85975 100644 --- a/chrome/browser/extensions/extension_management_api.cc +++ b/chrome/browser/extensions/extension_management_api.cc @@ -407,8 +407,8 @@ bool SetEnabledFunction::RunImpl() { return false; } AddRef(); // Matched in InstallUIProceed/InstallUIAbort - install_ui_.reset(new ExtensionInstallUI(profile_)); - install_ui_->ConfirmReEnable(this, extension); + install_prompt_.reset(new ExtensionInstallPrompt(profile_)); + install_prompt_->ConfirmReEnable(this, extension); return true; } service()->EnableExtension(extension_id_); diff --git a/chrome/browser/extensions/extension_management_api.h b/chrome/browser/extensions/extension_management_api.h index 69b04a6..d30504a 100644 --- a/chrome/browser/extensions/extension_management_api.h +++ b/chrome/browser/extensions/extension_management_api.h @@ -8,7 +8,7 @@ #include "base/compiler_specific.h" #include "chrome/browser/extensions/extension_function.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -91,7 +91,7 @@ class LaunchAppFunction : public ExtensionManagementFunction { }; class SetEnabledFunction : public AsyncExtensionManagementFunction, - public ExtensionInstallUI::Delegate { + public ExtensionInstallPrompt::Delegate { public: DECLARE_EXTENSION_FUNCTION_NAME("management.setEnabled"); @@ -103,7 +103,7 @@ class SetEnabledFunction : public AsyncExtensionManagementFunction, // ExtensionFunction: virtual bool RunImpl() OVERRIDE; - // ExtensionInstallUI::Delegate. + // ExtensionInstallPrompt::Delegate. virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -111,7 +111,7 @@ class SetEnabledFunction : public AsyncExtensionManagementFunction, std::string extension_id_; // Used for prompting to re-enable items with permissions escalation updates. - scoped_ptr<ExtensionInstallUI> install_ui_; + scoped_ptr<ExtensionInstallPrompt> install_prompt_; }; class UninstallFunction : public AsyncExtensionManagementFunction, diff --git a/chrome/browser/extensions/extension_navigation_observer.cc b/chrome/browser/extensions/extension_navigation_observer.cc index 2cb1bc6..d54eb45 100644 --- a/chrome/browser/extensions/extension_navigation_observer.cc +++ b/chrome/browser/extensions/extension_navigation_observer.cc @@ -73,8 +73,8 @@ void ExtensionNavigationObserver::PromptToEnableExtensionIfNecessary( in_progress_prompt_extension_id_ = extension->id(); in_progress_prompt_navigation_controller_ = nav_controller; - extension_install_ui_.reset(new ExtensionInstallUI(profile_)); - extension_install_ui_->ConfirmReEnable(this, extension); + extension_install_prompt_.reset(new ExtensionInstallPrompt(profile_)); + extension_install_prompt_->ConfirmReEnable(this, extension); } } @@ -89,7 +89,7 @@ void ExtensionNavigationObserver::InstallUIProceed() { in_progress_prompt_extension_id_ = ""; in_progress_prompt_navigation_controller_ = NULL; - extension_install_ui_.reset(); + extension_install_prompt_.reset(); // Grant permissions, re-enable the extension, and then reload the tab. extension_service->GrantPermissionsAndEnableExtension(extension); @@ -103,7 +103,7 @@ void ExtensionNavigationObserver::InstallUIAbort(bool user_initiated) { in_progress_prompt_extension_id_ = ""; in_progress_prompt_navigation_controller_ = NULL; - extension_install_ui_.reset(); + extension_install_prompt_.reset(); std::string histogram_name = user_initiated ? "Extensions.Permissions_ReEnableCancel" : diff --git a/chrome/browser/extensions/extension_navigation_observer.h b/chrome/browser/extensions/extension_navigation_observer.h index 5734e50..00255e9 100644 --- a/chrome/browser/extensions/extension_navigation_observer.h +++ b/chrome/browser/extensions/extension_navigation_observer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,7 +10,7 @@ #include <string> #include "base/memory/scoped_ptr.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "content/public/browser/notification_registrar.h" class Profile; @@ -23,7 +23,7 @@ class NavigationController; // user navigates into an extension that has been disabled due to a permission // increase, it prompts the user to accept the new permissions and re-enables // the extension. -class ExtensionNavigationObserver : public ExtensionInstallUI::Delegate, +class ExtensionNavigationObserver : public ExtensionInstallPrompt::Delegate, public content::NotificationObserver { public: explicit ExtensionNavigationObserver(Profile* profile); @@ -43,7 +43,7 @@ class ExtensionNavigationObserver : public ExtensionInstallUI::Delegate, void PromptToEnableExtensionIfNecessary( content::NavigationController* nav_controller); - // ExtensionInstallUI::Delegate callbacks used for the permissions prompt. + // ExtensionInstallPrompt::Delegate callbacks used for the permissions prompt. virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -52,7 +52,7 @@ class ExtensionNavigationObserver : public ExtensionInstallUI::Delegate, Profile* profile_; // The UI used to confirm enabling extensions. - scoped_ptr<ExtensionInstallUI> extension_install_ui_; + scoped_ptr<ExtensionInstallPrompt> extension_install_prompt_; // The data we keep track of when prompting to enable extensions. std::string in_progress_prompt_extension_id_; diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 3d5d054..9f451a2 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -575,9 +575,9 @@ bool ExtensionService::UpdateExtension( // We want a silent install only for non-pending extensions and // pending extensions that have install_silently set. - ExtensionInstallUI* client = + ExtensionInstallPrompt* client = (!is_pending_extension || pending_extension_info.install_silently()) ? - NULL : new ExtensionInstallUI(profile_); + NULL : new ExtensionInstallPrompt(profile_); scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, client)); installer->set_expected_id(id); diff --git a/chrome/browser/extensions/unpacked_installer.cc b/chrome/browser/extensions/unpacked_installer.cc index 22b0714..b73d7bc 100644 --- a/chrome/browser/extensions/unpacked_installer.cc +++ b/chrome/browser/extensions/unpacked_installer.cc @@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/file_util.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/permissions_updater.h" @@ -23,8 +23,8 @@ namespace { const char kUnpackedExtensionsBlacklistedError[] = "Loading of unpacked extensions is disabled by the administrator."; -// Manages an ExtensionInstallUI for a particular extension. -class SimpleExtensionLoadPrompt : public ExtensionInstallUI::Delegate { +// Manages an ExtensionInstallPrompt for a particular extension. +class SimpleExtensionLoadPrompt : public ExtensionInstallPrompt::Delegate { public: SimpleExtensionLoadPrompt(Profile* profile, base::WeakPtr<ExtensionService> extension_service, @@ -39,7 +39,7 @@ class SimpleExtensionLoadPrompt : public ExtensionInstallUI::Delegate { private: base::WeakPtr<ExtensionService> service_weak_; - scoped_ptr<ExtensionInstallUI> install_ui_; + scoped_ptr<ExtensionInstallPrompt> install_ui_; scoped_refptr<const Extension> extension_; }; @@ -48,7 +48,7 @@ SimpleExtensionLoadPrompt::SimpleExtensionLoadPrompt( base::WeakPtr<ExtensionService> extension_service, const Extension* extension) : service_weak_(extension_service), - install_ui_(new ExtensionInstallUI(profile)), + install_ui_(new ExtensionInstallPrompt(profile)), extension_(extension) { } @@ -231,7 +231,7 @@ void UnpackedInstaller::OnLoaded( service_weak_, extension); prompt->ShowPrompt(); - return; // continues in SimpleExtensionLoadPrompt::InstallUI* + return; // continues in SimpleExtensionLoadPrompt::InstallPrompt* } PermissionsUpdater perms_updater(service_weak_->profile()); diff --git a/chrome/browser/extensions/webstore_inline_installer.cc b/chrome/browser/extensions/webstore_inline_installer.cc index 9155f3f..8d085e8 100644 --- a/chrome/browser/extensions/webstore_inline_installer.cc +++ b/chrome/browser/extensions/webstore_inline_installer.cc @@ -260,8 +260,8 @@ void WebstoreInlineInstaller::OnWebstoreResponseParseSuccess( return; } - if (average_rating_ < ExtensionInstallUI::kMinExtensionRating || - average_rating_ >ExtensionInstallUI::kMaxExtensionRating) { + if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating || + average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) { CompleteInstall(kInvalidWebstoreResponseError); return; } @@ -344,12 +344,13 @@ void WebstoreInlineInstaller::OnWebstoreParseSuccess( Profile* profile = Profile::FromBrowserContext( web_contents()->GetBrowserContext()); - ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INLINE_INSTALL_PROMPT); + ExtensionInstallPrompt::Prompt prompt( + ExtensionInstallPrompt::INLINE_INSTALL_PROMPT); prompt.SetInlineInstallWebstoreData(localized_user_count_, average_rating_, rating_count_); std::string error; - dummy_extension_ = ExtensionInstallUI::GetLocalizedExtensionForDisplay( + dummy_extension_ = ExtensionInstallPrompt::GetLocalizedExtensionForDisplay( manifest, id_, localized_name_, localized_description_, &error); if (!dummy_extension_) { OnWebstoreParseFailure(id_, WebstoreInstallHelper::Delegate::MANIFEST_ERROR, @@ -357,7 +358,7 @@ void WebstoreInlineInstaller::OnWebstoreParseSuccess( return; } - install_ui_.reset(new ExtensionInstallUI(profile)); + install_ui_.reset(new ExtensionInstallPrompt(profile)); install_ui_->ConfirmInlineInstall(this, dummy_extension_, &icon_, prompt); // Control flow finishes up in InstallUIProceed or InstallUIAbort. } diff --git a/chrome/browser/extensions/webstore_inline_installer.h b/chrome/browser/extensions/webstore_inline_installer.h index 4076209..76ed3ab 100644 --- a/chrome/browser/extensions/webstore_inline_installer.h +++ b/chrome/browser/extensions/webstore_inline_installer.h @@ -11,7 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/webstore_install_helper.h" #include "chrome/browser/extensions/webstore_installer.h" #include "content/public/browser/web_contents_observer.h" @@ -37,7 +37,7 @@ class URLFetcher; // request is attached to goes away. class WebstoreInlineInstaller : public base::RefCountedThreadSafe<WebstoreInlineInstaller>, - public ExtensionInstallUI::Delegate, + public ExtensionInstallPrompt::Delegate, public content::WebContentsObserver, public net::URLFetcherDelegate, public WebstoreInstaller::Delegate, @@ -97,7 +97,7 @@ class WebstoreInlineInstaller InstallHelperResultCode result_code, const std::string& error_message) OVERRIDE; - // ExtensionInstallUI::Delegate interface implementation. + // ExtensionInstallPrompt::Delegate interface implementation. virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -122,7 +122,7 @@ class WebstoreInlineInstaller std::string id_; GURL requestor_url_; Delegate* delegate_; - scoped_ptr<ExtensionInstallUI> install_ui_; + scoped_ptr<ExtensionInstallPrompt> install_ui_; // For fetching webstore JSON data. scoped_ptr<net::URLFetcher> webstore_data_url_fetcher_; diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc index 1485d8f..bf75f63 100644 --- a/chrome/browser/infobars/infobars_browsertest.cc +++ b/chrome/browser/infobars/infobars_browsertest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/extensions/crx_installer.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/infobars/infobar_tab_helper.h" #include "chrome/browser/themes/theme_service.h" @@ -38,7 +38,7 @@ class InfoBarsTest : public InProcessBrowserTest { chrome::NOTIFICATION_EXTENSION_LOADED, content::NotificationService::AllSources()); - ExtensionInstallUI* client = new ExtensionInstallUI(profile); + ExtensionInstallPrompt* client = new ExtensionInstallPrompt(profile); scoped_refptr<CrxInstaller> installer( CrxInstaller::Create(service, client)); installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION); diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 630c27c..a3ec1d0e 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -3793,7 +3793,7 @@ void Browser::OnInstallApplication(TabContents* source, scoped_refptr<CrxInstaller> installer(CrxInstaller::Create( extension_service, extension_service->show_extensions_prompts() ? - new ExtensionInstallUI(profile()) : NULL)); + new ExtensionInstallPrompt(profile()) : NULL)); installer->InstallWebApp(web_app); } diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h index 0ac16b0..9c8429f 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h +++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h @@ -12,13 +12,13 @@ #include "base/memory/scoped_ptr.h" #include "base/string16.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "ui/gfx/image/image_skia.h" class Profile; // Displays the extension or bundle install prompt, and notifies the -// ExtensionInstallUI::Delegate of success or failure. +// ExtensionInstallPrompt::Delegate of success or failure. @interface ExtensionInstallDialogController : NSWindowController { @private IBOutlet NSImageView* iconView_; @@ -39,8 +39,8 @@ class Profile; NSWindow* parentWindow_; // weak Profile* profile_; // weak - ExtensionInstallUI::Delegate* delegate_; // weak - scoped_ptr<ExtensionInstallUI::Prompt> prompt_; + ExtensionInstallPrompt::Delegate* delegate_; // weak + scoped_ptr<ExtensionInstallPrompt::Prompt> prompt_; } // For unit test use only @@ -58,8 +58,8 @@ class Profile; - (id)initWithParentWindow:(NSWindow*)window profile:(Profile*)profile - delegate:(ExtensionInstallUI::Delegate*)delegate - prompt:(const ExtensionInstallUI::Prompt&)prompt; + delegate:(ExtensionInstallPrompt::Delegate*)delegate + prompt:(const ExtensionInstallPrompt::Prompt&)prompt; - (void)runAsModalSheet; - (IBAction)storeLinkClicked:(id)sender; // Callback for "View details" link. - (IBAction)cancel:(id)sender; diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm index a3248d6..0561ca2 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm @@ -90,18 +90,18 @@ void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { - (id)initWithParentWindow:(NSWindow*)window profile:(Profile*)profile - delegate:(ExtensionInstallUI::Delegate*)delegate - prompt:(const ExtensionInstallUI::Prompt&)prompt { + delegate:(ExtensionInstallPrompt::Delegate*)delegate + prompt:(const ExtensionInstallPrompt::Prompt&)prompt { NSString* nibpath = nil; // We use a different XIB in the case of bundle installs, inline installs or // no permission warnings. These are laid out nicely for the data they // display. - if (prompt.type() == ExtensionInstallUI::BUNDLE_INSTALL_PROMPT) { + if (prompt.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT) { nibpath = [base::mac::FrameworkBundle() pathForResource:@"ExtensionInstallPromptBundle" ofType:@"nib"]; - } else if (prompt.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT) { + } else if (prompt.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT) { nibpath = [base::mac::FrameworkBundle() pathForResource:@"ExtensionInstallPromptInline" ofType:@"nib"]; @@ -119,7 +119,7 @@ void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { parentWindow_ = window; profile_ = profile; delegate_ = delegate; - prompt_.reset(new ExtensionInstallUI::Prompt(prompt)); + prompt_.reset(new ExtensionInstallPrompt::Prompt(prompt)); } return self; } @@ -290,11 +290,11 @@ void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { } - (BOOL)isBundleInstall { - return prompt_->type() == ExtensionInstallUI::BUNDLE_INSTALL_PROMPT; + return prompt_->type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT; } - (BOOL)isInlineInstall { - return prompt_->type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT; + return prompt_->type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT; } - (void)appendRatingStar:(const gfx::ImageSkia*)skiaImage { @@ -319,8 +319,8 @@ void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { void ShowExtensionInstallDialogImpl( Profile* profile, - ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt) { + ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt) { Browser* browser = browser::FindLastActiveWithProfile(profile); if (!browser) { delegate->InstallUIAbort(false); diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm index 167eff5..4ddb9db 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm @@ -13,7 +13,7 @@ #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#import "chrome/browser/extensions/extension_install_ui.h" +#import "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/ui/cocoa/cocoa_profile_test.h" #import "chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h" #include "chrome/common/chrome_paths.h" @@ -78,15 +78,16 @@ public: }; -// Mock out the ExtensionInstallUI::Delegate interface so we can ensure the +// Mock out the ExtensionInstallPrompt::Delegate interface so we can ensure the // dialog is interacting with it correctly. -class MockExtensionInstallUIDelegate : public ExtensionInstallUI::Delegate { +class MockExtensionInstallPromptDelegate + : public ExtensionInstallPrompt::Delegate { public: - MockExtensionInstallUIDelegate() + MockExtensionInstallPromptDelegate() : proceed_count_(0), abort_count_(0) {} - // ExtensionInstallUI::Delegate overrides. + // ExtensionInstallPrompt::Delegate overrides. virtual void InstallUIProceed() OVERRIDE { proceed_count_++; } @@ -106,9 +107,9 @@ class MockExtensionInstallUIDelegate : public ExtensionInstallUI::Delegate { // Test that we can load the two kinds of prompts correctly, that the outlets // are hooked up, and that the dialog calls cancel when cancel is pressed. TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { - MockExtensionInstallUIDelegate delegate; + MockExtensionInstallPromptDelegate delegate; - ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INSTALL_PROMPT); + ExtensionInstallPrompt::Prompt prompt(ExtensionInstallPrompt::INSTALL_PROMPT); std::vector<string16> permissions; permissions.push_back(UTF8ToUTF16("warning 1")); prompt.SetPermissions(permissions); @@ -161,9 +162,10 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalOK) { - MockExtensionInstallUIDelegate delegate; + MockExtensionInstallPromptDelegate delegate; - ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INSTALL_PROMPT); + ExtensionInstallPrompt::Prompt prompt( + ExtensionInstallPrompt::INSTALL_PROMPT); std::vector<string16> permissions; permissions.push_back(UTF8ToUTF16("warning 1")); prompt.SetPermissions(permissions); @@ -187,19 +189,19 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalOK) { // Test that controls get repositioned when there are two warnings vs one // warning. TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { - MockExtensionInstallUIDelegate delegate1; - MockExtensionInstallUIDelegate delegate2; + MockExtensionInstallPromptDelegate delegate1; + MockExtensionInstallPromptDelegate delegate2; - ExtensionInstallUI::Prompt one_warning_prompt( - ExtensionInstallUI::INSTALL_PROMPT); + ExtensionInstallPrompt::Prompt one_warning_prompt( + ExtensionInstallPrompt::INSTALL_PROMPT); std::vector<string16> permissions; permissions.push_back(UTF8ToUTF16("warning 1")); one_warning_prompt.SetPermissions(permissions); one_warning_prompt.set_extension(extension_.get()); one_warning_prompt.set_icon(icon_); - ExtensionInstallUI::Prompt two_warnings_prompt( - ExtensionInstallUI::INSTALL_PROMPT); + ExtensionInstallPrompt::Prompt two_warnings_prompt( + ExtensionInstallPrompt::INSTALL_PROMPT); permissions.push_back(UTF8ToUTF16("warning 2")); two_warnings_prompt.SetPermissions(permissions); two_warnings_prompt.set_extension(extension_.get()); @@ -242,11 +244,11 @@ TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { // Test that we can load the skinny prompt correctly, and that the outlets are // are hooked up. TEST_F(ExtensionInstallDialogControllerTest, BasicsSkinny) { - MockExtensionInstallUIDelegate delegate; + MockExtensionInstallPromptDelegate delegate; // No warnings should trigger skinny prompt. - ExtensionInstallUI::Prompt no_warnings_prompt( - ExtensionInstallUI::INSTALL_PROMPT); + ExtensionInstallPrompt::Prompt no_warnings_prompt( + ExtensionInstallPrompt::INSTALL_PROMPT); no_warnings_prompt.set_extension(extension_.get()); no_warnings_prompt.set_icon(icon_); @@ -287,11 +289,11 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsSkinny) { // Test that we can load the inline prompt correctly, and that the outlets are // are hooked up. TEST_F(ExtensionInstallDialogControllerTest, BasicsInline) { - MockExtensionInstallUIDelegate delegate; + MockExtensionInstallPromptDelegate delegate; // No warnings should trigger skinny prompt. - ExtensionInstallUI::Prompt inline_prompt( - ExtensionInstallUI::INLINE_INSTALL_PROMPT); + ExtensionInstallPrompt::Prompt inline_prompt( + ExtensionInstallPrompt::INLINE_INSTALL_PROMPT); inline_prompt.SetInlineInstallWebstoreData("1,000", 3.5, 200); inline_prompt.set_extension(extension_.get()); inline_prompt.set_icon(icon_); diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm index 1869dbf..4dedebd 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm @@ -113,7 +113,7 @@ class ExtensionLoadedNotificationObserver !extension->page_action()->default_icon_path().empty()) { type_ = extension_installed_bubble::kPageAction; } else { - NOTREACHED(); // kGeneric installs handled in the extension_install_ui. + NOTREACHED(); // kGeneric installs handled in extension_install_prompt. } if (type_ == extension_installed_bubble::kBundle) { diff --git a/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc b/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc index 49caddb..3df8f3a 100644 --- a/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc @@ -53,35 +53,35 @@ void AddResourceIcon(const gfx::ImageSkia* icon, void* data) { namespace browser { // Displays the dialog when constructed, deletes itself when dialog is -// dismissed. Success/failure is passed back through the ExtensionInstallUI:: -// Delegate instance. +// dismissed. Success/failure is passed back through the +// ExtensionInstallPrompt::Delegate instance. class ExtensionInstallDialog { public: ExtensionInstallDialog(GtkWindow* parent, - ExtensionInstallUI::Delegate *delegate, - const ExtensionInstallUI::Prompt& prompt); + ExtensionInstallPrompt::Delegate *delegate, + const ExtensionInstallPrompt::Prompt& prompt); private: ~ExtensionInstallDialog(); CHROMEGTK_CALLBACK_1(ExtensionInstallDialog, void, OnResponse, int); CHROMEGTK_CALLBACK_0(ExtensionInstallDialog, void, OnStoreLinkClick); - ExtensionInstallUI::Delegate* delegate_; + ExtensionInstallPrompt::Delegate* delegate_; std::string extension_id_; // Set for INLINE_INSTALL_PROMPT. GtkWidget* dialog_; }; ExtensionInstallDialog::ExtensionInstallDialog( GtkWindow* parent, - ExtensionInstallUI::Delegate *delegate, - const ExtensionInstallUI::Prompt& prompt) + ExtensionInstallPrompt::Delegate *delegate, + const ExtensionInstallPrompt::Prompt& prompt) : delegate_(delegate), dialog_(NULL) { bool show_permissions = prompt.GetPermissionCount() > 0; bool is_inline_install = - prompt.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT; + prompt.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT; bool is_bundle_install = - prompt.type() == ExtensionInstallUI::BUNDLE_INSTALL_PROMPT; + prompt.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT; if (is_inline_install) extension_id_ = prompt.extension()->id(); @@ -268,8 +268,8 @@ void ExtensionInstallDialog::OnStoreLinkClick(GtkWidget* sender) { void ShowExtensionInstallDialogImpl( Profile* profile, - ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt) { + ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt) { Browser* browser = browser::FindLastActiveWithProfile(profile); if (!browser) { delegate->InstallUIAbort(false); diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index 605d9ce..9391873 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc @@ -75,8 +75,8 @@ void AddResourceIcon(const gfx::ImageSkia* skia_image, void* data) { class ExtensionInstallDialogView : public views::DialogDelegateView, public views::LinkListener { public: - ExtensionInstallDialogView(ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt); + ExtensionInstallDialogView(ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt); virtual ~ExtensionInstallDialogView(); private: @@ -95,22 +95,22 @@ class ExtensionInstallDialogView : public views::DialogDelegateView, virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; bool is_inline_install() { - return prompt_.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT; + return prompt_.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT; } bool is_bundle_install() { - return prompt_.type() == ExtensionInstallUI::BUNDLE_INSTALL_PROMPT; + return prompt_.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT; } - ExtensionInstallUI::Delegate* delegate_; - ExtensionInstallUI::Prompt prompt_; + ExtensionInstallPrompt::Delegate* delegate_; + ExtensionInstallPrompt::Prompt prompt_; DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView); }; ExtensionInstallDialogView::ExtensionInstallDialogView( - ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt) + ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt) : delegate_(delegate), prompt_(prompt) { // Possible grid layouts: @@ -351,8 +351,8 @@ void ExtensionInstallDialogView::LinkClicked(views::Link* source, void ShowExtensionInstallDialogImpl( Profile* profile, - ExtensionInstallUI::Delegate* delegate, - const ExtensionInstallUI::Prompt& prompt) { + ExtensionInstallPrompt::Delegate* delegate, + const ExtensionInstallPrompt::Prompt& prompt) { Browser* browser = browser::FindLastActiveWithProfile(profile); if (!browser) { delegate->InstallUIAbort(false); diff --git a/chrome/browser/ui/webui/extensions/install_extension_handler.cc b/chrome/browser/ui/webui/extensions/install_extension_handler.cc index 3c5507b..07c7c0a 100644 --- a/chrome/browser/ui/webui/extensions/install_extension_handler.cc +++ b/chrome/browser/ui/webui/extensions/install_extension_handler.cc @@ -8,7 +8,7 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/extensions/crx_installer.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/profiles/profile.h" @@ -83,7 +83,7 @@ void InstallExtensionHandler::HandleInstallMessage(const ListValue* args) { scoped_refptr<CrxInstaller> crx_installer( CrxInstaller::Create( ExtensionSystem::Get(profile)->extension_service(), - new ExtensionInstallUI(profile))); + new ExtensionInstallPrompt(profile))); crx_installer->set_allow_off_store_install(true); const bool kCaseSensitive = false; diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc index e17090c..ce247a1 100644 --- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc +++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc @@ -913,7 +913,7 @@ void AppLauncherHandler::PromptToEnableApp(const std::string& extension_id) { return; // Only one prompt at a time. extension_id_prompting_ = extension_id; - GetExtensionInstallUI()->ConfirmReEnable(this, extension); + GetExtensionInstallPrompt()->ConfirmReEnable(this, extension); } void AppLauncherHandler::ExtensionUninstallAccepted() { @@ -981,10 +981,10 @@ ExtensionUninstallDialog* AppLauncherHandler::GetExtensionUninstallDialog() { return extension_uninstall_dialog_.get(); } -ExtensionInstallUI* AppLauncherHandler::GetExtensionInstallUI() { +ExtensionInstallPrompt* AppLauncherHandler::GetExtensionInstallPrompt() { if (!extension_install_ui_.get()) { extension_install_ui_.reset( - new ExtensionInstallUI(Profile::FromWebUI(web_ui()))); + new ExtensionInstallPrompt(Profile::FromWebUI(web_ui()))); } return extension_install_ui_.get(); } diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chrome/browser/ui/webui/ntp/app_launcher_handler.h index 88494c5..6459933 100644 --- a/chrome/browser/ui/webui/ntp/app_launcher_handler.h +++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.h @@ -10,7 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "chrome/browser/cancelable_request.h" -#include "chrome/browser/extensions/extension_install_ui.h" +#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/favicon/favicon_service.h" #include "chrome/browser/prefs/pref_change_registrar.h" @@ -29,7 +29,7 @@ class Profile; // The handler for Javascript messages related to the "apps" view. class AppLauncherHandler : public content::WebUIMessageHandler, public ExtensionUninstallDialog::Delegate, - public ExtensionInstallUI::Delegate, + public ExtensionInstallPrompt::Delegate, public content::NotificationObserver { public: explicit AppLauncherHandler(ExtensionService* extension_service); @@ -143,7 +143,7 @@ class AppLauncherHandler : public content::WebUIMessageHandler, virtual void ExtensionUninstallAccepted() OVERRIDE; virtual void ExtensionUninstallCanceled() OVERRIDE; - // ExtensionInstallUI::Delegate: + // ExtensionInstallPrompt::Delegate: virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; @@ -151,9 +151,9 @@ class AppLauncherHandler : public content::WebUIMessageHandler, // needed. ExtensionUninstallDialog* GetExtensionUninstallDialog(); - // Returns the ExtensionInstallUI object for this class, creating it if + // Returns the ExtensionInstallPrompt object for this class, creating it if // needed. - ExtensionInstallUI* GetExtensionInstallUI(); + ExtensionInstallPrompt* GetExtensionInstallPrompt(); // Helper that uninstalls all the default apps. void UninstallDefaultApps(); @@ -180,7 +180,7 @@ class AppLauncherHandler : public content::WebUIMessageHandler, scoped_ptr<ExtensionUninstallDialog> extension_uninstall_dialog_; // Used to show confirmation UI for enabling extensions in incognito mode. - scoped_ptr<ExtensionInstallUI> extension_install_ui_; + scoped_ptr<ExtensionInstallPrompt> extension_install_ui_; // The id of the extension we are prompting the user about. std::string extension_id_prompting_; diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index a64b8f9..9c21acd 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -304,8 +304,12 @@ 'browser/extensions/extension_input_module_constants.h', 'browser/extensions/extension_install_dialog.cc', 'browser/extensions/extension_install_dialog.h', + 'browser/extensions/extension_install_prompt.cc', + 'browser/extensions/extension_install_prompt.h', 'browser/extensions/extension_install_ui.cc', 'browser/extensions/extension_install_ui.h', + 'browser/extensions/extension_install_ui_default.h', + 'browser/extensions/extension_install_ui_default.cc', 'browser/extensions/extension_keybinding_registry.cc', 'browser/extensions/extension_keybinding_registry.h', 'browser/extensions/extension_management_api_constants.cc', @@ -662,7 +666,13 @@ ], }], ['OS=="android"', { + 'sources': [ + 'browser/extensions/extension_install_ui_android.cc', + 'browser/extensions/extension_install_ui_android.h', + ], 'sources!': [ + 'browser/extensions/extension_install_ui_default.cc', + 'browser/extensions/extension_install_ui_default.h', 'browser/extensions/api/usb/usb_api.cc', 'browser/extensions/api/usb/usb_api.h', 'browser/extensions/api/usb/usb_device_resource.cc', |