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