Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1000)

Unified Diff: chrome/browser/ui/views/content_setting_bubble_contents.cc

Issue 12208010: Adding device selection menus to the content setting bubble (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed the final comments. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/views/content_setting_bubble_contents.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/views/content_setting_bubble_contents.cc
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index 7a01e388149a61df764e1164a9ddb37189604b31..f411559e09f68eb1c12804e55ff8a54e888ada2a 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -1,330 +1,489 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/content_setting_bubble_contents.h"
-
-#include <algorithm>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/content_settings/host_content_settings_map.h"
-#include "chrome/browser/plugins/plugin_finder.h"
-#include "chrome/browser/plugins/plugin_metadata.h"
-#include "chrome/browser/ui/chrome_style.h"
-#include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
-#include "chrome/browser/ui/views/browser_dialogs.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/plugin_service.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/views/controls/button/radio_button.h"
-#include "ui/views/controls/button/text_button.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/controls/link.h"
-#include "ui/views/controls/separator.h"
-#include "ui/views/layout/grid_layout.h"
-#include "ui/views/layout/layout_constants.h"
-
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
-
-// If we don't clamp the maximum width, then very long URLs and titles can make
-// the bubble arbitrarily wide.
-const int kMaxContentsWidth = 500;
-
-// When we have multiline labels, we should set a minimum width lest we get very
-// narrow bubbles with lots of line-wrapping.
-const int kMinMultiLineContentsWidth = 250;
-
-using content::PluginService;
-using content::WebContents;
-
-class ContentSettingBubbleContents::Favicon : public views::ImageView {
- public:
- Favicon(const gfx::Image& image,
- ContentSettingBubbleContents* parent,
- views::Link* link);
- virtual ~Favicon();
-
- private:
- // views::View overrides:
- virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
- virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
- virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
-
- ContentSettingBubbleContents* parent_;
- views::Link* link_;
-};
-
-ContentSettingBubbleContents::Favicon::Favicon(
- const gfx::Image& image,
- ContentSettingBubbleContents* parent,
- views::Link* link)
- : parent_(parent),
- link_(link) {
- SetImage(image.AsImageSkia());
-}
-
-ContentSettingBubbleContents::Favicon::~Favicon() {
-}
-
-bool ContentSettingBubbleContents::Favicon::OnMousePressed(
- const ui::MouseEvent& event) {
- return event.IsLeftMouseButton() || event.IsMiddleMouseButton();
-}
-
-void ContentSettingBubbleContents::Favicon::OnMouseReleased(
- const ui::MouseEvent& event) {
- if ((event.IsLeftMouseButton() || event.IsMiddleMouseButton()) &&
- HitTestPoint(event.location())) {
- parent_->LinkClicked(link_, event.flags());
- }
-}
-
-gfx::NativeCursor ContentSettingBubbleContents::Favicon::GetCursor(
- const ui::MouseEvent& event) {
-#if defined(USE_AURA)
- return ui::kCursorHand;
-#elif defined(OS_WIN)
- static HCURSOR g_hand_cursor = LoadCursor(NULL, IDC_HAND);
- return g_hand_cursor;
-#endif
-}
-
-ContentSettingBubbleContents::ContentSettingBubbleContents(
- ContentSettingBubbleModel* content_setting_bubble_model,
- WebContents* web_contents,
- views::View* anchor_view,
- views::BubbleBorder::ArrowLocation arrow_location)
- : BubbleDelegateView(anchor_view, arrow_location),
- content_setting_bubble_model_(content_setting_bubble_model),
- web_contents_(web_contents),
- custom_link_(NULL),
- manage_link_(NULL),
- close_button_(NULL) {
- // Compensate for built-in vertical padding in the anchor view's image.
- set_anchor_insets(gfx::Insets(5, 0, 5, 0));
-
- registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(web_contents));
-}
-
-ContentSettingBubbleContents::~ContentSettingBubbleContents() {
-}
-
-gfx::Size ContentSettingBubbleContents::GetPreferredSize() {
- gfx::Size preferred_size(views::View::GetPreferredSize());
- int preferred_width =
- (!content_setting_bubble_model_->bubble_content().domain_lists.empty() &&
- (kMinMultiLineContentsWidth > preferred_size.width())) ?
- kMinMultiLineContentsWidth : preferred_size.width();
- preferred_size.set_width(std::min(preferred_width, kMaxContentsWidth));
- return preferred_size;
-}
-
-void ContentSettingBubbleContents::Init() {
- using views::GridLayout;
-
- GridLayout* layout = new views::GridLayout(this);
- SetLayoutManager(layout);
-
- const int kSingleColumnSetId = 0;
- views::ColumnSet* column_set = layout->AddColumnSet(kSingleColumnSetId);
- column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
- GridLayout::USE_PREF, 0, 0);
-
- const ContentSettingBubbleModel::BubbleContent& bubble_content =
- content_setting_bubble_model_->bubble_content();
- bool bubble_content_empty = true;
-
- if (!bubble_content.title.empty()) {
- views::Label* title_label = new views::Label(UTF8ToUTF16(
- bubble_content.title));
- layout->StartRow(0, kSingleColumnSetId);
- layout->AddView(title_label);
- bubble_content_empty = false;
- }
-
- const std::set<std::string>& plugins = bubble_content.resource_identifiers;
- if (!plugins.empty()) {
- if (!bubble_content_empty)
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- PluginFinder* finder = PluginFinder::GetInstance();
- for (std::set<std::string>::const_iterator i(plugins.begin());
- i != plugins.end(); ++i) {
- string16 name = finder->FindPluginNameWithIdentifier(*i);
- layout->StartRow(0, kSingleColumnSetId);
- layout->AddView(new views::Label(name));
- bubble_content_empty = false;
- }
- }
-
- if (content_setting_bubble_model_->content_type() ==
- CONTENT_SETTINGS_TYPE_POPUPS) {
- const int kPopupColumnSetId = 2;
- views::ColumnSet* popup_column_set =
- layout->AddColumnSet(kPopupColumnSetId);
- popup_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
- GridLayout::USE_PREF, 0, 0);
- popup_column_set->AddPaddingColumn(
- 0, views::kRelatedControlHorizontalSpacing);
- popup_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
- GridLayout::USE_PREF, 0, 0);
-
- for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator
- i(bubble_content.popup_items.begin());
- i != bubble_content.popup_items.end(); ++i) {
- if (!bubble_content_empty)
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- layout->StartRow(0, kPopupColumnSetId);
-
- views::Link* link = new views::Link(UTF8ToUTF16(i->title));
- link->set_listener(this);
- link->SetElideBehavior(views::Label::ELIDE_IN_MIDDLE);
- popup_links_[link] = i - bubble_content.popup_items.begin();
- layout->AddView(new Favicon(i->image, this, link));
- layout->AddView(link);
- bubble_content_empty = false;
- }
- }
-
- const int indented_kSingleColumnSetId = 3;
- // Insert a column set with greater indent.
- views::ColumnSet* indented_single_column_set =
- layout->AddColumnSet(indented_kSingleColumnSetId);
- indented_single_column_set->AddPaddingColumn(
- 0, chrome_style::kCheckboxIndent);
- indented_single_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
- 1, GridLayout::USE_PREF, 0, 0);
-
- const ContentSettingBubbleModel::RadioGroup& radio_group =
- bubble_content.radio_group;
- if (!radio_group.radio_items.empty()) {
- if (!bubble_content_empty)
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- for (ContentSettingBubbleModel::RadioItems::const_iterator i(
- radio_group.radio_items.begin());
- i != radio_group.radio_items.end(); ++i) {
- views::RadioButton* radio = new views::RadioButton(UTF8ToUTF16(*i), 0);
- radio->SetEnabled(bubble_content.radio_group_enabled);
- radio->set_listener(this);
- radio_group_.push_back(radio);
- layout->StartRow(0, indented_kSingleColumnSetId);
- layout->AddView(radio);
- bubble_content_empty = false;
- }
- DCHECK(!radio_group_.empty());
- // Now that the buttons have been added to the view hierarchy, it's safe
- // to call SetChecked() on them.
- radio_group_[radio_group.default_item]->SetChecked(true);
- }
-
- gfx::Font domain_font =
- views::Label().font().DeriveFont(0, gfx::Font::BOLD);
- for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i(
- bubble_content.domain_lists.begin());
- i != bubble_content.domain_lists.end(); ++i) {
- layout->StartRow(0, kSingleColumnSetId);
- views::Label* section_title = new views::Label(UTF8ToUTF16(i->title));
- section_title->SetMultiLine(true);
- section_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- layout->AddView(section_title, 1, 1, GridLayout::FILL, GridLayout::LEADING);
- for (std::set<std::string>::const_iterator j = i->hosts.begin();
- j != i->hosts.end(); ++j) {
- layout->StartRow(0, indented_kSingleColumnSetId);
- layout->AddView(new views::Label(UTF8ToUTF16(*j), domain_font));
- }
- bubble_content_empty = false;
- }
-
- if (!bubble_content.custom_link.empty()) {
- custom_link_ = new views::Link(UTF8ToUTF16(bubble_content.custom_link));
- custom_link_->SetEnabled(bubble_content.custom_link_enabled);
- custom_link_->set_listener(this);
- if (!bubble_content_empty)
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- layout->StartRow(0, kSingleColumnSetId);
- layout->AddView(custom_link_);
- bubble_content_empty = false;
- }
-
- if (!bubble_content_empty) {
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- layout->StartRow(0, kSingleColumnSetId);
- layout->AddView(new views::Separator, 1, 1,
- GridLayout::FILL, GridLayout::FILL);
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- }
-
- const int kDoubleColumnSetId = 1;
- views::ColumnSet* double_column_set =
- layout->AddColumnSet(kDoubleColumnSetId);
- double_column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
- GridLayout::USE_PREF, 0, 0);
- double_column_set->AddPaddingColumn(
- 0, views::kUnrelatedControlHorizontalSpacing);
- double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
- GridLayout::USE_PREF, 0, 0);
-
- layout->StartRow(0, kDoubleColumnSetId);
- manage_link_ = new views::Link(UTF8ToUTF16(bubble_content.manage_link));
- manage_link_->set_listener(this);
- layout->AddView(manage_link_);
-
- close_button_ = new views::NativeTextButton(
- this, l10n_util::GetStringUTF16(IDS_DONE));
- layout->AddView(close_button_);
-}
-
-void ContentSettingBubbleContents::ButtonPressed(views::Button* sender,
- const ui::Event& event) {
- if (sender == close_button_) {
- content_setting_bubble_model_->OnDoneClicked();
- StartFade(false);
- return;
- }
-
- for (RadioGroup::const_iterator i(radio_group_.begin());
- i != radio_group_.end(); ++i) {
- if (sender == *i) {
- content_setting_bubble_model_->OnRadioClicked(i - radio_group_.begin());
- return;
- }
- }
- NOTREACHED() << "unknown radio";
-}
-
-void ContentSettingBubbleContents::LinkClicked(views::Link* source,
- int event_flags) {
- if (source == custom_link_) {
- content_setting_bubble_model_->OnCustomLinkClicked();
- StartFade(false);
- return;
- }
- if (source == manage_link_) {
- StartFade(false);
- content_setting_bubble_model_->OnManageLinkClicked();
- // CAREFUL: Showing the settings window activates it, which deactivates the
- // info bubble, which causes it to close, which deletes us.
- return;
- }
-
- PopupLinks::const_iterator i(popup_links_.find(source));
- DCHECK(i != popup_links_.end());
- content_setting_bubble_model_->OnPopupClicked(i->second);
-}
-
-void ContentSettingBubbleContents::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, type);
- DCHECK(source == content::Source<WebContents>(web_contents_));
- web_contents_ = NULL;
-}
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/content_setting_bubble_contents.h"
+
+#include <algorithm>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/stl_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/plugins/plugin_finder.h"
+#include "chrome/browser/plugins/plugin_metadata.h"
+#include "chrome/browser/ui/chrome_style.h"
+#include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
+#include "chrome/browser/ui/content_settings/content_setting_media_menu_model.h"
+#include "chrome/browser/ui/views/browser_dialogs.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/web_contents.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/views/controls/button/menu_button.h"
+#include "ui/views/controls/button/radio_button.h"
+#include "ui/views/controls/button/text_button.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/link.h"
+#include "ui/views/controls/menu/menu.h"
+#include "ui/views/controls/menu/menu_model_adapter.h"
+#include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/controls/separator.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_constants.h"
+
+#if defined(USE_AURA)
+#include "ui/base/cursor/cursor.h"
+#endif
+
+namespace {
+
+// If we don't clamp the maximum width, then very long URLs and titles can make
+// the bubble arbitrarily wide.
+const int kMaxContentsWidth = 500;
+
+// When we have multiline labels, we should set a minimum width lest we get very
+// narrow bubbles with lots of line-wrapping.
+const int kMinMultiLineContentsWidth = 250;
+
+// The minimum and maximum width of the media menu buttons.
+const int kMinMediaMenuButtonWidth = 100;
+const int kMaxMediaMenuButtonWidth = 600;
+
+}
+
+using content::PluginService;
+using content::WebContents;
+
+
+// ContentSettingBubbleContents::Favicon --------------------------------------
+
+class ContentSettingBubbleContents::Favicon : public views::ImageView {
+ public:
+ Favicon(const gfx::Image& image,
+ ContentSettingBubbleContents* parent,
+ views::Link* link);
+ virtual ~Favicon();
+
+ private:
+ // views::View overrides:
+ virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
+ virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
+
+ ContentSettingBubbleContents* parent_;
+ views::Link* link_;
+};
+
+ContentSettingBubbleContents::Favicon::Favicon(
+ const gfx::Image& image,
+ ContentSettingBubbleContents* parent,
+ views::Link* link)
+ : parent_(parent),
+ link_(link) {
+ SetImage(image.AsImageSkia());
+}
+
+ContentSettingBubbleContents::Favicon::~Favicon() {
+}
+
+bool ContentSettingBubbleContents::Favicon::OnMousePressed(
+ const ui::MouseEvent& event) {
+ return event.IsLeftMouseButton() || event.IsMiddleMouseButton();
+}
+
+void ContentSettingBubbleContents::Favicon::OnMouseReleased(
+ const ui::MouseEvent& event) {
+ if ((event.IsLeftMouseButton() || event.IsMiddleMouseButton()) &&
+ HitTestPoint(event.location())) {
+ parent_->LinkClicked(link_, event.flags());
+ }
+}
+
+gfx::NativeCursor ContentSettingBubbleContents::Favicon::GetCursor(
+ const ui::MouseEvent& event) {
+#if defined(USE_AURA)
+ return ui::kCursorHand;
+#elif defined(OS_WIN)
+ static HCURSOR g_hand_cursor = LoadCursor(NULL, IDC_HAND);
+ return g_hand_cursor;
+#endif
+}
+
+
+// ContentSettingBubbleContents::MediaMenuParts -------------------------------
+
+struct ContentSettingBubbleContents::MediaMenuParts {
+ explicit MediaMenuParts(content::MediaStreamType type);
+ ~MediaMenuParts();
+
+ content::MediaStreamType type;
+ scoped_ptr<ui::SimpleMenuModel> menu_model;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MediaMenuParts);
+};
+
+ContentSettingBubbleContents::MediaMenuParts::MediaMenuParts(
+ content::MediaStreamType type)
+ : type(type) {}
+
+ContentSettingBubbleContents::MediaMenuParts::~MediaMenuParts() {}
+
+
+// ContentSettingBubbleContents -----------------------------------------------
+
+ContentSettingBubbleContents::ContentSettingBubbleContents(
+ ContentSettingBubbleModel* content_setting_bubble_model,
+ WebContents* web_contents,
+ views::View* anchor_view,
+ views::BubbleBorder::ArrowLocation arrow_location)
+ : BubbleDelegateView(anchor_view, arrow_location),
+ content_setting_bubble_model_(content_setting_bubble_model),
+ web_contents_(web_contents),
+ custom_link_(NULL),
+ manage_link_(NULL),
+ close_button_(NULL) {
+ // Compensate for built-in vertical padding in the anchor view's image.
+ set_anchor_insets(gfx::Insets(5, 0, 5, 0));
+
+ registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::Source<WebContents>(web_contents));
+}
+
+ContentSettingBubbleContents::~ContentSettingBubbleContents() {
+ STLDeleteValues(&media_menus_);
+}
+
+gfx::Size ContentSettingBubbleContents::GetPreferredSize() {
+ gfx::Size preferred_size(views::View::GetPreferredSize());
+ int preferred_width =
+ (!content_setting_bubble_model_->bubble_content().domain_lists.empty() &&
+ (kMinMultiLineContentsWidth > preferred_size.width())) ?
+ kMinMultiLineContentsWidth : preferred_size.width();
+ preferred_size.set_width(std::min(preferred_width, kMaxContentsWidth));
+ return preferred_size;
+}
+
+void ContentSettingBubbleContents::UpdateMenuLabel(
+ content::MediaStreamType type,
+ const std::string& label) {
+ for (MediaMenuPartsMap::const_iterator it = media_menus_.begin();
+ it != media_menus_.end(); ++it) {
+ if (it->second->type == type) {
+ it->first->SetText(UTF8ToUTF16(label));
+ return;
+ }
+ }
+ NOTREACHED();
+}
+
+void ContentSettingBubbleContents::Init() {
+ using views::GridLayout;
+
+ GridLayout* layout = new views::GridLayout(this);
+ SetLayoutManager(layout);
+
+ const int kSingleColumnSetId = 0;
+ views::ColumnSet* column_set = layout->AddColumnSet(kSingleColumnSetId);
+ column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+
+ const ContentSettingBubbleModel::BubbleContent& bubble_content =
+ content_setting_bubble_model_->bubble_content();
+ bool bubble_content_empty = true;
+
+ if (!bubble_content.title.empty()) {
+ views::Label* title_label = new views::Label(UTF8ToUTF16(
+ bubble_content.title));
+ layout->StartRow(0, kSingleColumnSetId);
+ layout->AddView(title_label);
+ bubble_content_empty = false;
+ }
+
+ const std::set<std::string>& plugins = bubble_content.resource_identifiers;
+ if (!plugins.empty()) {
+ if (!bubble_content_empty)
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ PluginFinder* finder = PluginFinder::GetInstance();
+ for (std::set<std::string>::const_iterator i(plugins.begin());
+ i != plugins.end(); ++i) {
+ string16 name = finder->FindPluginNameWithIdentifier(*i);
+ layout->StartRow(0, kSingleColumnSetId);
+ layout->AddView(new views::Label(name));
+ bubble_content_empty = false;
+ }
+ }
+
+ if (content_setting_bubble_model_->content_type() ==
+ CONTENT_SETTINGS_TYPE_POPUPS) {
+ const int kPopupColumnSetId = 2;
+ views::ColumnSet* popup_column_set =
+ layout->AddColumnSet(kPopupColumnSetId);
+ popup_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
+ GridLayout::USE_PREF, 0, 0);
+ popup_column_set->AddPaddingColumn(
+ 0, views::kRelatedControlHorizontalSpacing);
+ popup_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+
+ for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator
+ i(bubble_content.popup_items.begin());
+ i != bubble_content.popup_items.end(); ++i) {
+ if (!bubble_content_empty)
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout->StartRow(0, kPopupColumnSetId);
+
+ views::Link* link = new views::Link(UTF8ToUTF16(i->title));
+ link->set_listener(this);
+ link->SetElideBehavior(views::Label::ELIDE_IN_MIDDLE);
+ popup_links_[link] = i - bubble_content.popup_items.begin();
+ layout->AddView(new Favicon(i->image, this, link));
+ layout->AddView(link);
+ bubble_content_empty = false;
+ }
+ }
+
+ const int indented_kSingleColumnSetId = 3;
+ // Insert a column set with greater indent.
+ views::ColumnSet* indented_single_column_set =
+ layout->AddColumnSet(indented_kSingleColumnSetId);
+ indented_single_column_set->AddPaddingColumn(
+ 0, chrome_style::kCheckboxIndent);
+ indented_single_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
+ 1, GridLayout::USE_PREF, 0, 0);
+
+ const ContentSettingBubbleModel::RadioGroup& radio_group =
+ bubble_content.radio_group;
+ if (!radio_group.radio_items.empty()) {
+ if (!bubble_content_empty)
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ for (ContentSettingBubbleModel::RadioItems::const_iterator i(
+ radio_group.radio_items.begin());
+ i != radio_group.radio_items.end(); ++i) {
+ views::RadioButton* radio = new views::RadioButton(UTF8ToUTF16(*i), 0);
+ radio->SetEnabled(bubble_content.radio_group_enabled);
+ radio->set_listener(this);
+ radio_group_.push_back(radio);
+ layout->StartRow(0, indented_kSingleColumnSetId);
+ layout->AddView(radio);
+ bubble_content_empty = false;
+ }
+ DCHECK(!radio_group_.empty());
+ // Now that the buttons have been added to the view hierarchy, it's safe
+ // to call SetChecked() on them.
+ radio_group_[radio_group.default_item]->SetChecked(true);
+ }
+
+ // Layout code for the media device menus.
+ if (content_setting_bubble_model_->content_type() ==
+ CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
+ const int kMediaMenuColumnSetId = 2;
+ views::ColumnSet* menu_column_set =
+ layout->AddColumnSet(kMediaMenuColumnSetId);
+ menu_column_set->AddPaddingColumn(
+ 0, chrome_style::kCheckboxIndent);
+ menu_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
+ GridLayout::USE_PREF, 0, 0);
+ menu_column_set->AddPaddingColumn(
+ 0, views::kRelatedControlHorizontalSpacing);
+ menu_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+
+ int menu_width = 0;
+ for (ContentSettingBubbleModel::MediaMenuMap::const_iterator i(
+ bubble_content.media_menus.begin());
+ i != bubble_content.media_menus.end(); ++i) {
+ if (!bubble_content_empty)
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout->StartRow(0, kMediaMenuColumnSetId);
+
+ views::Label* label = new views::Label(UTF8ToUTF16(i->second.label));
+ label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+
+ views::MenuButton* menu_button = new views::MenuButton(
+ NULL, UTF8ToUTF16((i->second.selected_device.name)), this, false);
+ menu_button->set_alignment(views::TextButton::ALIGN_LEFT);
+ menu_button->set_border(
+ new views::TextButtonNativeThemeBorder(menu_button));
+ menu_button->set_animate_on_state_change(false);
+
+ MediaMenuParts* menu_view = new MediaMenuParts(i->first);
+ menu_view->menu_model.reset(new ContentSettingMediaMenuModel(
+ i->first,
+ content_setting_bubble_model_.get(),
+ base::Bind(&ContentSettingBubbleContents::UpdateMenuLabel,
+ base::Unretained(this))));
+ media_menus_[menu_button] = menu_view;
+
+ // Use the longest width of the menus as the width of the menu buttons.
+ menu_width = std::max(menu_width,
+ GetPreferredMediaMenuWidth(
+ menu_button, menu_view->menu_model.get()));
+
+ layout->AddView(label);
+ layout->AddView(menu_button);
+
+ bubble_content_empty = false;
+ }
+
+ // Make sure the width is within [kMinMediaMenuButtonWidth,
+ // kMaxMediaMenuButtonWidth].
+ menu_width = std::max(kMinMediaMenuButtonWidth, menu_width);
+ menu_width = std::min(kMaxMediaMenuButtonWidth, menu_width);
+
+ // Set all the menu buttons to the width we calculated above.
+ for (MediaMenuPartsMap::const_iterator i = media_menus_.begin();
+ i != media_menus_.end(); ++i) {
+ i->first->set_min_width(menu_width);
+ i->first->set_max_width(menu_width);
+ }
+ }
+
+ gfx::Font domain_font =
+ views::Label().font().DeriveFont(0, gfx::Font::BOLD);
+ for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i(
+ bubble_content.domain_lists.begin());
+ i != bubble_content.domain_lists.end(); ++i) {
+ layout->StartRow(0, kSingleColumnSetId);
+ views::Label* section_title = new views::Label(UTF8ToUTF16(i->title));
+ section_title->SetMultiLine(true);
+ section_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ layout->AddView(section_title, 1, 1, GridLayout::FILL, GridLayout::LEADING);
+ for (std::set<std::string>::const_iterator j = i->hosts.begin();
+ j != i->hosts.end(); ++j) {
+ layout->StartRow(0, indented_kSingleColumnSetId);
+ layout->AddView(new views::Label(UTF8ToUTF16(*j), domain_font));
+ }
+ bubble_content_empty = false;
+ }
+
+ if (!bubble_content.custom_link.empty()) {
+ custom_link_ = new views::Link(UTF8ToUTF16(bubble_content.custom_link));
+ custom_link_->SetEnabled(bubble_content.custom_link_enabled);
+ custom_link_->set_listener(this);
+ if (!bubble_content_empty)
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout->StartRow(0, kSingleColumnSetId);
+ layout->AddView(custom_link_);
+ bubble_content_empty = false;
+ }
+
+ if (!bubble_content_empty) {
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout->StartRow(0, kSingleColumnSetId);
+ layout->AddView(new views::Separator, 1, 1,
+ GridLayout::FILL, GridLayout::FILL);
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ }
+
+ const int kDoubleColumnSetId = 1;
+ views::ColumnSet* double_column_set =
+ layout->AddColumnSet(kDoubleColumnSetId);
+ double_column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
+ GridLayout::USE_PREF, 0, 0);
+ double_column_set->AddPaddingColumn(
+ 0, views::kUnrelatedControlHorizontalSpacing);
+ double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+
+ layout->StartRow(0, kDoubleColumnSetId);
+ manage_link_ = new views::Link(UTF8ToUTF16(bubble_content.manage_link));
+ manage_link_->set_listener(this);
+ layout->AddView(manage_link_);
+
+ close_button_ = new views::NativeTextButton(
+ this, l10n_util::GetStringUTF16(IDS_DONE));
+ layout->AddView(close_button_);
+}
+
+void ContentSettingBubbleContents::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ if (sender == close_button_) {
+ content_setting_bubble_model_->OnDoneClicked();
+ StartFade(false);
+ return;
+ }
+
+ for (RadioGroup::const_iterator i(radio_group_.begin());
+ i != radio_group_.end(); ++i) {
+ if (sender == *i) {
+ content_setting_bubble_model_->OnRadioClicked(i - radio_group_.begin());
+ return;
+ }
+ }
+ NOTREACHED() << "unknown radio";
+}
+
+void ContentSettingBubbleContents::LinkClicked(views::Link* source,
+ int event_flags) {
+ if (source == custom_link_) {
+ content_setting_bubble_model_->OnCustomLinkClicked();
+ StartFade(false);
+ return;
+ }
+ if (source == manage_link_) {
+ StartFade(false);
+ content_setting_bubble_model_->OnManageLinkClicked();
+ // CAREFUL: Showing the settings window activates it, which deactivates the
+ // info bubble, which causes it to close, which deletes us.
+ return;
+ }
+
+ PopupLinks::const_iterator i(popup_links_.find(source));
+ DCHECK(i != popup_links_.end());
+ content_setting_bubble_model_->OnPopupClicked(i->second);
+}
+
+void ContentSettingBubbleContents::OnMenuButtonClicked(
+ views::View* source,
+ const gfx::Point& point) {
+ MediaMenuPartsMap::iterator i(media_menus_.find(
+ static_cast<views::MenuButton*>(source)));
+ DCHECK(i != media_menus_.end());
+
+ views::MenuModelAdapter menu_model_adapter(i->second->menu_model.get());
+ menu_runner_.reset(new views::MenuRunner(menu_model_adapter.CreateMenu()));
+
+ gfx::Point screen_location;
+ views::View::ConvertPointToScreen(i->first, &screen_location);
+ ignore_result(menu_runner_->RunMenuAt(
+ source->GetWidget(),
+ i->first,
+ gfx::Rect(screen_location, i->first->size()),
+ views::MenuItemView::TOPLEFT,
+ views::MenuRunner::HAS_MNEMONICS));
+}
+
+void ContentSettingBubbleContents::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, type);
+ DCHECK(source == content::Source<WebContents>(web_contents_));
+ web_contents_ = NULL;
+}
+
+int ContentSettingBubbleContents::GetPreferredMediaMenuWidth(
+ views::MenuButton* button,
+ ui::SimpleMenuModel* menu_model) {
+ string16 title = button->text();
+
+ int width = button->GetPreferredSize().width();
+ for (int i = 0; i < menu_model->GetItemCount(); ++i) {
+ button->SetText(menu_model->GetLabelAt(i));
+ width = std::max(width, button->GetPreferredSize().width());
+ }
+
+ // Recover the title for the menu button.
+ button->SetText(title);
+ return width;
+}
« no previous file with comments | « chrome/browser/ui/views/content_setting_bubble_contents.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698