diff options
Diffstat (limited to 'chrome/browser')
8 files changed, 400 insertions, 306 deletions
diff --git a/chrome/browser/extensions/extension_install_dialog.cc b/chrome/browser/extensions/extension_install_dialog.cc index 336c2c7..813e63b 100644 --- a/chrome/browser/extensions/extension_install_dialog.cc +++ b/chrome/browser/extensions/extension_install_dialog.cc @@ -67,8 +67,8 @@ void ShowExtensionInstallDialogForManifest( } ExtensionInstallUI::Prompt filled_out_prompt = prompt; - filled_out_prompt.permissions = - (*dummy_extension)->GetPermissionMessageStrings(); + filled_out_prompt.SetPermissions( + (*dummy_extension)->GetPermissionMessageStrings()); ShowExtensionInstallDialog(profile, delegate, diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc index 77fc4a4..6fd551f 100644 --- a/chrome/browser/extensions/extension_install_ui.cc +++ b/chrome/browser/extensions/extension_install_ui.cc @@ -39,36 +39,31 @@ #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" -// static -const int ExtensionInstallUI::kTitleIds[NUM_PROMPT_TYPES] = { - IDS_EXTENSION_INSTALL_PROMPT_TITLE, +static const int kTitleIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { IDS_EXTENSION_INSTALL_PROMPT_TITLE, + IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE, IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE, IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE }; -// static -const int ExtensionInstallUI::kHeadingIds[NUM_PROMPT_TYPES] = { +static const int kHeadingIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { IDS_EXTENSION_INSTALL_PROMPT_HEADING, IDS_EXTENSION_INSTALL_PROMPT_HEADING, IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING, IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING }; -// static -const int ExtensionInstallUI::kButtonIds[NUM_PROMPT_TYPES] = { - IDS_EXTENSION_PROMPT_INSTALL_BUTTON, +static const int kAcceptButtonIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { IDS_EXTENSION_PROMPT_INSTALL_BUTTON, + IDS_EXTENSION_PROMPT_INLINE_INSTALL_BUTTON, IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON, IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON }; -// static -const int ExtensionInstallUI::kAbortButtonIds[NUM_PROMPT_TYPES] = { +static const int kAbortButtonIds[ExtensionInstallUI::NUM_PROMPT_TYPES] = { 0, 0, 0, IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON }; -// static -const int ExtensionInstallUI::kWarningIds[NUM_PROMPT_TYPES] = { +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_WILL_NOW_HAVE_ACCESS_TO, @@ -82,12 +77,116 @@ const int kIconSize = 69; } // namespace -ExtensionInstallUI::Prompt::Prompt(PromptType type) : type(type) { +ExtensionInstallUI::Prompt::Prompt(PromptType type) : type_(type) { } ExtensionInstallUI::Prompt::~Prompt() { } +void ExtensionInstallUI::Prompt::SetPermissions( + std::vector<string16> permissions) { + permissions_ = permissions; +} + +void ExtensionInstallUI::Prompt::SetInlineInstallWebstoreData( + 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 { + if (type_ == INLINE_INSTALL_PROMPT) { + return l10n_util::GetStringFUTF16( + kTitleIds[type_], l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); + } else { + return l10n_util::GetStringUTF16(kTitleIds[type_]); + } +} + +string16 ExtensionInstallUI::Prompt::GetHeading(std::string extension_name) + const { + if (type_ == INLINE_INSTALL_PROMPT) { + return UTF8ToUTF16(extension_name); + } 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::GetPermissionsHeader() 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; + } + + int i; + for (i = 0; i < rating_integer; i++) { + appender(IDR_EXTENSIONS_RATING_STAR_ON, data); + } + if (rating_fractional) { + appender(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT, data); + i++; + } + for (; i < kMaxExtensionRating; i++) { + appender(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 { + CHECK_EQ(INLINE_INSTALL_PROMPT, type_); + return permissions_.size(); +} + +string16 ExtensionInstallUI::Prompt::GetPermission(int index) const { + CHECK_EQ(INLINE_INSTALL_PROMPT, type_); + return l10n_util::GetStringFUTF16( + IDS_EXTENSION_PERMISSION_LINE, permissions_[index]); +} + ExtensionInstallUI::ExtensionInstallUI(Profile* profile) : profile_(profile), ui_loop_(MessageLoop::current()), @@ -227,7 +326,7 @@ void ExtensionInstallUI::OnImageLoaded( NotificationService::NoDetails()); Prompt prompt(prompt_type_); - prompt.permissions = permissions_->GetWarningMessages(); + prompt.SetPermissions(permissions_->GetWarningMessages()); ShowExtensionInstallDialog( profile_, delegate_, extension_, &icon_, prompt); break; diff --git a/chrome/browser/extensions/extension_install_ui.h b/chrome/browser/extensions/extension_install_ui.h index 4cc10c2..18f69d3 100644 --- a/chrome/browser/extensions/extension_install_ui.h +++ b/chrome/browser/extensions/extension_install_ui.h @@ -37,35 +37,61 @@ class ExtensionInstallUI : public ImageLoadingTracker::Observer { }; // Extra information needed to display an installation or uninstallation - // prompt. - struct Prompt { + // 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(); - PromptType type; + void SetPermissions(std::vector<string16> permissions); + void SetInlineInstallWebstoreData(std::string localized_user_count, + double average_rating, + int rating_count); + + PromptType type() const { return type_; } + + // Getters for UI element labels. + string16 GetDialogTitle() const; + string16 GetHeading(std::string extension_name) const; + string16 GetAcceptButtonLabel() const; + bool HasAbortButtonLabel() const; + string16 GetAbortButtonLabel() const; + string16 GetPermissionsHeader() 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 called back with the resource ID that they + // need to load/append. + typedef void*(*StarAppender)(int, void*); + void AppendRatingStars(StarAppender appender, void* data) const; + string16 GetRatingCount() const; + string16 GetUserCount() const; + size_t GetPermissionCount() const; + string16 GetPermission(int index) const; + + 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; + std::vector<string16> permissions_; // These fields are populated only when the prompt type is // INLINE_INSTALL_PROMPT // Already formatted to be locale-specific. - std::string localized_user_count; + std::string localized_user_count_; // Range is kMinExtensionRating to kMaxExtensionRating - double average_rating; - int rating_count; + double average_rating_; + int rating_count_; }; static const int kMinExtensionRating = 0; static const int kMaxExtensionRating = 5; - // A mapping from PromptType to message ID for various dialog content. - static const int kTitleIds[NUM_PROMPT_TYPES]; - static const int kHeadingIds[NUM_PROMPT_TYPES]; - static const int kButtonIds[NUM_PROMPT_TYPES]; - static const int kWarningIds[NUM_PROMPT_TYPES]; - static const int kAbortButtonIds[NUM_PROMPT_TYPES]; - class Delegate { public: // We call this method to signal that the installation should continue. diff --git a/chrome/browser/extensions/webstore_inline_installer.cc b/chrome/browser/extensions/webstore_inline_installer.cc index ffa8158..ad08d85 100644 --- a/chrome/browser/extensions/webstore_inline_installer.cc +++ b/chrome/browser/extensions/webstore_inline_installer.cc @@ -252,9 +252,9 @@ void WebstoreInlineInstaller::OnWebstoreParseSuccess( tab_contents_->browser_context()); ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INLINE_INSTALL_PROMPT); - prompt.localized_user_count = localized_user_count_; - prompt.average_rating = average_rating_; - prompt.rating_count = rating_count_; + prompt.SetInlineInstallWebstoreData(localized_user_count_, + average_rating_, + rating_count_); ShowExtensionInstallDialogForManifest(profile, this, 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 5877481..cd383ee 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm @@ -67,7 +67,7 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { // We use a different XIB in the case of no permission warnings, that is a // little bit more nicely laid out. - if (prompt.permissions.empty()) { + if (prompt.GetPermissionCount() == 0) { nibpath = [base::mac::MainAppBundle() pathForResource:@"ExtensionInstallPromptNoWarnings" ofType:@"nib"]; @@ -83,27 +83,26 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { icon_ = *icon; delegate_ = delegate; - title_.reset( - [l10n_util::GetNSStringF(ExtensionInstallUI::kHeadingIds[prompt.type], - UTF8ToUTF16(extension->name())) retain]); - subtitle_.reset( - [l10n_util::GetNSString(ExtensionInstallUI::kWarningIds[prompt.type]) - retain]); - button_.reset([l10n_util::GetNSString( - ExtensionInstallUI::kButtonIds[prompt.type]) retain]); - int cancel_id = ExtensionInstallUI::kAbortButtonIds[prompt.type]; - cancel_button_.reset([l10n_util::GetNSString( - cancel_id > 0 ? cancel_id : IDS_CANCEL) retain]); + title_.reset([base::SysUTF16ToNSString( + prompt.GetHeading(extension->name())) retain]); + subtitle_.reset([base::SysUTF16ToNSString( + prompt.GetPermissionsHeader()) retain]); + button_.reset([base::SysUTF16ToNSString( + prompt.GetAcceptButtonLabel()) retain]); + NSString* cancel_button_label = prompt.HasAbortButtonLabel() ? + base::SysUTF16ToNSString(prompt.GetAbortButtonLabel()) : + l10n_util::GetNSString(IDS_CANCEL); + cancel_button_.reset([cancel_button_label retain]); // We display the permission warnings as a simple text string, separated by // newlines. - if (!prompt.permissions.empty()) { + if (prompt.GetPermissionCount()) { string16 joined_warnings; - for (size_t i = 0; i < prompt.permissions.size(); ++i) { + for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { if (i > 0) joined_warnings += UTF8ToUTF16("\n\n"); - joined_warnings += prompt.permissions[i]; + joined_warnings += prompt.GetPermission(i); } warnings_.reset( 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 4a175b0..c29cbf6 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 @@ -108,7 +108,9 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { new MockExtensionInstallUIDelegate); ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INSTALL_PROMPT); - prompt.permissions.push_back(UTF8ToUTF16("warning 1")); + std::vector<string16> permissions; + permissions.push_back(UTF8ToUTF16("warning 1")); + prompt.SetPermissions(permissions); scoped_nsobject<ExtensionInstallDialogController> controller([[ExtensionInstallDialogController alloc] @@ -140,7 +142,7 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { EXPECT_TRUE([controller warningsField] != nil); EXPECT_NSEQ([[controller warningsField] stringValue], - base::SysUTF16ToNSString(prompt.permissions[0])); + base::SysUTF16ToNSString(prompt.GetPermission(0))); EXPECT_TRUE([controller warningsBox] != nil); @@ -164,7 +166,9 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalOK) { new MockExtensionInstallUIDelegate); ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INSTALL_PROMPT); - prompt.permissions.push_back(UTF8ToUTF16("warning 1")); + std::vector<string16> permissions; + permissions.push_back(UTF8ToUTF16("warning 1")); + prompt.SetPermissions(permissions); scoped_nsobject<ExtensionInstallDialogController> controller([[ExtensionInstallDialogController alloc] @@ -192,12 +196,14 @@ TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { ExtensionInstallUI::Prompt one_warning_prompt( ExtensionInstallUI::INSTALL_PROMPT); - one_warning_prompt.permissions.push_back(UTF8ToUTF16("warning 1")); + std::vector<string16> permissions; + permissions.push_back(UTF8ToUTF16("warning 1")); + one_warning_prompt.SetPermissions(permissions); ExtensionInstallUI::Prompt two_warnings_prompt( ExtensionInstallUI::INSTALL_PROMPT); - two_warnings_prompt.permissions.push_back(UTF8ToUTF16("warning 1")); - two_warnings_prompt.permissions.push_back(UTF8ToUTF16("warning 2")); + permissions.push_back(UTF8ToUTF16("warning 2")); + two_warnings_prompt.SetPermissions(permissions); scoped_nsobject<ExtensionInstallDialogController> controller1([[ExtensionInstallDialogController alloc] 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 8544cda..00028b3 100644 --- a/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc @@ -4,7 +4,6 @@ #include <gtk/gtk.h> -#include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/extensions/extension_install_dialog.h" @@ -16,7 +15,6 @@ #include "chrome/browser/ui/gtk/gtk_util.h" #include "chrome/common/extensions/extension.h" #include "grit/generated_resources.h" -#include "grit/theme_resources.h" #include "skia/ext/image_operations.h" #include "ui/base/gtk/gtk_hig_constants.h" #include "ui/base/l10n/l10n_util.h" @@ -45,33 +43,6 @@ GtkWidget* AddResourceIcon(int resource_id, GtkWidget* container) { return icon_widget; } -// Adds star icons corresponding to a rating. Replicates the CWS stars display -// logic (from components.ratingutils.setFractionalYellowStars). -void AddRatingStars(double average_rating, GtkWidget* container) { - 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; - } - - int i = 0; - while (i++ < rating_integer) { - AddResourceIcon(IDR_EXTENSIONS_RATING_STAR_ON, container); - } - if (rating_fractional) { - AddResourceIcon(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT, container); - i++; - } - while (i++ < ExtensionInstallUI::kMaxExtensionRating) { - AddResourceIcon(IDR_EXTENSIONS_RATING_STAR_OFF, container); - } -} - // Displays the dialog when constructed, deletes itself when dialog is // dismissed. Success/failure is passed back through the ExtensionInstallUI:: // Delegate instance. @@ -101,25 +72,24 @@ ExtensionInstallDialog::ExtensionInstallDialog( const ExtensionInstallUI::Prompt& prompt) : delegate_(delegate), extension_(extension) { - ExtensionInstallUI::PromptType type = prompt.type; - const std::vector<string16>& permissions = prompt.permissions; - bool show_permissions = !permissions.empty(); - bool is_inline_install = type == ExtensionInstallUI::INLINE_INSTALL_PROMPT; + bool show_permissions = prompt.GetPermissionCount() > 0; + bool is_inline_install = + prompt.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT; // Build the dialog. dialog_ = gtk_dialog_new_with_buttons( - l10n_util::GetStringUTF8(ExtensionInstallUI::kTitleIds[type]).c_str(), + UTF16ToUTF8(prompt.GetDialogTitle()).c_str(), parent, GTK_DIALOG_MODAL, NULL); - int cancel = ExtensionInstallUI::kAbortButtonIds[type]; GtkWidget* close_button = gtk_dialog_add_button( GTK_DIALOG(dialog_), - cancel > 0 ? l10n_util::GetStringUTF8(cancel).c_str(): GTK_STOCK_CANCEL, + prompt.HasAbortButtonLabel() ? + UTF16ToUTF8(prompt.GetAbortButtonLabel()).c_str() : GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE); gtk_dialog_add_button( GTK_DIALOG(dialog_), - l10n_util::GetStringUTF8(ExtensionInstallUI::kButtonIds[type]).c_str(), + UTF16ToUTF8(prompt.GetAcceptButtonLabel()).c_str(), GTK_RESPONSE_ACCEPT); gtk_dialog_set_has_separator(GTK_DIALOG(dialog_), FALSE); @@ -142,17 +112,16 @@ ExtensionInstallDialog::ExtensionInstallDialog( TRUE, TRUE, 0); GtkWidget* heading_vbox = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(left_column_area), heading_vbox, FALSE, FALSE, 0); + // If we are not going to show anything else, vertically center the title. + bool center_heading = !show_permissions && !is_inline_install; + gtk_box_pack_start(GTK_BOX(left_column_area), heading_vbox, center_heading, + center_heading, 0); - // Heading (name-only for inline installs) - std::string heading_text = is_inline_install ? extension_->name() : - l10n_util::GetStringFUTF8(ExtensionInstallUI::kHeadingIds[type], - UTF8ToUTF16(extension_->name())); - GtkWidget* heading_label = gtk_util::CreateBoldLabel(heading_text); + // Heading + GtkWidget* heading_label = gtk_util::CreateBoldLabel( + UTF16ToUTF8(prompt.GetHeading(extension_->name())).c_str()); gtk_label_set_line_wrap(GTK_LABEL(heading_label), true); gtk_misc_set_alignment(GTK_MISC(heading_label), 0.0, 0.5); - // If we are not going to show anything else, vertically center the title. - bool center_heading = !show_permissions && !is_inline_install; gtk_box_pack_start(GTK_BOX(heading_vbox), heading_label, center_heading, center_heading, 0); @@ -160,18 +129,19 @@ ExtensionInstallDialog::ExtensionInstallDialog( // Average rating (as stars) and number of ratings GtkWidget* stars_hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(heading_vbox), stars_hbox, FALSE, FALSE, 0); - AddRatingStars(prompt.average_rating, stars_hbox); - GtkWidget* rating_label = gtk_label_new(l10n_util::GetStringFUTF8( - IDS_EXTENSION_RATING_COUNT, - UTF8ToUTF16(base::IntToString(prompt.rating_count))).c_str()); + prompt.AppendRatingStars( + reinterpret_cast<ExtensionInstallUI::Prompt::StarAppender>( + AddResourceIcon), + stars_hbox); + GtkWidget* rating_label = gtk_label_new(UTF16ToUTF8( + prompt.GetRatingCount()).c_str()); gtk_util::ForceFontSizePixels(rating_label, kRatingTextSize); gtk_box_pack_start(GTK_BOX(stars_hbox), rating_label, FALSE, FALSE, 3); // User count - GtkWidget* users_label = gtk_label_new(l10n_util::GetStringFUTF8( - IDS_EXTENSION_USER_COUNT, - UTF8ToUTF16(prompt.localized_user_count)).c_str()); + GtkWidget* users_label = gtk_label_new(UTF16ToUTF8( + prompt.GetUserCount()).c_str()); gtk_util::SetLabelWidth(users_label, kLeftColumnMinWidth); gtk_util::SetLabelColor(users_label, &ui::kGdkGray); gtk_util::ForceFontSizePixels(rating_label, kRatingTextSize); @@ -219,17 +189,15 @@ ExtensionInstallDialog::ExtensionInstallDialog( permissions_container = left_column_area; } - GtkWidget* warning_label = gtk_util::CreateBoldLabel( - l10n_util::GetStringUTF8( - ExtensionInstallUI::kWarningIds[type]).c_str()); - gtk_util::SetLabelWidth(warning_label, kLeftColumnMinWidth); - gtk_box_pack_start(GTK_BOX(permissions_container), warning_label, FALSE, - FALSE, is_inline_install ? 0 : ui::kControlSpacing); - - for (std::vector<string16>::const_iterator iter = permissions.begin(); - iter != permissions.end(); ++iter) { - GtkWidget* permission_label = gtk_label_new(l10n_util::GetStringFUTF8( - IDS_EXTENSION_PERMISSION_LINE, *iter).c_str()); + GtkWidget* permissions_header = gtk_util::CreateBoldLabel( + UTF16ToUTF8(prompt.GetPermissionsHeader()).c_str()); + gtk_util::SetLabelWidth(permissions_header, kLeftColumnMinWidth); + gtk_box_pack_start(GTK_BOX(permissions_container), permissions_header, + FALSE, FALSE, 0); + + for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { + GtkWidget* permission_label = gtk_label_new(UTF16ToUTF8( + prompt.GetPermission(i)).c_str()); gtk_util::SetLabelWidth(permission_label, kLeftColumnMinWidth); gtk_box_pack_start(GTK_BOX(permissions_container), permission_label, FALSE, FALSE, kPermissionsPadding); 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 268c589..9e41a93 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc @@ -14,8 +14,14 @@ #include "chrome/common/extensions/extension.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" #include "views/controls/image_view.h" #include "views/controls/label.h" +#include "views/controls/link.h" +#include "views/controls/link_listener.h" +#include "views/controls/separator.h" +#include "views/layout/box_layout.h" +#include "views/layout/grid_layout.h" #include "views/layout/layout_constants.h" #include "views/view.h" #include "views/widget/widget.h" @@ -26,30 +32,13 @@ namespace { // Size of extension icon in top left of dialog. const int kIconSize = 69; -// Width of the white permission box. This also is the max width of all -// elements in the right column of the dialog in the case where the extension -// requests permissions. -const int kPermissionBoxWidth = 270; - -// Width of the right column of the dialog when the extension requests no +// Width of the left column of the dialog when the extension requests // permissions. -const int kNoPermissionsRightColumnWidth = 210; - -// Width of the gray border around the permission box. -const int kPermissionBoxBorderWidth = 1; - -// Width of the horizontal padding inside the permission box border. -const int kPermissionBoxHorizontalPadding = 10; +const int kPermissionsLeftColumnWidth = 250; -// Width of the vertical padding inside the permission box border. -const int kPermissionBoxVerticalPadding = 11; - -// The max width of the individual permission strings inside the permission -// box. -const int kPermissionLabelWidth = - kPermissionBoxWidth - - kPermissionBoxBorderWidth * 2 - - kPermissionBoxHorizontalPadding * 2; +// Width of the left column of the dialog when the extension requests no +// permissions. +const int kNoPermissionsLeftColumnWidth = 200; // Heading font size correction. #if defined(CROS_FONTS_USING_BCI) @@ -58,22 +47,29 @@ const int kHeadingFontSizeDelta = 0; const int kHeadingFontSizeDelta = 1; #endif +const int kRatingFontSizeDelta = -1; + +void AddResourceIcon(int resource_id, views::View* parent) { + const SkBitmap* skia_image = ResourceBundle::GetSharedInstance(). + GetBitmapNamed(resource_id); + views::ImageView* image_view = new views::ImageView(); + image_view->SetImage(*skia_image); + parent->AddChildView(image_view); +} + } // namespace // Implements the extension installation dialog for TOOLKIT_VIEWS. -class ExtensionInstallDialogView : public views::DialogDelegateView { +class ExtensionInstallDialogView : public views::DialogDelegateView, + public views::LinkListener { public: ExtensionInstallDialogView(ExtensionInstallUI::Delegate* delegate, const Extension* extension, - SkBitmap* icon, + SkBitmap* skia_icon, const ExtensionInstallUI::Prompt& prompt); virtual ~ExtensionInstallDialogView(); private: - // views::View: - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual void Layout() OVERRIDE; - // views::DialogDelegate: virtual std::wstring GetDialogButtonLabel( MessageBoxFlags::DialogButton button) const OVERRIDE; @@ -86,31 +82,15 @@ class ExtensionInstallDialogView : public views::DialogDelegateView { virtual std::wstring GetWindowTitle() const OVERRIDE; virtual views::View* GetContentsView() OVERRIDE; - // The delegate that we will call back to when the user accepts or rejects - // the installation. - ExtensionInstallUI::Delegate* delegate_; - - // Displays the extension's icon. - views::ImageView* icon_; + // views::LinkListener: + virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; - // Displays the main heading "Install FooBar?". - views::Label* heading_; - - // Displays the permission box header "The extension will have access to:". - views::Label* will_have_access_to_; - - // The white box containing the list of permissions the extension requires. - // This can be NULL if the extension requires no permissions. - views::View* permission_box_; - - // The labels describing each of the permissions the extension requires. - std::vector<views::Label*> permissions_; - - // The width of the right column of the dialog. Will be either - // kPermissionBoxWidth or kNoPermissionsRightColumnWidth, depending on - // whether the extension requires any permissions. - int right_column_width_; + bool is_inline_install() { + return prompt_.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT; + } + ExtensionInstallUI::Delegate* delegate_; + const Extension* extension_; ExtensionInstallUI::Prompt prompt_; DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView); @@ -119,163 +99,171 @@ class ExtensionInstallDialogView : public views::DialogDelegateView { ExtensionInstallDialogView::ExtensionInstallDialogView( ExtensionInstallUI::Delegate* delegate, const Extension* extension, - SkBitmap* icon, + SkBitmap* skia_icon, const ExtensionInstallUI::Prompt& prompt) : delegate_(delegate), - icon_(NULL), - heading_(NULL), - will_have_access_to_(NULL), - permission_box_(NULL), - right_column_width_(0), + extension_(extension), prompt_(prompt) { + // Possible grid layouts: + // Inline install + // w/ permissions no permissions + // +--------------------+------+ +--------------+------+ + // | heading | icon | | heading | icon | + // +--------------------| | +--------------| | + // | rating | | | rating | | + // +--------------------| | +--------------+ | + // | user_count | | | user_count | | + // +--------------------| | +--------------| | + // | store_link | | | store_link | | + // +--------------------+------+ +--------------+------+ + // | separator | + // +--------------------+------+ + // | permissions_header | | + // +--------------------+------+ + // | permission1 | | + // +--------------------+------+ + // | permission2 | | + // +--------------------+------+ + // + // Regular install + // w/ permissions no permissions + // +--------------------+------+ +--------------+------+ + // | heading | icon | | heading | icon | + // +--------------------| | +--------------+------+ + // | permissions_header | | + // +--------------------| | + // | permission1 | | + // +--------------------| | + // | permission2 | | + // +--------------------+------+ + + using views::GridLayout; + GridLayout* layout = GridLayout::CreatePanel(this); + SetLayoutManager(layout); + + int column_set_id = 0; + views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); + + column_set->AddColumn(GridLayout::LEADING, + GridLayout::FILL, + 0, // no resizing + GridLayout::USE_PREF, + 0, // no fixed with + prompt.GetPermissionCount() > 0 ? + kNoPermissionsLeftColumnWidth : + kPermissionsLeftColumnWidth); + column_set->AddPaddingColumn(0, views::kPanelHorizMargin); + column_set->AddColumn(GridLayout::LEADING, + GridLayout::LEADING, + 0, // no resizing + GridLayout::USE_PREF, + 0, // no fixed width + kIconSize); + + layout->StartRow(0, column_set_id); + + views::Label* heading = new views::Label(UTF16ToWide( + prompt.GetHeading(extension->name()))); + heading->SetFont(heading->font().DeriveFont(kHeadingFontSizeDelta, + gfx::Font::BOLD)); + heading->SetMultiLine(true); + layout->AddView(heading); + // Scale down to icon size, but allow smaller icons (don't scale up). - gfx::Size size(icon->width(), icon->height()); + gfx::Size size(skia_icon->width(), skia_icon->height()); if (size.width() > kIconSize || size.height() > kIconSize) size = gfx::Size(kIconSize, kIconSize); - icon_ = new views::ImageView(); - icon_->SetImageSize(size); - icon_->SetImage(*icon); - icon_->SetHorizontalAlignment(views::ImageView::CENTER); - icon_->SetVerticalAlignment(views::ImageView::CENTER); - AddChildView(icon_); - - heading_ = new views::Label(UTF16ToWide( - l10n_util::GetStringFUTF16(ExtensionInstallUI::kHeadingIds[prompt.type], - UTF8ToUTF16(extension->name())))); - heading_->SetFont(heading_->font().DeriveFont(kHeadingFontSizeDelta, - gfx::Font::BOLD)); - heading_->SetMultiLine(true); - heading_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - AddChildView(heading_); - - if (prompt.permissions.empty()) { - right_column_width_ = kNoPermissionsRightColumnWidth; - } else { - right_column_width_ = kPermissionBoxWidth; - will_have_access_to_ = new views::Label(UTF16ToWide( - l10n_util::GetStringUTF16( - ExtensionInstallUI::kWarningIds[prompt.type]))); - will_have_access_to_->SetMultiLine(true); - will_have_access_to_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - AddChildView(will_have_access_to_); - - permission_box_ = new views::View(); - permission_box_->set_background( - views::Background::CreateSolidBackground(SK_ColorWHITE)); - permission_box_->set_border( - views::Border::CreateSolidBorder(kPermissionBoxBorderWidth, - SK_ColorLTGRAY)); - AddChildView(permission_box_); + views::ImageView* icon = new views::ImageView(); + icon->SetImageSize(size); + icon->SetImage(*skia_icon); + icon->SetHorizontalAlignment(views::ImageView::CENTER); + icon->SetVerticalAlignment(views::ImageView::CENTER); + int icon_row_span = 1; + if (is_inline_install()) { + // Also span the rating, user_count and store_link rows. + icon_row_span = 4; + } else if (prompt.GetPermissionCount()) { + // Also span the permission header and each of the permission rows (all have + // a padding row above it). + icon_row_span = 3 + prompt.GetPermissionCount() * 2; } - - for (size_t i = 0; i < prompt.permissions.size(); ++i) { - views::Label* label = new views::Label(UTF16ToWide(prompt.permissions[i])); - label->SetMultiLine(true); - label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - permission_box_->AddChildView(label); - permissions_.push_back(label); + layout->AddView(icon, 1, icon_row_span); + + if (is_inline_install()) { + layout->StartRow(0, column_set_id); + views::View* rating = new views::View(); + rating->SetLayoutManager(new views::BoxLayout( + views::BoxLayout::kHorizontal, 0, 0, 0)); + layout->AddView(rating); + prompt.AppendRatingStars( + reinterpret_cast<ExtensionInstallUI::Prompt::StarAppender>( + AddResourceIcon), + rating); + + views::Label* rating_count = new views::Label( + UTF16ToWide(prompt.GetRatingCount())); + rating_count->SetFont( + rating_count->font().DeriveFont(kRatingFontSizeDelta)); + rating->AddChildView(rating_count); + + layout->StartRow(0, column_set_id); + views::Label* user_count = new views::Label( + UTF16ToWide(prompt.GetUserCount())); + user_count->SetColor(SK_ColorGRAY); + user_count->SetFont(user_count->font().DeriveFont(kRatingFontSizeDelta)); + layout->AddView(user_count); + + layout->StartRow(0, column_set_id); + views::Link* store_link = new views::Link(UTF16ToWide( + l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_STORE_LINK))); + store_link->SetFont(store_link->font().DeriveFont(kRatingFontSizeDelta)); + store_link->set_listener(this); + layout->AddView(store_link); } -} -ExtensionInstallDialogView::~ExtensionInstallDialogView() { -} - -gfx::Size ExtensionInstallDialogView::GetPreferredSize() { - int width = views::kPanelHorizMargin * 2; - width += kIconSize; - width += views::kPanelHorizMargin; // Gutter. - width += right_column_width_; - - int height = views::kPanelVertMargin * 2; - height += heading_->GetHeightForWidth(right_column_width_); - - if (permission_box_) { - height += views::kRelatedControlVerticalSpacing; - height += will_have_access_to_->GetHeightForWidth(right_column_width_); - - height += views::kRelatedControlVerticalSpacing; - height += kPermissionBoxBorderWidth * 2; - height += kPermissionBoxVerticalPadding * 2; + if (prompt.GetPermissionCount()) { + layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); - for (size_t i = 0; i < permissions_.size(); ++i) { - if (i > 0) - height += views::kRelatedControlVerticalSpacing; - height += permissions_[0]->GetHeightForWidth(kPermissionLabelWidth); + if (is_inline_install()) { + layout->StartRow(0, column_set_id); + views::Separator* separator = new views::Separator(); + layout->AddView(separator, 3, 1, GridLayout::FILL, GridLayout::FILL); + layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); } - } - - return gfx::Size(width, - std::max(height, kIconSize + views::kPanelVertMargin * 2)); -} - -void ExtensionInstallDialogView::Layout() { - int x = views::kPanelHorizMargin; - int y = views::kPanelVertMargin; - - icon_->SetBounds(x, y, kIconSize, kIconSize); - x += kIconSize; - x += views::kPanelHorizMargin; - heading_->SizeToFit(right_column_width_); - heading_->SetX(x); - - // If there's no special permissions, we do a slightly different layout with - // the heading centered vertically wrt the icon. - if (!permission_box_) { - heading_->SetY((GetPreferredSize().height() - heading_->height()) / 2); - return; - } - - // Otherwise, do the layout with the permission box. - heading_->SetY(y); - y += heading_->height(); - - y += views::kRelatedControlVerticalSpacing; - will_have_access_to_->SizeToFit(right_column_width_); - will_have_access_to_->SetX(x); - will_have_access_to_->SetY(y); - y += will_have_access_to_->height(); - - y += views::kRelatedControlVerticalSpacing; - permission_box_->SetX(x); - permission_box_->SetY(y); - - // First we layout the labels inside the permission box, so that we know how - // big the box will have to be. - int label_x = kPermissionBoxBorderWidth + kPermissionBoxHorizontalPadding; - int label_y = kPermissionBoxBorderWidth + kPermissionBoxVerticalPadding; - int permission_box_height = kPermissionBoxBorderWidth * 2; - permission_box_height += kPermissionBoxVerticalPadding * 2; - - for (size_t i = 0; i < permissions_.size(); ++i) { - if (i > 0) { - label_y += views::kRelatedControlVerticalSpacing; - permission_box_height += views::kPanelVertMargin; + layout->StartRow(0, column_set_id); + views::Label* permissions_header = new views::Label(UTF16ToWide( + prompt.GetPermissionsHeader())); + permissions_header->SetMultiLine(true); + layout->AddView(permissions_header); + + for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { + layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout->StartRow(0, column_set_id); + views::Label* permission_label = new views::Label( + UTF16ToWide(prompt.GetPermission(i))); + permission_label->SetMultiLine(true); + permission_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + layout->AddView(permission_label, + 1, 1, + GridLayout::LEADING, GridLayout::FILL, + kPermissionsLeftColumnWidth, 0); } - - permissions_[i]->SizeToFit(kPermissionLabelWidth); - permissions_[i]->SetX(label_x); - permissions_[i]->SetY(label_y); - - label_y += permissions_[i]->height(); - permission_box_height += permissions_[i]->height(); } +} - // Now finally we can size the permission box itself. - permission_box_->SetBounds(permission_box_->x(), permission_box_->y(), - right_column_width_, permission_box_height); +ExtensionInstallDialogView::~ExtensionInstallDialogView() { } std::wstring ExtensionInstallDialogView::GetDialogButtonLabel( MessageBoxFlags::DialogButton button) const { switch (button) { case MessageBoxFlags::DIALOGBUTTON_OK: - return UTF16ToWide(l10n_util::GetStringUTF16( - ExtensionInstallUI::kButtonIds[prompt_.type])); - case MessageBoxFlags::DIALOGBUTTON_CANCEL: { - int id = ExtensionInstallUI::kAbortButtonIds[prompt_.type]; - return UTF16ToWide(l10n_util::GetStringUTF16(id > 0 ? id : IDS_CANCEL)); - } + return UTF16ToWide(prompt_.GetAcceptButtonLabel()); + case MessageBoxFlags::DIALOGBUTTON_CANCEL: + return prompt_.HasAbortButtonLabel() ? + UTF16ToWide(prompt_.GetAbortButtonLabel()) : + UTF16ToWide(l10n_util::GetStringUTF16(IDS_CANCEL)); default: NOTREACHED(); return std::wstring(); @@ -301,14 +289,22 @@ bool ExtensionInstallDialogView::IsModal() const { } std::wstring ExtensionInstallDialogView::GetWindowTitle() const { - return UTF16ToWide( - l10n_util::GetStringUTF16(ExtensionInstallUI::kTitleIds[prompt_.type])); + return UTF16ToWide(prompt_.GetDialogTitle()); } views::View* ExtensionInstallDialogView::GetContentsView() { return this; } +void ExtensionInstallDialogView::LinkClicked(views::Link* source, + int event_flags) { + GURL store_url( + extension_urls::GetWebstoreItemDetailURLPrefix() + extension_->id()); + BrowserList::GetLastActive()-> + OpenURL(store_url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); + GetWidget()->Close(); +} + void ShowExtensionInstallDialog( Profile* profile, ExtensionInstallUI::Delegate* delegate, |