diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-10 22:04:28 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-10 22:04:28 +0000 |
commit | 121cd7b957d4ed22f861a22783de788703bcaf7c (patch) | |
tree | c8a391f2c463a0321b7cb2efd61f9760fca51249 | |
parent | a850ba49a28734c8660e04c52449a3b770a04d1b (diff) | |
download | chromium_src-121cd7b957d4ed22f861a22783de788703bcaf7c.zip chromium_src-121cd7b957d4ed22f861a22783de788703bcaf7c.tar.gz chromium_src-121cd7b957d4ed22f861a22783de788703bcaf7c.tar.bz2 |
Add a confirmation prompt to app uninstallation on the ntp.
The uninstall dialog used to say:
[===============================x]
|Confirm Uninstallation |
|--------------------------------|
|<b>Uninstall Foo Extension?</b> |
| |
|Are you sure you want to |
|uninstall this extension? |
| |
|================================|
We don't have the bottom string with the word 'app', and I
realized it is somewhat extraneous anyway. So just removed it
in all cases and de-bolded the text above. Looks much better.
Also, fixed a bug where the icon we display in the GTK
dialogs is too big by doing image resizing in
ExtensionInstallUI.
BUG=54874
TEST=Uninstall app and extension. Both should have a prompt,
and UI layout should be the same.
Review URL: http://codereview.chromium.org/3332016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59157 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/extension_install_prompt.mm | 3 | ||||
-rw-r--r-- | chrome/browser/dom_ui/app_launcher_handler.cc | 40 | ||||
-rw-r--r-- | chrome/browser/dom_ui/app_launcher_handler.h | 19 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_install_ui.cc | 14 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_install_ui.h | 2 | ||||
-rw-r--r-- | chrome/browser/gtk/extension_install_prompt_gtk.cc | 26 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/apps.js | 1 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_install_prompt.cc | 119 |
9 files changed, 102 insertions, 125 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index af446c4..79f019d 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3410,9 +3410,6 @@ each locale. --> <message name="IDS_EXTENSION_UNINSTALL_PROMPT_HEADING" desc="First bold line in the content area of the extension uninstallation prompt. Asks the user if they want to uninstall a particular extension."> Uninstall "<ph name="EXTENSION_NAME">$1<ex>Gmail Checker</ex></ph>"? </message> - <message name="IDS_EXTENSION_UNINSTALL_CONFIRMATION" desc="The warning you get when you are about to uninstall an extension."> - Are you sure you want to uninstall this extension? - </message> <message name="IDS_EXTENSION_PROMPT_WARNING_BROWSER" desc="Warning displayed in body of extension dialog when the extension requires access to browser APIs."> This extension will have access to your browsing history. </message> diff --git a/chrome/browser/cocoa/extension_install_prompt.mm b/chrome/browser/cocoa/extension_install_prompt.mm index b73ebc2..3519319 100644 --- a/chrome/browser/cocoa/extension_install_prompt.mm +++ b/chrome/browser/cocoa/extension_install_prompt.mm @@ -21,7 +21,7 @@ class Profile; void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl( Profile* profile, Delegate* delegate, Extension* extension, SkBitmap* icon, - const string16& warning_text, ExtensionInstallUI::PromptType type) { + ExtensionInstallUI::PromptType type) { NSAlert* alert = [[[NSAlert alloc] init] autorelease]; NSButton* continueButton = [alert addButtonWithTitle:l10n_util::GetNSString( @@ -37,7 +37,6 @@ void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl( [alert setMessageText:l10n_util::GetNSStringF( ExtensionInstallUI::kHeadingIds[type], UTF8ToUTF16(extension->name()))]; - [alert setInformativeText:base::SysUTF16ToNSString(warning_text)]; [alert setAlertStyle:NSWarningAlertStyle]; [alert setIcon:gfx::SkBitmapToNSImage(*icon)]; diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc index 46cf478..7049d05 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.cc +++ b/chrome/browser/dom_ui/app_launcher_handler.cc @@ -6,6 +6,7 @@ #include "app/animation.h" #include "base/string_number_conversions.h" +#include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/app_launched_animation.h" @@ -197,11 +198,42 @@ void AppLauncherHandler::AnimateAppIcon(Extension* extension, void AppLauncherHandler::HandleUninstallApp(const ListValue* args) { std::string extension_id = WideToUTF8(ExtractStringValue(args)); + Extension* extension = extensions_service_->GetExtensionById( + extension_id, false); + if (!extension) + return; + + if (!extension_id_prompting_.empty()) + return; // Only one prompt at a time. + + extension_id_prompting_ = extension_id; + GetExtensionInstallUI()->ConfirmUninstall(this, extension); +} + +ExtensionInstallUI* AppLauncherHandler::GetExtensionInstallUI() { + if (!install_ui_.get()) + install_ui_.reset(new ExtensionInstallUI(dom_ui_->GetProfile())); + return install_ui_.get(); +} - // Make sure that the extension exists. +void AppLauncherHandler::InstallUIProceed(bool create_app_shortcut) { + // We only ever use ExtensionInstallUI for uninstalling, which should never + // result in it telling us to create a shortcut. + DCHECK(!create_app_shortcut); + DCHECK(!extension_id_prompting_.empty()); + + // The extension can be uninstalled in another window while the UI was + // showing. Do nothing in that case. Extension* extension = - extensions_service_->GetExtensionById(extension_id, false); - DCHECK(extension); + extensions_service_->GetExtensionById(extension_id_prompting_, true); + if (!extension) + return; + + extensions_service_->UninstallExtension(extension_id_prompting_, + false /* external_uninstall */); + extension_id_prompting_ = ""; +} - extensions_service_->UninstallExtension(extension_id, false); +void AppLauncherHandler::InstallUIAbort() { + extension_id_prompting_ = ""; } diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h index 7e89bb7..6a2954a 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.h +++ b/chrome/browser/dom_ui/app_launcher_handler.h @@ -6,7 +6,9 @@ #define CHROME_BROWSER_DOM_UI_APP_LAUNCHER_HANDLER_H_ #pragma once +#include "base/scoped_ptr.h" #include "chrome/browser/dom_ui/dom_ui.h" +#include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" @@ -20,6 +22,7 @@ namespace gfx { // The handler for Javascript messages related to the "apps" view. class AppLauncherHandler : public DOMMessageHandler, + public ExtensionInstallUI::Delegate, public NotificationObserver { public: explicit AppLauncherHandler(ExtensionsService* extension_service); @@ -47,6 +50,15 @@ class AppLauncherHandler void HandleUninstallApp(const ListValue* args); private: + // ExtensionInstallUI::Delegate implementation, used for receiving + // notification about uninstall confirmation dialog selections. + virtual void InstallUIProceed(bool create_app_shortcut); + virtual void InstallUIAbort(); + + // Returns the ExtensionInstallUI object for this class, creating it if + // needed. + ExtensionInstallUI* GetExtensionInstallUI(); + // Starts the animation of the app icon. void AnimateAppIcon(Extension* extension, const gfx::Rect& rect); @@ -57,6 +69,13 @@ class AppLauncherHandler // when necessary. NotificationRegistrar registrar_; + // Used to show confirmation UI for uninstalling/enabling extensions in + // incognito mode. + scoped_ptr<ExtensionInstallUI> install_ui_; + + // The id of the extension we are prompting the user about. + std::string extension_id_prompting_; + DISALLOW_COPY_AND_ASSIGN(AppLauncherHandler); }; diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc index e2a8c8e..5e39366 100644 --- a/chrome/browser/extensions/extension_install_ui.cc +++ b/chrome/browser/extensions/extension_install_ui.cc @@ -63,6 +63,9 @@ const int ExtensionInstallUI::kButtonIds[NUM_PROMPT_TYPES] = { namespace { +// Size of extension icon in top left of dialog. +const int kIconSize = 69; + static void GetV2Warnings(Extension* extension, std::vector<string16>* warnings) { if (!extension->plugins().empty()) { @@ -291,15 +294,13 @@ void ExtensionInstallUI::OnImageLoaded( std::vector<string16> warnings; GetV2Warnings(extension_, &warnings); - ShowExtensionInstallUIPrompt2Impl( - profile_, delegate_, extension_, &icon_, warnings); + ShowExtensionInstallUIPrompt2Impl(profile_, delegate_, extension_, &icon_, + warnings); break; } case UNINSTALL_PROMPT: { - string16 message = - l10n_util::GetStringUTF16(IDS_EXTENSION_UNINSTALL_CONFIRMATION); ShowExtensionInstallUIPromptImpl(profile_, delegate_, extension_, &icon_, - message, UNINSTALL_PROMPT); + UNINSTALL_PROMPT); break; } default: @@ -360,8 +361,7 @@ void ExtensionInstallUI::ShowConfirmation(PromptType prompt_type) { ExtensionResource image = extension_->GetIconResource(Extension::EXTENSION_ICON_LARGE); tracker_.LoadImage(extension_, image, - gfx::Size(Extension::EXTENSION_ICON_LARGE, - Extension::EXTENSION_ICON_LARGE), + gfx::Size(kIconSize, kIconSize), ImageLoadingTracker::DONT_CACHE); } diff --git a/chrome/browser/extensions/extension_install_ui.h b/chrome/browser/extensions/extension_install_ui.h index 238da54..ae07363 100644 --- a/chrome/browser/extensions/extension_install_ui.h +++ b/chrome/browser/extensions/extension_install_ui.h @@ -116,7 +116,7 @@ class ExtensionInstallUI : public ImageLoadingTracker::Observer { // NOTE: The implementations of this function is platform-specific. static void ShowExtensionInstallUIPromptImpl( Profile* profile, Delegate* delegate, Extension* extension, - SkBitmap* icon, const string16& warning, PromptType type); + SkBitmap* icon, PromptType type); // Implements the showing of the new install dialog. The implementations of // this function are platform-specific. diff --git a/chrome/browser/gtk/extension_install_prompt_gtk.cc b/chrome/browser/gtk/extension_install_prompt_gtk.cc index 12566173..45efdc7 100644 --- a/chrome/browser/gtk/extension_install_prompt_gtk.cc +++ b/chrome/browser/gtk/extension_install_prompt_gtk.cc @@ -26,18 +26,6 @@ namespace { // Left or right margin. const int kPanelHorizMargin = 13; -GtkWidget* MakeMarkupLabel(const char* format, const std::string& str) { - GtkWidget* label = gtk_label_new(NULL); - char* markup = g_markup_printf_escaped(format, str.c_str()); - gtk_label_set_markup(GTK_LABEL(label), markup); - g_free(markup); - - // Left align it. - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - - return label; -} - void OnDialogResponse(GtkDialog* dialog, int response_id, ExtensionInstallUI::Delegate* delegate) { if (response_id == GTK_RESPONSE_ACCEPT) { @@ -52,7 +40,6 @@ void OnDialogResponse(GtkDialog* dialog, int response_id, void ShowInstallPromptDialog(GtkWindow* parent, SkBitmap* skia_icon, Extension *extension, ExtensionInstallUI::Delegate *delegate, - const string16& warning_text, ExtensionInstallUI::PromptType type) { // Build the dialog. int title_id = ExtensionInstallUI::kTitleIds[type]; @@ -88,15 +75,10 @@ void ShowInstallPromptDialog(GtkWindow* parent, SkBitmap* skia_icon, int heading_id = ExtensionInstallUI::kHeadingIds[type]; std::string heading_text = l10n_util::GetStringFUTF8( heading_id, UTF8ToUTF16(extension->name())); - GtkWidget* heading_label = MakeMarkupLabel("<span weight=\"bold\">%s</span>", - heading_text); + GtkWidget* heading_label = gtk_label_new(heading_text.c_str()); gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5); gtk_box_pack_start(GTK_BOX(right_column_area), heading_label, TRUE, TRUE, 0); - GtkWidget* warning_label = gtk_label_new(UTF16ToUTF8(warning_text).c_str()); - gtk_misc_set_alignment(GTK_MISC(warning_label), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(right_column_area), warning_label, TRUE, TRUE, 0); - g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), delegate); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_widget_show_all(dialog); @@ -106,7 +88,7 @@ void ShowInstallPromptDialog(GtkWindow* parent, SkBitmap* skia_icon, void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl( Profile* profile, Delegate* delegate, Extension* extension, SkBitmap* icon, - const string16& warning_text, ExtensionInstallUI::PromptType type) { + ExtensionInstallUI::PromptType type) { Browser* browser = BrowserList::GetLastActiveWithProfile(profile); if (!browser) { delegate->InstallUIAbort(); @@ -120,6 +102,6 @@ void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl( return; } - ShowInstallPromptDialog(browser_window->window(), icon, extension, - delegate, warning_text, type); + ShowInstallPromptDialog(browser_window->window(), icon, extension, delegate, + type); } diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js index 4c717b3..0ae457a 100644 --- a/chrome/browser/resources/ntp/apps.js +++ b/chrome/browser/resources/ntp/apps.js @@ -12,6 +12,7 @@ function getAppsCallback(data) { if (data.apps.length == 0) { appsSection.classList.add('disabled'); + layoutSections(); return; } diff --git a/chrome/browser/views/extensions/extension_install_prompt.cc b/chrome/browser/views/extensions/extension_install_prompt.cc index 3de19a3..af9c540 100644 --- a/chrome/browser/views/extensions/extension_install_prompt.cc +++ b/chrome/browser/views/extensions/extension_install_prompt.cc @@ -28,34 +28,19 @@ class Profile; namespace { -// Since apps don't (currently) have any privilege disclosure text, the dialog -// looks a bit empty if it is sized the same as extensions. So we scale -// everything down a bit for apps for the time being. -const int kRightColumnWidthApp = 210; -const int kRightColumnWidthExtension = 270; -const int kIconSizeApp = 69; -const int kIconSizeExtension = 85; +const int kRightColumnWidth = 210; +const int kIconSize = 69; // Implements the extension installation prompt for Windows. class InstallDialogContent : public views::View, public views::DialogDelegate { public: InstallDialogContent(ExtensionInstallUI::Delegate* delegate, - Extension* extension, SkBitmap* icon, const std::wstring& warning_text, - ExtensionInstallUI::PromptType type) - : delegate_(delegate), icon_(NULL), warning_(NULL), - create_shortcut_(NULL), type_(type) { - if (extension->GetFullLaunchURL().is_valid()) { - icon_size_ = kIconSizeApp; - right_column_width_ = kRightColumnWidthApp; - } else { - icon_size_ = kIconSizeExtension; - right_column_width_ = kRightColumnWidthExtension; - } - + Extension* extension, SkBitmap* icon, ExtensionInstallUI::PromptType type) + : delegate_(delegate), icon_(NULL), type_(type) { // Scale down to icon size, but allow smaller icons (don't scale up). gfx::Size size(icon->width(), icon->height()); - if (size.width() > icon_size_ || size.height() > icon_size_) - size = gfx::Size(icon_size_, icon_size_); + if (size.width() > kIconSize || size.height() > kIconSize) + size = gfx::Size(kIconSize, kIconSize); icon_ = new views::ImageView(); icon_->SetImageSize(size); icon_->SetImage(*icon); @@ -64,24 +49,9 @@ class InstallDialogContent : public views::View, public views::DialogDelegate { heading_ = new views::Label( l10n_util::GetStringF(ExtensionInstallUI::kHeadingIds[type_], UTF8ToWide(extension->name()))); - heading_->SetFont(heading_->font().DeriveFont(1, gfx::Font::BOLD)); heading_->SetMultiLine(true); heading_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); AddChildView(heading_); - - if (type_ == ExtensionInstallUI::INSTALL_PROMPT && - extension->GetFullLaunchURL().is_valid()) { - create_shortcut_ = new views::Checkbox( - l10n_util::GetString(IDS_EXTENSION_PROMPT_CREATE_SHORTCUT)); - create_shortcut_->SetChecked(true); - create_shortcut_->SetMultiLine(true); - AddChildView(create_shortcut_); - } else { - warning_ = new views::Label(warning_text); - warning_->SetMultiLine(true); - warning_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - AddChildView(warning_); - } } private: @@ -104,8 +74,9 @@ class InstallDialogContent : public views::View, public views::DialogDelegate { } virtual bool Accept() { - delegate_->InstallUIProceed( - create_shortcut_ && create_shortcut_->checked()); + // We don't support shortcut creation from this dialog anymore. + // TODO(aa): Remove this param from ExtensionInstallUI::Delegate. + delegate_->InstallUIProceed(false); return true; } @@ -124,70 +95,47 @@ class InstallDialogContent : public views::View, public views::DialogDelegate { // View virtual gfx::Size GetPreferredSize() { - int width = right_column_width_ + kPanelHorizMargin + kPanelHorizMargin; - width += icon_size_; - width += kPanelHorizMargin; + int width = kRightColumnWidth; + width += kIconSize; + width += kPanelHorizMargin * 3; int height = kPanelVertMargin * 2; - height += heading_->GetHeightForWidth(right_column_width_); - height += kPanelVertMargin; - - if (warning_) - height += warning_->GetHeightForWidth(right_column_width_); - else - height += create_shortcut_->GetPreferredSize().height(); - - height += kPanelVertMargin; + height += heading_->GetHeightForWidth(kRightColumnWidth); return gfx::Size(width, - std::max(height, icon_size_ + kPanelVertMargin * 2)); + std::max(height, kIconSize + kPanelVertMargin * 2)); } virtual void Layout() { int x = kPanelHorizMargin; int y = kPanelVertMargin; - icon_->SetBounds(x, y, icon_size_, icon_size_); - x += icon_size_; - x += kPanelHorizMargin; - - heading_->SizeToFit(right_column_width_); - heading_->SetX(x); - heading_->SetY(y); - y += heading_->height(); - - y += kPanelVertMargin; - - if (create_shortcut_) { - create_shortcut_->SetBounds(x, y, right_column_width_, 0); - create_shortcut_->SetBounds(x, y, right_column_width_, - create_shortcut_->GetPreferredSize().height()); - - int bottom_aligned = icon_->y() + icon_->height() - - create_shortcut_->height(); - if (bottom_aligned > y) { - create_shortcut_->SetY(bottom_aligned); - y = bottom_aligned; - } - y += create_shortcut_->height(); + heading_->SizeToFit(kRightColumnWidth); + + if (heading_->height() <= kIconSize) { + icon_->SetBounds(x, y, kIconSize, kIconSize); + x += kIconSize; + x += kPanelHorizMargin; + + heading_->SetX(x); + heading_->SetY(y + (kIconSize - heading_->height()) / 2); } else { - warning_->SizeToFit(right_column_width_); - warning_->SetX(x); - warning_->SetY(y); - y += warning_->height(); + icon_->SetBounds(x, + y + (heading_->height() - kIconSize) / 2, + kIconSize, + kIconSize); + x += kIconSize; + x += kPanelHorizMargin; + + heading_->SetX(x); + heading_->SetY(y); } - - y += kPanelVertMargin; } ExtensionInstallUI::Delegate* delegate_; views::ImageView* icon_; views::Label* heading_; - views::Label* warning_; - views::Checkbox* create_shortcut_; ExtensionInstallUI::PromptType type_; - int right_column_width_; - int icon_size_; DISALLOW_COPY_AND_ASSIGN(InstallDialogContent); }; @@ -197,7 +145,7 @@ class InstallDialogContent : public views::View, public views::DialogDelegate { // static void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl( Profile* profile, Delegate* delegate, Extension* extension, SkBitmap* icon, - const string16& warning_text, PromptType type) { + PromptType type) { Browser* browser = BrowserList::GetLastActiveWithProfile(profile); if (!browser) { delegate->InstallUIAbort(); @@ -212,6 +160,5 @@ void ExtensionInstallUI::ShowExtensionInstallUIPromptImpl( views::Window::CreateChromeWindow(window->GetNativeHandle(), gfx::Rect(), new InstallDialogContent(delegate, extension, icon, - UTF16ToWideHack(warning_text), type))->Show(); } |