15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/website_settings/permission_selector.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/gtk_theme_service.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/gtk_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/menu_gtk.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/website_settings/website_settings_ui.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_hig_constants.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/menu_model.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSetting CommandIdToContentSetting(int command_id) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (command_id) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PermissionMenuModel::COMMAND_SET_TO_DEFAULT: 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CONTENT_SETTING_DEFAULT; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PermissionMenuModel::COMMAND_SET_TO_ALLOW: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CONTENT_SETTING_ALLOW; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PermissionMenuModel::COMMAND_SET_TO_BLOCK: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CONTENT_SETTING_BLOCK; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CONTENT_SETTING_DEFAULT; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PermissionSelector::PermissionSelector(GtkThemeService* theme_service, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSettingsType type, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSetting setting, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSetting default_setting, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_settings::SettingSource source) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : widget_(NULL), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_button_(NULL), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_(NULL), 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_(type), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_setting_(default_setting), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setting_(setting) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(default_setting, CONTENT_SETTING_DEFAULT); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create permission info box. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kChildSpacing = 4; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget_ = gtk_hbox_new(FALSE, kChildSpacing); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add permission type icon. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSetting effective_setting = setting; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (effective_setting == CONTENT_SETTING_DEFAULT) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) effective_setting = default_setting; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type, effective_setting).ToGdkPixbuf(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_ = gtk_image_new_from_pixbuf(pixbuf); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(widget_), icon_, FALSE, FALSE, 0); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a label for the permission type. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* label = theme_service->BuildLabel(l10n_util::GetStringFUTF8( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_WEBSITE_SETTINGS_PERMISSION_TYPE, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebsiteSettingsUI::PermissionTypeToUIString(type)), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::kGdkBlack); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(widget_), label, FALSE, FALSE, 0); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the menu button. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_button_ = theme_service->BuildChromeButton(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* button_hbox = gtk_hbox_new(FALSE, 0); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_container_add(GTK_CONTAINER(menu_button_), button_hbox); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* button_label = theme_service->BuildLabel( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTF16ToUTF8(WebsiteSettingsUI::PermissionActionToUIString( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setting, default_setting, source)), 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::kGdkBlack); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(button_hbox), button_label, FALSE, FALSE, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::kControlSpacing); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool user_setting = source == content_settings::SETTING_SOURCE_USER; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_sensitive(GTK_WIDGET(menu_button_), user_setting); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (user_setting) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* arrow = NULL; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't handle theme changes, which is a bug but they are very unlikely 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to occur while a bubble is grabbing input. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (theme_service->UsingNativeTheme()) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow = gtk_image_new_from_pixbuf( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetNativeImageNamed(IDR_APP_DROPARROW).ToGdkPixbuf()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(button_hbox), arrow, FALSE, FALSE, 0); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_button_set_relief(GTK_BUTTON(menu_button_), GTK_RELIEF_NONE); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(widget_), menu_button_, FALSE, FALSE, 0); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) menu_model_.reset(new PermissionMenuModel(this, url, type, default_setting, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setting)); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuGtk::Delegate* delegate = new MenuGtk::Delegate(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_.reset(new MenuGtk(delegate, menu_model_.get())); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_signal_connect(menu_button_, "button-press-event", 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnMenuButtonPressEventThunk), this); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PermissionSelector::~PermissionSelector() { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PermissionSelector::AddObserver(PermissionSelectorObserver* observer) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_.AddObserver(observer); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSetting PermissionSelector::GetSetting() const { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return setting_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSettingsType PermissionSelector::GetType() const { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean PermissionSelector::OnMenuButtonPressEvent(GtkWidget* button, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkEventButton* event) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->button != 1) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_->PopupForWidget(button, event->button, event->time); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PermissionSelector::ExecuteCommand(int command_id) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setting_ = CommandIdToContentSetting(command_id); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Change the permission icon to reflect the selected setting. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSetting effective_setting = setting_; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (effective_setting == CONTENT_SETTING_DEFAULT) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) effective_setting = default_setting_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_, effective_setting).ToGdkPixbuf(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), pixbuf); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Change the text of the menu button to reflect the selected setting. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_button_set_label(GTK_BUTTON(menu_button_), UTF16ToUTF8( 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebsiteSettingsUI::PermissionActionToUIString( 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setting_, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_setting_, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_settings::SETTING_SOURCE_USER)).c_str()); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(PermissionSelectorObserver, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPermissionChanged(this)); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PermissionSelector::IsCommandIdChecked(int command_id) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return setting_ == CommandIdToContentSetting(command_id); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 163