1 // Copyright 2014 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.
5 #include "chrome/browser/ui/views/website_settings/permissions_bubble_view.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
9 #include "grit/generated_resources.h"
10 #include "ui/base/l10n/l10n_util.h"
11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/gfx/text_constants.h"
13 #include "ui/views/bubble/bubble_delegate.h"
14 #include "ui/views/controls/button/checkbox.h"
15 #include "ui/views/controls/button/label_button.h"
16 #include "ui/views/controls/label.h"
17 #include "ui/views/layout/box_layout.h"
18 #include "ui/views/layout/grid_layout.h"
22 // Spacing constant for outer margin. This is added to the
23 // bubble margin itself to equalize the margins at 20px.
24 const int kBubbleOuterMargin
= 12;
26 // Spacing between major items should be 10px.
27 const int kItemMajorSpacing
= 10;
29 // Button border size, draws inside the spacing distance.
30 const int kButtonBorderSize
= 2;
34 // View implementation for the permissions bubble.
35 class PermissionsBubbleDelegateView
: public views::BubbleDelegateView
,
36 public views::ButtonListener
{
38 explicit PermissionsBubbleDelegateView(
40 PermissionBubbleViewViews
* owner
,
41 const std::vector
<PermissionBubbleRequest
*>& requests
,
42 const std::vector
<bool>& accept_state
,
43 bool customization_mode
);
44 virtual ~PermissionsBubbleDelegateView();
47 void SizeToContents();
49 // BubbleDelegateView:
50 virtual bool ShouldShowCloseButton() const OVERRIDE
;
51 virtual bool ShouldShowWindowTitle() const OVERRIDE
;
52 virtual base::string16
GetWindowTitle() const OVERRIDE
;
53 virtual void OnWidgetDestroying(views::Widget
* widget
) OVERRIDE
;
56 virtual void ButtonPressed(views::Button
* button
,
57 const ui::Event
& event
) OVERRIDE
;
60 PermissionBubbleViewViews
* owner_
;
61 views::Button
* allow_
;
63 views::Button
* customize_
;
64 base::string16 title_
;
66 DISALLOW_COPY_AND_ASSIGN(PermissionsBubbleDelegateView
);
69 PermissionsBubbleDelegateView::PermissionsBubbleDelegateView(
71 PermissionBubbleViewViews
* owner
,
72 const std::vector
<PermissionBubbleRequest
*>& requests
,
73 const std::vector
<bool>& accept_state
,
74 bool customization_mode
)
75 : views::BubbleDelegateView(anchor
, views::BubbleBorder::TOP_LEFT
),
80 RemoveAllChildViews(true);
81 set_close_on_esc(false);
82 set_close_on_deactivate(false);
84 SetLayoutManager(new views::BoxLayout(
85 views::BoxLayout::kVertical
, kBubbleOuterMargin
, 0, kItemMajorSpacing
));
87 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
89 if (requests
.size() == 1) {
90 title_
= requests
[0]->GetMessageText();
92 GetWidget()->UpdateWindowTitle();
94 for (std::vector
<PermissionBubbleRequest
*>::const_iterator it
=
96 it
!= requests
.end(); it
++) {
97 if (customization_mode
) {
98 views::Checkbox
* label
=
99 new views::Checkbox((*it
)->GetMessageTextFragment());
100 label
->SetFontList(rb
.GetFontList(ui::ResourceBundle::MediumFont
));
101 label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
104 // TODO(gbillock): i18n the bullet string?
105 const base::string16 bullet
= base::UTF8ToUTF16(" • ");
106 views::Label
* label
=
107 new views::Label(bullet
+ (*it
)->GetMessageTextFragment());
108 label
->SetFontList(rb
.GetFontList(ui::ResourceBundle::MediumFont
));
109 label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
115 views::View
* button_row
= new views::View();
116 views::GridLayout
* button_layout
= new views::GridLayout(button_row
);
117 views::ColumnSet
* columns
= button_layout
->AddColumnSet(0);
118 columns
->AddColumn(views::GridLayout::LEADING
, views::GridLayout::CENTER
,
119 100.0, views::GridLayout::USE_PREF
, 0, 0);
120 columns
->AddColumn(views::GridLayout::TRAILING
, views::GridLayout::FILL
,
121 0, views::GridLayout::USE_PREF
, 0, 0);
122 if (!customization_mode
) {
123 columns
->AddPaddingColumn(0, kItemMajorSpacing
- (2*kButtonBorderSize
));
124 columns
->AddColumn(views::GridLayout::TRAILING
, views::GridLayout::FILL
,
125 0, views::GridLayout::USE_PREF
, 0, 0);
128 button_row
->SetLayoutManager(button_layout
);
129 AddChildView(button_row
);
131 button_layout
->StartRow(0, 0);
133 // Customization case: empty "Customize" label and an "OK" button
134 if (customization_mode
) {
135 button_layout
->AddView(new views::View());
137 views::LabelButton
* ok_button
=
138 new views::LabelButton(this, l10n_util::GetStringUTF16(
140 ok_button
->SetStyle(views::Button::STYLE_BUTTON
);
141 button_layout
->AddView(ok_button
);
144 button_layout
->AddPaddingRow(0, kBubbleOuterMargin
);
148 // Only show the "Customize" button if there is more than one option.
149 if (requests
.size() > 1) {
150 views::LabelButton
* customize
= new views::LabelButton(this,
151 l10n_util::GetStringUTF16(IDS_PERMISSION_CUSTOMIZE
));
152 customize
->SetStyle(views::Button::STYLE_TEXTBUTTON
);
153 customize
->SetTextColor(views::Button::STATE_NORMAL
, SK_ColorBLUE
);
154 customize
->SetTextColor(views::Button::STATE_HOVERED
, SK_ColorBLUE
);
155 customize
->SetTextColor(views::Button::STATE_PRESSED
, SK_ColorBLUE
);
156 button_layout
->AddView(customize
);
158 button_layout
->AddView(new views::View());
161 // Lay out the Deny/Allow buttons. Use custom text if there is only
162 // one permission request.
163 base::string16 deny_text
;
164 base::string16 allow_text
;
165 if (requests
.size() == 1) {
166 deny_text
= requests
[0]->GetAlternateDenyButtonText();
167 allow_text
= requests
[0]->GetAlternateAcceptButtonText();
170 if (deny_text
.empty())
171 deny_text
= l10n_util::GetStringUTF16(IDS_PERMISSION_DENY
);
172 if (allow_text
.empty())
173 allow_text
= l10n_util::GetStringUTF16(IDS_PERMISSION_ALLOW
);
175 views::LabelButton
* deny_button
= new views::LabelButton(this, deny_text
);
176 deny_button
->SetStyle(views::Button::STYLE_BUTTON
);
177 deny_button
->SetFontList(rb
.GetFontList(ui::ResourceBundle::MediumFont
));
178 button_layout
->AddView(deny_button
);
181 views::LabelButton
* allow_button
= new views::LabelButton(this, allow_text
);
182 allow_button
->SetStyle(views::Button::STYLE_BUTTON
);
183 allow_button
->SetFontList(rb
.GetFontList(ui::ResourceBundle::MediumFont
));
184 button_layout
->AddView(allow_button
);
185 allow_
= allow_button
;
187 button_layout
->AddPaddingRow(0, kBubbleOuterMargin
);
190 PermissionsBubbleDelegateView::~PermissionsBubbleDelegateView() {
195 void PermissionsBubbleDelegateView::ResetOwner() {
199 bool PermissionsBubbleDelegateView::ShouldShowCloseButton() const {
203 bool PermissionsBubbleDelegateView::ShouldShowWindowTitle() const {
207 base::string16
PermissionsBubbleDelegateView::GetWindowTitle() const {
208 if (!title_
.empty()) {
212 return l10n_util::GetStringUTF16(IDS_PERMISSIONS_BUBBLE_PROMPT
);
215 void PermissionsBubbleDelegateView::SizeToContents() {
216 BubbleDelegateView::SizeToContents();
219 void PermissionsBubbleDelegateView::OnWidgetDestroying(views::Widget
* widget
) {
220 views::BubbleDelegateView::OnWidgetDestroying(widget
);
227 void PermissionsBubbleDelegateView::ButtonPressed(views::Button
* button
,
228 const ui::Event
& event
) {
232 if (button
== allow_
)
234 else if (button
== deny_
)
236 else if (button
== customize_
)
237 owner_
->SetCustomizationMode();
240 PermissionBubbleViewViews::PermissionBubbleViewViews(views::View
* anchor_view
)
241 : anchor_view_(anchor_view
),
243 bubble_delegate_(NULL
) {}
245 PermissionBubbleViewViews::~PermissionBubbleViewViews() {}
247 void PermissionBubbleViewViews::SetDelegate(Delegate
* delegate
) {
248 delegate_
= delegate
;
251 void PermissionBubbleViewViews::Show(
252 const std::vector
<PermissionBubbleRequest
*>& requests
,
253 const std::vector
<bool>& values
,
254 bool customization_mode
) {
255 if (bubble_delegate_
!= NULL
) {
256 bubble_delegate_
->ResetOwner();
257 bubble_delegate_
->StartFade(false);
260 PermissionsBubbleDelegateView
* bubble_delegate
=
261 new PermissionsBubbleDelegateView(anchor_view_
, this,
262 requests
, values
, customization_mode
);
263 bubble_delegate_
= bubble_delegate
;
264 views::BubbleDelegateView::CreateBubble(bubble_delegate_
);
266 bubble_delegate_
->StartFade(true);
267 bubble_delegate
->SizeToContents();
270 void PermissionBubbleViewViews::Hide() {
271 if (bubble_delegate_
) {
272 bubble_delegate_
->ResetOwner();
273 bubble_delegate_
->StartFade(false);
277 void PermissionBubbleViewViews::Closing() {
278 if (bubble_delegate_
)
279 bubble_delegate_
= NULL
;
281 delegate_
->Closing();
284 void PermissionBubbleViewViews::Toggle(int index
, bool value
) {
286 delegate_
->ToggleAccept(index
, value
);
289 void PermissionBubbleViewViews::Accept() {
294 void PermissionBubbleViewViews::Deny() {
299 void PermissionBubbleViewViews::SetCustomizationMode() {
301 delegate_
->SetCustomizationMode();