| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/website_settings/permission_selector_view.h" | 5 #include "chrome/browser/ui/views/website_settings/permission_selector_view.h" |
| 6 | 6 |
| 7 #include "base/i18n/rtl.h" | 7 #include "base/i18n/rtl.h" |
| 8 #include "base/macros.h" | 8 #include "base/macros.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 10 #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h
" | 10 #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h
" |
| 11 #include "chrome/browser/ui/website_settings/permission_menu_model.h" | 11 #include "chrome/browser/ui/website_settings/permission_menu_model.h" |
| 12 #include "chrome/browser/ui/website_settings/website_settings_ui.h" | 12 #include "chrome/browser/ui/website_settings/website_settings_ui.h" |
| 13 #include "chrome/grit/generated_resources.h" | 13 #include "chrome/grit/generated_resources.h" |
| 14 #include "ui/accessibility/ax_view_state.h" | 14 #include "ui/accessibility/ax_view_state.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
| 16 #include "ui/base/models/combobox_model.h" |
| 16 #include "ui/gfx/image/image.h" | 17 #include "ui/gfx/image/image.h" |
| 17 #include "ui/views/controls/button/menu_button.h" | 18 #include "ui/views/controls/button/menu_button.h" |
| 19 #include "ui/views/controls/combobox/combobox.h" |
| 20 #include "ui/views/controls/combobox/combobox_listener.h" |
| 18 #include "ui/views/controls/image_view.h" | 21 #include "ui/views/controls/image_view.h" |
| 19 #include "ui/views/controls/label.h" | 22 #include "ui/views/controls/label.h" |
| 20 #include "ui/views/controls/menu/menu_runner.h" | 23 #include "ui/views/controls/menu/menu_runner.h" |
| 21 #include "ui/views/layout/grid_layout.h" | 24 #include "ui/views/layout/grid_layout.h" |
| 22 #include "ui/views/view.h" | 25 #include "ui/views/view.h" |
| 23 #include "ui/views/widget/widget.h" | 26 #include "ui/views/widget/widget.h" |
| 24 | 27 |
| 25 namespace internal { | 28 namespace internal { |
| 26 | 29 |
| 27 // The |PermissionMenuButton| provides a menu for selecting a setting a | 30 // The |PermissionMenuButton| provides a menu for selecting a setting a |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(), | 108 if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(), |
| 106 this, | 109 this, |
| 107 gfx::Rect(p, gfx::Size()), | 110 gfx::Rect(p, gfx::Size()), |
| 108 views::MENU_ANCHOR_TOPLEFT, | 111 views::MENU_ANCHOR_TOPLEFT, |
| 109 ui::MENU_SOURCE_NONE) == | 112 ui::MENU_SOURCE_NONE) == |
| 110 views::MenuRunner::MENU_DELETED) { | 113 views::MenuRunner::MENU_DELETED) { |
| 111 return; | 114 return; |
| 112 } | 115 } |
| 113 } | 116 } |
| 114 | 117 |
| 118 // This class adapts a |PermissionMenuModel| into a |ui::ComboboxModel| so that |
| 119 // |PermissionCombobox| can use it. |
| 120 class ComboboxModelAdapter : public ui::ComboboxModel { |
| 121 public: |
| 122 explicit ComboboxModelAdapter(PermissionMenuModel* model) : model_(model) {} |
| 123 ~ComboboxModelAdapter() override {} |
| 124 |
| 125 void OnPerformAction(int index); |
| 126 |
| 127 // Returns the checked index of the underlying PermissionMenuModel, of which |
| 128 // there must be exactly one. This is used to choose which index is selected |
| 129 // in the PermissionCombobox. |
| 130 int GetCheckedIndex(); |
| 131 |
| 132 // ui::ComboboxModel: |
| 133 int GetItemCount() const override; |
| 134 base::string16 GetItemAt(int index) override; |
| 135 |
| 136 private: |
| 137 PermissionMenuModel* model_; |
| 138 }; |
| 139 |
| 140 void ComboboxModelAdapter::OnPerformAction(int index) { |
| 141 model_->ExecuteCommand(index, 0); |
| 142 } |
| 143 |
| 144 int ComboboxModelAdapter::GetCheckedIndex() { |
| 145 int checked_index = -1; |
| 146 for (int i = 0; i < model_->GetItemCount(); ++i) { |
| 147 if (model_->IsCommandIdChecked(i)) { |
| 148 // This function keeps track of |checked_index| instead of returning early |
| 149 // here so that it can DCHECK that there's exactly one selected item, |
| 150 // which is not normally guaranteed by MenuModel, but *is* true of |
| 151 // PermissionMenuModel. |
| 152 DCHECK_EQ(checked_index, -1); |
| 153 checked_index = i; |
| 154 } |
| 155 } |
| 156 return checked_index; |
| 157 } |
| 158 |
| 159 int ComboboxModelAdapter::GetItemCount() const { |
| 160 DCHECK(model_); |
| 161 return model_->GetItemCount(); |
| 162 } |
| 163 |
| 164 base::string16 ComboboxModelAdapter::GetItemAt(int index) { |
| 165 return model_->GetLabelAt(index); |
| 166 } |
| 167 |
| 168 // The |PermissionCombobox| provides a combobox for selecting a permission type. |
| 169 // This is only used on platforms where the permission dialog uses a combobox |
| 170 // instead of a MenuButton (currently, Mac). |
| 171 class PermissionCombobox : public views::Combobox, |
| 172 public views::ComboboxListener { |
| 173 public: |
| 174 PermissionCombobox(const base::string16& text, |
| 175 ComboboxModelAdapter* model, |
| 176 bool enabled, |
| 177 bool use_default); |
| 178 ~PermissionCombobox() override; |
| 179 |
| 180 void UpdateSelectedIndex(bool use_default); |
| 181 |
| 182 private: |
| 183 // views::ComboboxListener: |
| 184 void OnPerformAction(Combobox* combobox) override; |
| 185 |
| 186 ComboboxModelAdapter* model_; |
| 187 }; |
| 188 |
| 189 PermissionCombobox::PermissionCombobox(const base::string16& text, |
| 190 ComboboxModelAdapter* model, |
| 191 bool enabled, |
| 192 bool use_default) |
| 193 : views::Combobox(model), model_(model) { |
| 194 set_listener(this); |
| 195 SetEnabled(enabled); |
| 196 UpdateSelectedIndex(use_default); |
| 197 } |
| 198 |
| 199 PermissionCombobox::~PermissionCombobox() {} |
| 200 |
| 201 void PermissionCombobox::UpdateSelectedIndex(bool use_default) { |
| 202 int index = model_->GetCheckedIndex(); |
| 203 if (use_default && index == -1) { |
| 204 LOG(ERROR) << "ow!"; |
| 205 index = 0; |
| 206 } |
| 207 SetSelectedIndex(index); |
| 208 } |
| 209 |
| 210 void PermissionCombobox::OnPerformAction(Combobox* combobox) { |
| 211 model_->OnPerformAction(combobox->selected_index()); |
| 212 } |
| 213 |
| 115 } // namespace internal | 214 } // namespace internal |
| 116 | 215 |
| 117 /////////////////////////////////////////////////////////////////////////////// | 216 /////////////////////////////////////////////////////////////////////////////// |
| 118 // PermissionSelectorView | 217 // PermissionSelectorView |
| 119 /////////////////////////////////////////////////////////////////////////////// | 218 /////////////////////////////////////////////////////////////////////////////// |
| 120 | 219 |
| 121 PermissionSelectorView::PermissionSelectorView( | 220 PermissionSelectorView::PermissionSelectorView( |
| 122 const GURL& url, | 221 const GURL& url, |
| 123 const WebsiteSettingsUI::PermissionInfo& permission) | 222 const WebsiteSettingsUI::PermissionInfo& permission) |
| 124 : icon_(NULL), menu_button_(NULL) { | 223 : icon_(NULL), menu_button_(NULL), combobox_(NULL) { |
| 125 views::GridLayout* layout = new views::GridLayout(this); | 224 views::GridLayout* layout = new views::GridLayout(this); |
| 126 SetLayoutManager(layout); | 225 SetLayoutManager(layout); |
| 127 const int column_set_id = 0; | 226 const int column_set_id = 0; |
| 128 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); | 227 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); |
| 129 column_set->AddColumn(views::GridLayout::FILL, | 228 column_set->AddColumn(views::GridLayout::FILL, |
| 130 views::GridLayout::FILL, | 229 views::GridLayout::FILL, |
| 131 1, | 230 1, |
| 132 views::GridLayout::FIXED, | 231 views::GridLayout::FIXED, |
| 133 kPermissionIconColumnWidth, | 232 kPermissionIconColumnWidth, |
| 134 0); | 233 0); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 165 1, | 264 1, |
| 166 views::GridLayout::LEADING, | 265 views::GridLayout::LEADING, |
| 167 views::GridLayout::CENTER); | 266 views::GridLayout::CENTER); |
| 168 // Create the menu model. | 267 // Create the menu model. |
| 169 menu_model_.reset(new PermissionMenuModel( | 268 menu_model_.reset(new PermissionMenuModel( |
| 170 url, | 269 url, |
| 171 permission, | 270 permission, |
| 172 base::Bind(&PermissionSelectorView::PermissionChanged, | 271 base::Bind(&PermissionSelectorView::PermissionChanged, |
| 173 base::Unretained(this)))); | 272 base::Unretained(this)))); |
| 174 // Create the permission menu button. | 273 // Create the permission menu button. |
| 175 bool button_enabled = | 274 #if defined(OS_MACOSX) |
| 176 permission.source == content_settings::SETTING_SOURCE_USER; | 275 InitializeComboboxView(layout, permission); |
| 177 menu_button_ = new internal::PermissionMenuButton( | 276 #else |
| 178 WebsiteSettingsUI::PermissionActionToUIString( | 277 InitializeMenuButtonView(layout, permission); |
| 179 permission.type, permission.setting, permission.default_setting, | 278 #endif |
| 180 permission.source), | |
| 181 menu_model_.get(), button_enabled); | |
| 182 menu_button_->SetEnabled(button_enabled); | |
| 183 menu_button_->SetAccessibleName( | |
| 184 WebsiteSettingsUI::PermissionTypeToUIString(permission.type)); | |
| 185 layout->AddView(menu_button_); | |
| 186 } | 279 } |
| 187 | 280 |
| 188 void PermissionSelectorView::AddObserver( | 281 void PermissionSelectorView::AddObserver( |
| 189 PermissionSelectorViewObserver* observer) { | 282 PermissionSelectorViewObserver* observer) { |
| 190 observer_list_.AddObserver(observer); | 283 observer_list_.AddObserver(observer); |
| 191 } | 284 } |
| 192 | 285 |
| 193 void PermissionSelectorView::ChildPreferredSizeChanged(View* child) { | 286 void PermissionSelectorView::ChildPreferredSizeChanged(View* child) { |
| 194 SizeToPreferredSize(); | 287 SizeToPreferredSize(); |
| 195 // FIXME: The parent is only a plain |View| that is used as a | 288 // FIXME: The parent is only a plain |View| that is used as a |
| 196 // container/box/panel. The SizeToPreferredSize method of the parent is | 289 // container/box/panel. The SizeToPreferredSize method of the parent is |
| 197 // called here directly in order not to implement a custom |View| class with | 290 // called here directly in order not to implement a custom |View| class with |
| 198 // its own implementation of the ChildPreferredSizeChanged method. | 291 // its own implementation of the ChildPreferredSizeChanged method. |
| 199 parent()->SizeToPreferredSize(); | 292 parent()->SizeToPreferredSize(); |
| 200 } | 293 } |
| 201 | 294 |
| 202 PermissionSelectorView::~PermissionSelectorView() { | 295 PermissionSelectorView::~PermissionSelectorView() { |
| 296 // Gross. On paper the Combobox and the ComboboxModelAdapter are both owned by |
| 297 // this class, but actually, the Combobox is owned by View and will be |
| 298 // destroyed in ~View(), which runs *after* ~PermissionSelectorView() is done, |
| 299 // which means the Combobox gets destroyed after its ComboboxModel, which |
| 300 // causes an explosion when the Combobox attempts to stop observing the |
| 301 // ComboboxModel. This hack ensures the Combobox is deleted before its |
| 302 // ComboboxModel. |
| 303 // |
| 304 // Technically, the MenuButton has the same problem, but MenuButton doesn't |
| 305 // use its model in its destructor. |
| 306 if (combobox_) |
| 307 RemoveChildView(combobox_); |
| 308 } |
| 309 |
| 310 void PermissionSelectorView::InitializeMenuButtonView( |
| 311 views::GridLayout* layout, |
| 312 const WebsiteSettingsUI::PermissionInfo& permission) { |
| 313 bool button_enabled = |
| 314 permission.source == content_settings::SETTING_SOURCE_USER; |
| 315 menu_button_ = new internal::PermissionMenuButton( |
| 316 WebsiteSettingsUI::PermissionActionToUIString( |
| 317 permission.type, permission.setting, permission.default_setting, |
| 318 permission.source), |
| 319 menu_model_.get(), button_enabled); |
| 320 menu_button_->SetEnabled(button_enabled); |
| 321 menu_button_->SetAccessibleName( |
| 322 WebsiteSettingsUI::PermissionTypeToUIString(permission.type)); |
| 323 layout->AddView(menu_button_); |
| 324 } |
| 325 |
| 326 void PermissionSelectorView::InitializeComboboxView( |
| 327 views::GridLayout* layout, |
| 328 const WebsiteSettingsUI::PermissionInfo& permission) { |
| 329 bool button_enabled = |
| 330 permission.source == content_settings::SETTING_SOURCE_USER; |
| 331 combobox_model_adapter_.reset( |
| 332 new internal::ComboboxModelAdapter(menu_model_.get())); |
| 333 combobox_ = new internal::PermissionCombobox( |
| 334 WebsiteSettingsUI::PermissionActionToUIString( |
| 335 permission.type, permission.setting, permission.default_setting, |
| 336 permission.source), |
| 337 combobox_model_adapter_.get(), button_enabled, |
| 338 true); |
| 339 combobox_->SetEnabled(button_enabled); |
| 340 combobox_->SetAccessibleName( |
| 341 WebsiteSettingsUI::PermissionTypeToUIString(permission.type)); |
| 342 layout->AddView(combobox_); |
| 203 } | 343 } |
| 204 | 344 |
| 205 void PermissionSelectorView::PermissionChanged( | 345 void PermissionSelectorView::PermissionChanged( |
| 206 const WebsiteSettingsUI::PermissionInfo& permission) { | 346 const WebsiteSettingsUI::PermissionInfo& permission) { |
| 207 // Change the permission icon to reflect the selected setting. | 347 // Change the permission icon to reflect the selected setting. |
| 208 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission); | 348 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission); |
| 209 icon_->SetImage(image.ToImageSkia()); | 349 icon_->SetImage(image.ToImageSkia()); |
| 210 | 350 |
| 351 LOG(ERROR) << "PermissionChanged"; |
| 352 |
| 211 // Update the menu button text to reflect the new setting. | 353 // Update the menu button text to reflect the new setting. |
| 212 menu_button_->SetText(WebsiteSettingsUI::PermissionActionToUIString( | 354 if (menu_button_) { |
| 213 permission.type, permission.setting, permission.default_setting, | 355 menu_button_->SetText(WebsiteSettingsUI::PermissionActionToUIString( |
| 214 content_settings::SETTING_SOURCE_USER)); | 356 permission.type, permission.setting, permission.default_setting, |
| 215 menu_button_->SizeToPreferredSize(); | 357 content_settings::SETTING_SOURCE_USER)); |
| 358 menu_button_->SizeToPreferredSize(); |
| 359 } else if (combobox_) { |
| 360 bool use_default = permission.setting == CONTENT_SETTING_DEFAULT; |
| 361 combobox_->UpdateSelectedIndex(use_default); |
| 362 } |
| 216 | 363 |
| 217 FOR_EACH_OBSERVER(PermissionSelectorViewObserver, | 364 FOR_EACH_OBSERVER(PermissionSelectorViewObserver, |
| 218 observer_list_, | 365 observer_list_, |
| 219 OnPermissionChanged(permission)); | 366 OnPermissionChanged(permission)); |
| 220 } | 367 } |
| OLD | NEW |