1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/gtk/website_settings/permission_selector.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/i18n/rtl.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "chrome/browser/ui/gtk/gtk_theme_service.h" 11 #include "chrome/browser/ui/gtk/gtk_util.h" 12 #include "chrome/browser/ui/gtk/menu_gtk.h" 13 #include "chrome/browser/ui/website_settings/website_settings_ui.h" 14 #include "grit/generated_resources.h" 15 #include "grit/theme_resources.h" 16 #include "ui/base/gtk/gtk_hig_constants.h" 17 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/base/models/menu_model.h" 19 #include "ui/base/resource/resource_bundle.h" 20 #include "ui/gfx/image/image.h" 21 22 namespace { 23 24 ContentSetting CommandIdToContentSetting(int command_id) { 25 switch (command_id) { 26 case PermissionMenuModel::COMMAND_SET_TO_DEFAULT: 27 return CONTENT_SETTING_DEFAULT; 28 case PermissionMenuModel::COMMAND_SET_TO_ALLOW: 29 return CONTENT_SETTING_ALLOW; 30 case PermissionMenuModel::COMMAND_SET_TO_BLOCK: 31 return CONTENT_SETTING_BLOCK; 32 default: 33 NOTREACHED(); 34 return CONTENT_SETTING_DEFAULT; 35 } 36 } 37 38 } // namespace 39 40 PermissionSelector::PermissionSelector(GtkThemeService* theme_service, 41 const GURL& url, 42 ContentSettingsType type, 43 ContentSetting setting, 44 ContentSetting default_setting, 45 content_settings::SettingSource source) 46 : widget_(NULL), 47 menu_button_(NULL), 48 icon_(NULL), 49 type_(type), 50 default_setting_(default_setting), 51 setting_(setting) { 52 DCHECK_NE(default_setting, CONTENT_SETTING_DEFAULT); 53 54 // Create permission info box. 55 const int kChildSpacing = 4; 56 widget_ = gtk_hbox_new(FALSE, kChildSpacing); 57 58 // Add permission type icon. 59 ContentSetting effective_setting = setting; 60 if (effective_setting == CONTENT_SETTING_DEFAULT) 61 effective_setting = default_setting; 62 GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( 63 type, effective_setting).ToGdkPixbuf(); 64 icon_ = gtk_image_new_from_pixbuf(pixbuf); 65 gtk_box_pack_start(GTK_BOX(widget_), icon_, FALSE, FALSE, 0); 66 67 // Add a label for the permission type. 68 GtkWidget* label = theme_service->BuildLabel(l10n_util::GetStringFUTF8( 69 IDS_WEBSITE_SETTINGS_PERMISSION_TYPE, 70 WebsiteSettingsUI::PermissionTypeToUIString(type)), 71 ui::kGdkBlack); 72 gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR); 73 74 gtk_box_pack_start(GTK_BOX(widget_), label, FALSE, FALSE, 0); 75 76 // Add the menu button. 77 menu_button_ = theme_service->BuildChromeButton(); 78 GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0); 79 gtk_container_add(GTK_CONTAINER(menu_button_), button_hbox); 80 81 GtkWidget* button_label = theme_service->BuildLabel( 82 UTF16ToUTF8(WebsiteSettingsUI::PermissionActionToUIString( 83 setting, default_setting, source)), 84 ui::kGdkBlack); 85 gtk_box_pack_start(GTK_BOX(button_hbox), button_label, FALSE, FALSE, 86 ui::kControlSpacing); 87 88 bool user_setting = source == content_settings::SETTING_SOURCE_USER; 89 gtk_widget_set_sensitive(GTK_WIDGET(menu_button_), user_setting); 90 if (user_setting) { 91 GtkWidget* arrow = NULL; 92 // We don't handle theme changes, which is a bug but they are very unlikely 93 // to occur while a bubble is grabbing input. 94 if (theme_service->UsingNativeTheme()) { 95 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE); 96 } else { 97 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 98 arrow = gtk_image_new_from_pixbuf( 99 rb.GetNativeImageNamed(IDR_APP_DROPARROW).ToGdkPixbuf()); 100 } 101 gtk_box_pack_start(GTK_BOX(button_hbox), arrow, FALSE, FALSE, 0); 102 } 103 gtk_button_set_relief(GTK_BUTTON(menu_button_), GTK_RELIEF_NONE); 104 gtk_box_pack_start(GTK_BOX(widget_), menu_button_, FALSE, FALSE, 0); 105 106 menu_model_.reset(new PermissionMenuModel(this, url, type, default_setting, 107 setting)); 108 MenuGtk::Delegate* delegate = new MenuGtk::Delegate(); 109 menu_.reset(new MenuGtk(delegate, menu_model_.get())); 110 g_signal_connect(menu_button_, "button-press-event", 111 G_CALLBACK(OnMenuButtonPressEventThunk), this); 112 } 113 114 PermissionSelector::~PermissionSelector() { 115 } 116 117 void PermissionSelector::AddObserver(PermissionSelectorObserver* observer) { 118 observer_list_.AddObserver(observer); 119 } 120 121 ContentSetting PermissionSelector::GetSetting() const { 122 return setting_; 123 } 124 125 ContentSettingsType PermissionSelector::GetType() const { 126 return type_; 127 } 128 129 gboolean PermissionSelector::OnMenuButtonPressEvent(GtkWidget* button, 130 GdkEventButton* event) { 131 if (event->button != 1) 132 return FALSE; 133 menu_->PopupForWidget(button, event->button, event->time); 134 return TRUE; 135 } 136 137 void PermissionSelector::ExecuteCommand(int command_id) { 138 setting_ = CommandIdToContentSetting(command_id); 139 140 // Change the permission icon to reflect the selected setting. 141 ContentSetting effective_setting = setting_; 142 if (effective_setting == CONTENT_SETTING_DEFAULT) 143 effective_setting = default_setting_; 144 GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( 145 type_, effective_setting).ToGdkPixbuf(); 146 gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), pixbuf); 147 148 // Change the text of the menu button to reflect the selected setting. 149 gtk_button_set_label(GTK_BUTTON(menu_button_), UTF16ToUTF8( 150 WebsiteSettingsUI::PermissionActionToUIString( 151 setting_, 152 default_setting_, 153 content_settings::SETTING_SOURCE_USER)).c_str()); 154 155 FOR_EACH_OBSERVER(PermissionSelectorObserver, 156 observer_list_, 157 OnPermissionChanged(this)); 158 } 159 160 bool PermissionSelector::IsCommandIdChecked(int command_id) { 161 return setting_ == CommandIdToContentSetting(command_id); 162 } 163