[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / views / sync / one_click_signin_bubble_view.cc
blob118e3aac47d1ade74f056eb7ff50f3632c2b693a
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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/sync/one_click_signin_bubble_view.h"
7 #include "base/callback_helpers.h"
8 #include "base/logging.h"
9 #include "chrome/browser/google/google_util.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
12 #include "chrome/browser/ui/sync/one_click_signin_histogram.h"
13 #include "chrome/common/url_constants.h"
14 #include "grit/chromium_strings.h"
15 #include "grit/generated_resources.h"
16 #include "grit/theme_resources.h"
17 #include "grit/ui_resources.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/events/keycodes/keyboard_codes.h"
21 #include "ui/views/controls/button/image_button.h"
22 #include "ui/views/controls/button/label_button.h"
23 #include "ui/views/controls/image_view.h"
24 #include "ui/views/controls/label.h"
25 #include "ui/views/controls/link.h"
26 #include "ui/views/layout/grid_layout.h"
27 #include "ui/views/layout/layout_constants.h"
28 #include "ui/views/widget/widget.h"
30 // Minimum width of the the bubble.
31 const int kMinBubbleWidth = 310;
33 // Minimum width for the multi-line label.
34 const int kMinimumDialogLabelWidth = 400;
35 const int kMinimumLabelWidth = 240;
36 const int kDialogMargin = 16;
38 namespace {
40 // The column set constants that can be used in the InitContent() function
41 // to layout views.
42 enum OneClickSigninBubbleColumnTypes {
43 COLUMN_SET_FILL_ALIGN,
44 COLUMN_SET_CONTROLS,
45 COLUMN_SET_TITLE_BAR
47 } // namespace
49 // static
50 OneClickSigninBubbleView* OneClickSigninBubbleView::bubble_view_ = NULL;
52 // static
53 void OneClickSigninBubbleView::ShowBubble(
54 BrowserWindow::OneClickSigninBubbleType type,
55 const base::string16& email,
56 const base::string16& error_message,
57 scoped_ptr<OneClickSigninBubbleDelegate> delegate,
58 views::View* anchor_view,
59 const BrowserWindow::StartSyncCallback& start_sync) {
60 if (IsShowing())
61 return;
63 switch (type) {
64 case BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE:
65 bubble_view_ = new OneClickSigninBubbleView(
66 error_message, base::string16(), delegate.Pass(),
67 anchor_view, start_sync, false);
68 break;
69 case BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG:
70 bubble_view_ = new OneClickSigninBubbleView(
71 base::string16(), base::string16(), delegate.Pass(),
72 anchor_view, start_sync, true);
73 break;
74 case BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_SAML_MODAL_DIALOG:
75 bubble_view_ = new OneClickSigninBubbleView(
76 base::string16(), email, delegate.Pass(),
77 anchor_view, start_sync, true);
78 break;
81 views::BubbleDelegateView::CreateBubble(bubble_view_)->Show();
84 // static
85 bool OneClickSigninBubbleView::IsShowing() {
86 return bubble_view_ != NULL;
89 // static
90 void OneClickSigninBubbleView::Hide() {
91 if (IsShowing())
92 bubble_view_->GetWidget()->Close();
95 OneClickSigninBubbleView::OneClickSigninBubbleView(
96 const base::string16& error_message,
97 const base::string16& email,
98 scoped_ptr<OneClickSigninBubbleDelegate> delegate,
99 views::View* anchor_view,
100 const BrowserWindow::StartSyncCallback& start_sync_callback,
101 bool is_sync_dialog)
102 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
103 delegate_(delegate.Pass()),
104 error_message_(error_message),
105 email_(email),
106 start_sync_callback_(start_sync_callback),
107 is_sync_dialog_(is_sync_dialog),
108 advanced_link_(NULL),
109 learn_more_link_(NULL),
110 ok_button_(NULL),
111 undo_button_(NULL),
112 close_button_(NULL),
113 clicked_learn_more_(false) {
114 if (is_sync_dialog_) {
115 DCHECK(!start_sync_callback_.is_null());
116 set_arrow(views::BubbleBorder::NONE);
117 set_anchor_view_insets(gfx::Insets(0, 0, anchor_view->height() / 2, 0));
118 set_close_on_deactivate(false);
120 int margin = is_sync_dialog_ ? kDialogMargin : views::kButtonVEdgeMarginNew;
121 set_margins(gfx::Insets(margin, margin, margin, margin));
124 OneClickSigninBubbleView::~OneClickSigninBubbleView() {
127 ui::ModalType OneClickSigninBubbleView::GetModalType() const {
128 return is_sync_dialog_? ui::MODAL_TYPE_CHILD : ui::MODAL_TYPE_NONE;
131 void OneClickSigninBubbleView::Init() {
132 views::GridLayout* layout = new views::GridLayout(this);
133 SetLayoutManager(layout);
135 SetBorder(views::Border::CreateEmptyBorder(8, 8, 8, 8));
137 // Column set for descriptive text and link.
138 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_FILL_ALIGN);
139 cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
140 views::GridLayout::USE_PREF, 0, 0);
142 // Column set for buttons at bottom of bubble.
143 cs = layout->AddColumnSet(COLUMN_SET_CONTROLS);
144 cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
145 views::GridLayout::USE_PREF, 0, 0);
146 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
147 cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, 0,
148 views::GridLayout::USE_PREF, 0, 0);
149 cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, 0,
150 views::GridLayout::USE_PREF, 0, 0);
152 is_sync_dialog_ ? InitDialogContent(layout) : InitBubbleContent(layout);
154 // Add controls at the bottom.
155 // Don't display the advanced link for the error bubble.
156 if (is_sync_dialog_ || error_message_.empty()) {
157 InitAdvancedLink();
158 layout->StartRow(0, COLUMN_SET_CONTROLS);
159 layout->AddView(advanced_link_);
162 InitButtons(layout);
163 ok_button_->SetIsDefault(true);
165 AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, 0));
168 void OneClickSigninBubbleView::InitBubbleContent(views::GridLayout* layout) {
169 layout->set_minimum_size(gfx::Size(kMinBubbleWidth, 0));
171 // If no error occurred, add title message.
172 if (error_message_.empty()) {
173 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_TITLE_BAR);
174 cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0,
175 views::GridLayout::USE_PREF, 0, 0);
177 layout->StartRow(0, COLUMN_SET_TITLE_BAR);
179 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
180 views::Label* label = new views::Label(
181 l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_TITLE_NEW),
182 rb.GetFontList(ui::ResourceBundle::MediumFont));
183 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
184 layout->AddView(label);
187 layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
190 // Add main text description.
191 layout->StartRow(0, COLUMN_SET_FILL_ALIGN);
193 views::Label* label = !error_message_.empty() ?
194 new views::Label(error_message_) :
195 new views::Label(
196 l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_BUBBLE_MESSAGE));
198 label->SetMultiLine(true);
199 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
200 label->SizeToFit(kMinimumLabelWidth);
201 layout->AddView(label);
203 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
205 layout->StartRow(0, COLUMN_SET_CONTROLS);
207 InitLearnMoreLink();
208 layout->AddView(learn_more_link_);
211 void OneClickSigninBubbleView::InitDialogContent(views::GridLayout* layout) {
212 OneClickSigninHelper::LogConfirmHistogramValue(
213 one_click_signin::HISTOGRAM_CONFIRM_SHOWN);
215 // Column set for title bar.
216 views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_TITLE_BAR);
217 cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
218 views::GridLayout::USE_PREF, 0, 0);
219 cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
220 cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, 0,
221 views::GridLayout::USE_PREF, 0, 0);
223 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
226 layout->StartRow(0, COLUMN_SET_TITLE_BAR);
228 views::Label* label = new views::Label(
229 l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_TITLE_NEW),
230 rb.GetFontList(ui::ResourceBundle::MediumBoldFont));
231 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
232 layout->AddView(label);
234 close_button_ = new views::ImageButton(this);
235 close_button_->SetImage(views::ImageButton::STATE_NORMAL,
236 rb.GetImageNamed(IDR_CLOSE_2).ToImageSkia());
237 close_button_->SetImage(views::ImageButton::STATE_HOVERED,
238 rb.GetImageNamed(IDR_CLOSE_2_H).ToImageSkia());
239 close_button_->SetImage(views::ImageButton::STATE_PRESSED,
240 rb.GetImageNamed(IDR_CLOSE_2_P).ToImageSkia());
242 layout->AddView(close_button_);
245 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
248 layout->StartRow(0, COLUMN_SET_FILL_ALIGN);
250 views::Label* label = new views::Label(
251 l10n_util::GetStringFUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_MESSAGE_NEW,
252 email_));
253 label->SetMultiLine(true);
254 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
255 label->SizeToFit(kMinimumDialogLabelWidth);
256 layout->AddView(label);
258 layout->StartRow(0, COLUMN_SET_FILL_ALIGN);
260 InitLearnMoreLink();
261 layout->AddView(learn_more_link_, 1, 1, views::GridLayout::TRAILING,
262 views::GridLayout::CENTER);
265 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
268 void OneClickSigninBubbleView::InitButtons(views::GridLayout* layout) {
269 GetButtons(&ok_button_, &undo_button_);
270 layout->AddView(ok_button_);
272 if (is_sync_dialog_)
273 layout->AddView(undo_button_);
276 void OneClickSigninBubbleView::GetButtons(views::LabelButton** ok_button,
277 views::LabelButton** undo_button) {
278 base::string16 ok_label = !error_message_.empty() ?
279 l10n_util::GetStringUTF16(IDS_OK) :
280 l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_OK_BUTTON);
282 *ok_button = new views::LabelButton(this, ok_label);
283 (*ok_button)->SetStyle(views::Button::STYLE_BUTTON);
285 // The default size of the buttons is too large. To allow them to be smaller
286 // ignore the minimum default size.,
287 (*ok_button)->set_min_size(gfx::Size());
289 if (is_sync_dialog_) {
290 *undo_button = new views::LabelButton(this, base::string16());
291 (*undo_button)->SetStyle(views::Button::STYLE_BUTTON);
292 (*undo_button)->set_min_size(gfx::Size());
294 base::string16 undo_label =
295 l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_UNDO_BUTTON);
296 (*undo_button)->SetText(undo_label);
300 void OneClickSigninBubbleView::InitAdvancedLink() {
301 advanced_link_ = new views::Link(
302 l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_ADVANCED));
304 advanced_link_->set_listener(this);
305 advanced_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
308 void OneClickSigninBubbleView::InitLearnMoreLink() {
309 learn_more_link_ = new views::Link(
310 l10n_util::GetStringUTF16(IDS_LEARN_MORE));
311 learn_more_link_->set_listener(this);
312 learn_more_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
315 bool OneClickSigninBubbleView::AcceleratorPressed(
316 const ui::Accelerator& accelerator) {
317 if (accelerator.key_code() == ui::VKEY_RETURN ||
318 accelerator.key_code() == ui::VKEY_ESCAPE) {
319 OneClickSigninBubbleView::Hide();
321 if (is_sync_dialog_) {
322 if (accelerator.key_code() == ui::VKEY_RETURN) {
323 OneClickSigninHelper::LogConfirmHistogramValue(
324 clicked_learn_more_ ?
325 one_click_signin::HISTOGRAM_CONFIRM_LEARN_MORE_RETURN :
326 one_click_signin::HISTOGRAM_CONFIRM_RETURN);
328 base::ResetAndReturn(&start_sync_callback_).Run(
329 OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
330 } else if (accelerator.key_code() == ui::VKEY_ESCAPE) {
331 OneClickSigninHelper::LogConfirmHistogramValue(
332 clicked_learn_more_ ?
333 one_click_signin::HISTOGRAM_CONFIRM_LEARN_MORE_ESCAPE :
334 one_click_signin::HISTOGRAM_CONFIRM_ESCAPE);
336 base::ResetAndReturn(&start_sync_callback_).Run(
337 OneClickSigninSyncStarter::UNDO_SYNC);
341 return true;
344 return BubbleDelegateView::AcceleratorPressed(accelerator);
347 void OneClickSigninBubbleView::LinkClicked(views::Link* source,
348 int event_flags) {
349 if (source == learn_more_link_) {
350 if (is_sync_dialog_ && !clicked_learn_more_) {
351 OneClickSigninHelper::LogConfirmHistogramValue(
352 one_click_signin::HISTOGRAM_CONFIRM_LEARN_MORE);
353 clicked_learn_more_ = true;
355 delegate_->OnLearnMoreLinkClicked(is_sync_dialog_);
357 // don't hide the modal dialog, as this is an informational link
358 if (is_sync_dialog_)
359 return;
360 } else if (advanced_link_ && source == advanced_link_) {
361 if (is_sync_dialog_) {
362 OneClickSigninHelper::LogConfirmHistogramValue(
363 clicked_learn_more_ ?
364 one_click_signin::HISTOGRAM_CONFIRM_LEARN_MORE_ADVANCED :
365 one_click_signin::HISTOGRAM_CONFIRM_ADVANCED);
367 base::ResetAndReturn(&start_sync_callback_).Run(
368 OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST);
369 } else {
370 delegate_->OnAdvancedLinkClicked();
374 Hide();
377 void OneClickSigninBubbleView::ButtonPressed(views::Button* sender,
378 const ui::Event& event) {
379 Hide();
381 if (is_sync_dialog_) {
382 if (sender == ok_button_)
383 OneClickSigninHelper::LogConfirmHistogramValue(
384 clicked_learn_more_ ?
385 one_click_signin::HISTOGRAM_CONFIRM_LEARN_MORE_OK :
386 one_click_signin::HISTOGRAM_CONFIRM_OK);
388 if (sender == undo_button_)
389 OneClickSigninHelper::LogConfirmHistogramValue(
390 clicked_learn_more_ ?
391 one_click_signin::HISTOGRAM_CONFIRM_LEARN_MORE_UNDO :
392 one_click_signin::HISTOGRAM_CONFIRM_UNDO);
394 if (sender == close_button_)
395 OneClickSigninHelper::LogConfirmHistogramValue(
396 clicked_learn_more_ ?
397 one_click_signin::HISTOGRAM_CONFIRM_LEARN_MORE_CLOSE :
398 one_click_signin::HISTOGRAM_CONFIRM_CLOSE);
400 base::ResetAndReturn(&start_sync_callback_).Run((sender == ok_button_) ?
401 OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS :
402 OneClickSigninSyncStarter::UNDO_SYNC);
406 void OneClickSigninBubbleView::WindowClosing() {
407 // We have to reset |bubble_view_| here, not in our destructor, because
408 // we'll be destroyed asynchronously and the shown state will be checked
409 // before then.
410 DCHECK_EQ(bubble_view_, this);
411 bubble_view_ = NULL;
413 if (is_sync_dialog_ && !start_sync_callback_.is_null()) {
414 base::ResetAndReturn(&start_sync_callback_).Run(
415 OneClickSigninSyncStarter::UNDO_SYNC);