Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / views / passwords / manage_passwords_bubble_view.cc
blob0d4638ca9249ec7bca93f5f9963179a2ff896234
1 // Copyright 2013 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/passwords/manage_passwords_bubble_view.h"
7 #include "base/timer/timer.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_finder.h"
11 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
12 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
13 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
14 #include "chrome/browser/ui/passwords/save_account_more_combobox_model.h"
15 #include "chrome/browser/ui/passwords/save_password_refusal_combobox_model.h"
16 #include "chrome/browser/ui/views/frame/browser_view.h"
17 #include "chrome/browser/ui/views/passwords/credentials_item_view.h"
18 #include "chrome/browser/ui/views/passwords/manage_credential_item_view.h"
19 #include "chrome/browser/ui/views/passwords/manage_password_items_view.h"
20 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h"
21 #include "chrome/grit/generated_resources.h"
22 #include "content/public/browser/render_view_host.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/views/controls/button/blue_button.h"
26 #include "ui/views/controls/button/label_button.h"
27 #include "ui/views/controls/combobox/combobox.h"
28 #include "ui/views/controls/combobox/combobox_listener.h"
29 #include "ui/views/controls/link.h"
30 #include "ui/views/controls/link_listener.h"
31 #include "ui/views/controls/separator.h"
32 #include "ui/views/controls/styled_label.h"
33 #include "ui/views/controls/styled_label_listener.h"
34 #include "ui/views/event_monitor.h"
35 #include "ui/views/layout/fill_layout.h"
36 #include "ui/views/layout/grid_layout.h"
37 #include "ui/views/layout/layout_constants.h"
38 #include "ui/views/widget/widget.h"
40 int ManagePasswordsBubbleView::auto_signin_toast_timeout_ = 3;
42 // Helpers --------------------------------------------------------------------
44 namespace {
46 const int kDesiredBubbleWidth = 370;
48 enum ColumnSetType {
49 // | | (FILL, FILL) | |
50 // Used for the bubble's header, the credentials list, and for simple
51 // messages like "No passwords".
52 SINGLE_VIEW_COLUMN_SET,
54 // | | (TRAILING, CENTER) | | (TRAILING, CENTER) | |
55 // Used for buttons at the bottom of the bubble which should nest at the
56 // bottom-right corner.
57 DOUBLE_BUTTON_COLUMN_SET,
59 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | |
60 // Used for buttons at the bottom of the bubble which should occupy
61 // the corners.
62 LINK_BUTTON_COLUMN_SET,
64 // | | (TRAILING, CENTER) | |
65 // Used when there is only one button which should next at the bottom-right
66 // corner.
67 SINGLE_BUTTON_COLUMN_SET,
69 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | | (TRAILING, CENTER) | |
70 // Used when there are three buttons.
71 TRIPLE_BUTTON_COLUMN_SET,
74 enum TextRowType { ROW_SINGLE, ROW_MULTILINE };
76 // Construct an appropriate ColumnSet for the given |type|, and add it
77 // to |layout|.
78 void BuildColumnSet(views::GridLayout* layout, ColumnSetType type) {
79 views::ColumnSet* column_set = layout->AddColumnSet(type);
80 column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
81 int full_width = kDesiredBubbleWidth - (2 * views::kPanelHorizMargin);
82 switch (type) {
83 case SINGLE_VIEW_COLUMN_SET:
84 column_set->AddColumn(views::GridLayout::FILL,
85 views::GridLayout::FILL,
87 views::GridLayout::FIXED,
88 full_width,
89 0);
90 break;
91 case DOUBLE_BUTTON_COLUMN_SET:
92 column_set->AddColumn(views::GridLayout::TRAILING,
93 views::GridLayout::CENTER,
95 views::GridLayout::USE_PREF,
97 0);
98 column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
99 column_set->AddColumn(views::GridLayout::TRAILING,
100 views::GridLayout::CENTER,
102 views::GridLayout::USE_PREF,
105 break;
106 case LINK_BUTTON_COLUMN_SET:
107 column_set->AddColumn(views::GridLayout::LEADING,
108 views::GridLayout::CENTER,
110 views::GridLayout::USE_PREF,
113 column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
114 column_set->AddColumn(views::GridLayout::TRAILING,
115 views::GridLayout::CENTER,
117 views::GridLayout::USE_PREF,
120 break;
121 case SINGLE_BUTTON_COLUMN_SET:
122 column_set->AddColumn(views::GridLayout::TRAILING,
123 views::GridLayout::CENTER,
125 views::GridLayout::USE_PREF,
128 break;
129 case TRIPLE_BUTTON_COLUMN_SET:
130 column_set->AddColumn(views::GridLayout::LEADING,
131 views::GridLayout::CENTER,
133 views::GridLayout::USE_PREF,
136 column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
137 column_set->AddColumn(views::GridLayout::TRAILING,
138 views::GridLayout::CENTER,
140 views::GridLayout::USE_PREF,
143 column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
144 column_set->AddColumn(views::GridLayout::TRAILING,
145 views::GridLayout::CENTER,
147 views::GridLayout::USE_PREF,
150 break;
152 column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
155 // Given a layout and a model, add an appropriate title using a
156 // SINGLE_VIEW_COLUMN_SET, followed by a spacer row.
157 void AddTitleRow(views::GridLayout* layout, ManagePasswordsBubbleModel* model) {
158 views::Label* title_label = new views::Label(model->title());
159 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
160 title_label->SetMultiLine(true);
161 title_label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
162 ui::ResourceBundle::MediumFont));
164 // Add the title to the layout with appropriate padding.
165 layout->StartRowWithPadding(
166 0, SINGLE_VIEW_COLUMN_SET, 0, views::kRelatedControlSmallVerticalSpacing);
167 layout->AddView(title_label);
168 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
171 } // namespace
174 // ManagePasswordsBubbleView::AccountChooserView ------------------------------
176 // A view offering the user the ability to choose credentials for
177 // authentication. Contains a list of CredentialsItemView, along with a
178 // "Cancel" button.
179 class ManagePasswordsBubbleView::AccountChooserView
180 : public views::View,
181 public views::ButtonListener {
182 public:
183 explicit AccountChooserView(ManagePasswordsBubbleView* parent);
184 ~AccountChooserView() override;
186 private:
187 // views::ButtonListener:
188 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
190 // Adds |password_forms| to the layout remembering their |type|.
191 void AddCredentialItemsWithType(
192 views::GridLayout* layout,
193 const ScopedVector<const autofill::PasswordForm>& password_forms,
194 password_manager::CredentialType type);
196 ManagePasswordsBubbleView* parent_;
197 views::LabelButton* cancel_button_;
199 DISALLOW_COPY_AND_ASSIGN(AccountChooserView);
202 ManagePasswordsBubbleView::AccountChooserView::AccountChooserView(
203 ManagePasswordsBubbleView* parent)
204 : parent_(parent) {
205 views::GridLayout* layout = new views::GridLayout(this);
206 SetLayoutManager(layout);
208 cancel_button_ =
209 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_CANCEL));
210 cancel_button_->SetStyle(views::Button::STYLE_BUTTON);
211 cancel_button_->SetFontList(
212 ui::ResourceBundle::GetSharedInstance().GetFontList(
213 ui::ResourceBundle::SmallFont));
215 // Title row.
216 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
217 AddTitleRow(layout, parent_->model());
219 AddCredentialItemsWithType(
220 layout, parent_->model()->local_credentials(),
221 password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL);
223 AddCredentialItemsWithType(
224 layout, parent_->model()->federated_credentials(),
225 password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED);
227 // Button row.
228 BuildColumnSet(layout, SINGLE_BUTTON_COLUMN_SET);
229 layout->StartRowWithPadding(
230 0, SINGLE_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
231 layout->AddView(cancel_button_);
233 // Extra padding for visual awesomeness.
234 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
236 parent_->set_initially_focused_view(cancel_button_);
239 ManagePasswordsBubbleView::AccountChooserView::~AccountChooserView() {
242 void ManagePasswordsBubbleView::AccountChooserView::AddCredentialItemsWithType(
243 views::GridLayout* layout,
244 const ScopedVector<const autofill::PasswordForm>& password_forms,
245 password_manager::CredentialType type) {
246 net::URLRequestContextGetter* request_context =
247 parent_->model()->GetProfile()->GetRequestContext();
248 for (const autofill::PasswordForm* form : password_forms) {
249 // Add the title to the layout with appropriate padding.
250 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
251 layout->AddView(new CredentialsItemView(
252 this, form, type, CredentialsItemView::ACCOUNT_CHOOSER,
253 request_context));
257 void ManagePasswordsBubbleView::AccountChooserView::ButtonPressed(
258 views::Button* sender, const ui::Event& event) {
259 if (sender != cancel_button_) {
260 // ManagePasswordsBubbleModel should care about calling a callback in case
261 // the bubble is dismissed by any other means.
262 CredentialsItemView* view = static_cast<CredentialsItemView*>(sender);
263 parent_->model()->OnChooseCredentials(*view->form(),
264 view->credential_type());
265 } else {
266 parent_->model()->OnNopeClicked();
268 parent_->Close();
271 // ManagePasswordsBubbleView::AutoSigninView ----------------------------------
273 // A view containing just one credential that was used for for automatic signing
274 // in.
275 class ManagePasswordsBubbleView::AutoSigninView
276 : public views::View,
277 public views::ButtonListener,
278 public views::WidgetObserver {
279 public:
280 explicit AutoSigninView(ManagePasswordsBubbleView* parent);
282 private:
283 // views::ButtonListener:
284 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
286 // views::WidgetObserver:
287 // Tracks the state of the browser window.
288 void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
289 void OnWidgetClosing(views::Widget* widget) override;
291 void OnTimer();
292 static base::TimeDelta GetTimeout() {
293 return base::TimeDelta::FromSeconds(
294 ManagePasswordsBubbleView::auto_signin_toast_timeout_);
297 base::OneShotTimer<AutoSigninView> timer_;
298 ManagePasswordsBubbleView* parent_;
299 ScopedObserver<views::Widget, views::WidgetObserver> observed_browser_;
301 DISALLOW_COPY_AND_ASSIGN(AutoSigninView);
304 ManagePasswordsBubbleView::AutoSigninView::AutoSigninView(
305 ManagePasswordsBubbleView* parent)
306 : parent_(parent),
307 observed_browser_(this) {
308 SetLayoutManager(new views::FillLayout);
309 CredentialsItemView* credential = new CredentialsItemView(
310 this,
311 &parent_->model()->pending_password(),
312 password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL,
313 CredentialsItemView::AUTO_SIGNIN,
314 parent_->model()->GetProfile()->GetRequestContext());
315 AddChildView(credential);
316 parent_->set_initially_focused_view(credential);
318 Browser* browser =
319 chrome::FindBrowserWithWebContents(parent_->web_contents());
320 DCHECK(browser);
321 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
322 observed_browser_.Add(browser_view->GetWidget());
324 if (browser_view->IsActive())
325 timer_.Start(FROM_HERE, GetTimeout(), this, &AutoSigninView::OnTimer);
328 void ManagePasswordsBubbleView::AutoSigninView::ButtonPressed(
329 views::Button* sender, const ui::Event& event) {
330 parent_->model()->OnAutoSignInClicked();
331 parent_->Close();
334 void ManagePasswordsBubbleView::AutoSigninView::OnWidgetActivationChanged(
335 views::Widget* widget, bool active) {
336 if (active && !timer_.IsRunning())
337 timer_.Start(FROM_HERE, GetTimeout(), this, &AutoSigninView::OnTimer);
340 void ManagePasswordsBubbleView::AutoSigninView::OnWidgetClosing(
341 views::Widget* widget) {
342 observed_browser_.RemoveAll();
345 void ManagePasswordsBubbleView::AutoSigninView::OnTimer() {
346 parent_->model()->OnAutoSignInToastTimeout();
347 parent_->Close();
350 // ManagePasswordsBubbleView::PendingView -------------------------------------
352 // A view offering the user the ability to save credentials. Contains a
353 // single ManagePasswordItemsView, along with a "Save Passwords" button
354 // and a rejection combobox.
355 class ManagePasswordsBubbleView::PendingView
356 : public views::View,
357 public views::ButtonListener,
358 public views::ComboboxListener,
359 public views::StyledLabelListener {
360 public:
361 explicit PendingView(ManagePasswordsBubbleView* parent);
362 ~PendingView() override;
364 private:
365 // views::ButtonListener:
366 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
368 // views::StyledLabelListener:
369 void StyledLabelLinkClicked(const gfx::Range& range,
370 int event_flags) override;
372 // Handles the event when the user changes an index of a combobox.
373 void OnPerformAction(views::Combobox* source) override;
375 ManagePasswordsBubbleView* parent_;
377 views::BlueButton* save_button_;
379 // The combobox doesn't take ownership of its model. If we created a
380 // combobox we need to ensure that we delete the model here, and because the
381 // combobox uses the model in it's destructor, we need to make sure we
382 // delete the model _after_ the combobox itself is deleted.
383 scoped_ptr<SavePasswordRefusalComboboxModel> combobox_model_;
384 scoped_ptr<views::Combobox> refuse_combobox_;
386 DISALLOW_COPY_AND_ASSIGN(PendingView);
389 ManagePasswordsBubbleView::PendingView::PendingView(
390 ManagePasswordsBubbleView* parent)
391 : parent_(parent) {
392 views::GridLayout* layout = new views::GridLayout(this);
393 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
394 SetLayoutManager(layout);
396 std::vector<const autofill::PasswordForm*> credentials(
397 1, &parent->model()->pending_password());
398 // Create the pending credential item, save button and refusal combobox.
399 ManagePasswordItemsView* item =
400 new ManagePasswordItemsView(parent_->model(), credentials);
401 save_button_ = new views::BlueButton(
402 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON));
403 save_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
404 ui::ResourceBundle::SmallFont));
406 combobox_model_.reset(new SavePasswordRefusalComboboxModel);
407 refuse_combobox_.reset(new views::Combobox(combobox_model_.get()));
408 refuse_combobox_->set_listener(this);
409 refuse_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
410 // TODO(mkwst): Need a mechanism to pipe a font list down into a combobox.
412 // Title row.
413 views::StyledLabel* title_label =
414 new views::StyledLabel(parent_->model()->title(), this);
415 title_label->SetBaseFontList(
416 ui::ResourceBundle::GetSharedInstance().GetFontList(
417 ui::ResourceBundle::MediumFont));
418 if (!parent_->model()->title_brand_link_range().is_empty()) {
419 title_label->AddStyleRange(
420 parent_->model()->title_brand_link_range(),
421 views::StyledLabel::RangeStyleInfo::CreateForLink());
423 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
424 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
425 layout->AddView(title_label);
426 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
428 // Credential row.
429 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
430 layout->AddView(item);
432 // Button row.
433 BuildColumnSet(layout, DOUBLE_BUTTON_COLUMN_SET);
434 layout->StartRowWithPadding(
435 0, DOUBLE_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
436 layout->AddView(save_button_);
437 layout->AddView(refuse_combobox_.get());
439 // Extra padding for visual awesomeness.
440 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
442 parent_->set_initially_focused_view(save_button_);
445 ManagePasswordsBubbleView::PendingView::~PendingView() {
448 void ManagePasswordsBubbleView::PendingView::ButtonPressed(
449 views::Button* sender,
450 const ui::Event& event) {
451 DCHECK(sender == save_button_);
452 parent_->model()->OnSaveClicked();
453 parent_->Close();
456 void ManagePasswordsBubbleView::PendingView::StyledLabelLinkClicked(
457 const gfx::Range& range,
458 int event_flags) {
459 DCHECK_EQ(range, parent_->model()->title_brand_link_range());
460 parent_->model()->OnBrandLinkClicked();
463 void ManagePasswordsBubbleView::PendingView::OnPerformAction(
464 views::Combobox* source) {
465 DCHECK_EQ(source, refuse_combobox_);
466 switch (refuse_combobox_->selected_index()) {
467 case SavePasswordRefusalComboboxModel::INDEX_NOPE:
468 parent_->model()->OnNopeClicked();
469 parent_->Close();
470 break;
471 case SavePasswordRefusalComboboxModel::INDEX_NEVER_FOR_THIS_SITE:
472 parent_->NotifyNeverForThisSiteClicked();
473 break;
477 // ManagePasswordsBubbleView::SaveAccountView ---------------------------------
479 // A view offering the user the ability to save credentials. Contains 2 buttons
480 // and a "More" combobox.
481 class ManagePasswordsBubbleView::SaveAccountView
482 : public views::View,
483 public views::ButtonListener,
484 public views::ComboboxListener {
485 public:
486 explicit SaveAccountView(ManagePasswordsBubbleView* parent);
488 private:
489 // views::ButtonListener:
490 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
492 // Handles the event when the user changes an index of a combobox.
493 void OnPerformAction(views::Combobox* source) override;
495 ManagePasswordsBubbleView* parent_;
497 views::BlueButton* save_button_;
498 views::LabelButton* no_button_;
500 // The combobox doesn't take ownership of its model. If we created a
501 // combobox we need to ensure that we delete the model here, and because the
502 // combobox uses the model in it's destructor, we need to make sure we
503 // delete the model _after_ the combobox itself is deleted.
504 SaveAccountMoreComboboxModel combobox_model_;
505 scoped_ptr<views::Combobox> more_combobox_;
508 ManagePasswordsBubbleView::SaveAccountView::SaveAccountView(
509 ManagePasswordsBubbleView* parent)
510 : parent_(parent) {
511 DCHECK(parent_->model()->IsNewUIActive());
512 views::GridLayout* layout = new views::GridLayout(this);
513 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
514 SetLayoutManager(layout);
516 save_button_ = new views::BlueButton(
517 this,
518 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_ACCOUNT_BUTTON));
519 save_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
520 ui::ResourceBundle::SmallFont));
522 no_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
523 IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SMART_LOCK_NO_THANKS_BUTTON));
524 no_button_->SetStyle(views::Button::STYLE_BUTTON);
525 no_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
526 ui::ResourceBundle::SmallFont));
528 more_combobox_.reset(new views::Combobox(&combobox_model_));
529 more_combobox_->set_owned_by_client();
530 more_combobox_->set_listener(this);
531 more_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
533 // Title row.
534 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
535 AddTitleRow(layout, parent_->model());
537 // Button row.
538 BuildColumnSet(layout, TRIPLE_BUTTON_COLUMN_SET);
539 layout->StartRow(0, TRIPLE_BUTTON_COLUMN_SET);
540 layout->AddView(more_combobox_.get());
541 layout->AddView(save_button_);
542 layout->AddView(no_button_);
543 // Extra padding for visual awesomeness.
544 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
546 parent_->set_initially_focused_view(save_button_);
549 void ManagePasswordsBubbleView::SaveAccountView::ButtonPressed(
550 views::Button* sender,
551 const ui::Event& event) {
552 if (sender == save_button_)
553 parent_->model()->OnSaveClicked();
554 else if (sender == no_button_)
555 parent_->model()->OnNopeClicked();
556 else
557 NOTREACHED();
559 parent_->Close();
562 void ManagePasswordsBubbleView::SaveAccountView::OnPerformAction(
563 views::Combobox* source) {
564 DCHECK_EQ(source, more_combobox_);
565 switch (more_combobox_->selected_index()) {
566 case SaveAccountMoreComboboxModel::INDEX_MORE:
567 break;
568 case SaveAccountMoreComboboxModel::INDEX_NEVER_FOR_THIS_SITE:
569 parent_->NotifyNeverForThisSiteClicked();
570 break;
571 case SaveAccountMoreComboboxModel::INDEX_SETTINGS:
572 parent_->model()->OnManageLinkClicked();
573 parent_->Close();
574 break;
578 // ManagePasswordsBubbleView::ConfirmNeverView --------------------------------
580 // A view offering the user the ability to undo her decision to never save
581 // passwords for a particular site.
582 class ManagePasswordsBubbleView::ConfirmNeverView
583 : public views::View,
584 public views::ButtonListener {
585 public:
586 explicit ConfirmNeverView(ManagePasswordsBubbleView* parent);
587 ~ConfirmNeverView() override;
589 private:
590 // views::ButtonListener:
591 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
593 ManagePasswordsBubbleView* parent_;
595 views::LabelButton* confirm_button_;
596 views::LabelButton* undo_button_;
598 DISALLOW_COPY_AND_ASSIGN(ConfirmNeverView);
601 ManagePasswordsBubbleView::ConfirmNeverView::ConfirmNeverView(
602 ManagePasswordsBubbleView* parent)
603 : parent_(parent) {
604 views::GridLayout* layout = new views::GridLayout(this);
605 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
606 SetLayoutManager(layout);
608 // Title row.
609 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
610 AddTitleRow(layout, parent_->model());
612 // Confirmation text.
613 views::Label* confirmation = new views::Label(l10n_util::GetStringUTF16(
614 IDS_MANAGE_PASSWORDS_BLACKLIST_CONFIRMATION_TEXT));
615 confirmation->SetHorizontalAlignment(gfx::ALIGN_LEFT);
616 confirmation->SetMultiLine(true);
617 confirmation->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
618 ui::ResourceBundle::SmallFont));
619 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
620 layout->AddView(confirmation);
621 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
623 // Confirm and undo buttons.
624 BuildColumnSet(layout, DOUBLE_BUTTON_COLUMN_SET);
625 layout->StartRowWithPadding(
626 0, DOUBLE_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
628 confirm_button_ = new views::LabelButton(
629 this,
630 l10n_util::GetStringUTF16(
631 IDS_MANAGE_PASSWORDS_BLACKLIST_CONFIRMATION_BUTTON));
632 confirm_button_->SetStyle(views::Button::STYLE_BUTTON);
633 confirm_button_->SetFontList(
634 ui::ResourceBundle::GetSharedInstance().GetFontList(
635 ui::ResourceBundle::SmallFont));
636 layout->AddView(confirm_button_);
638 undo_button_ =
639 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_CANCEL));
640 undo_button_->SetStyle(views::Button::STYLE_BUTTON);
641 undo_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
642 ui::ResourceBundle::SmallFont));
643 layout->AddView(undo_button_);
645 // Extra padding for visual awesomeness.
646 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
648 parent_->set_initially_focused_view(confirm_button_);
651 ManagePasswordsBubbleView::ConfirmNeverView::~ConfirmNeverView() {
654 void ManagePasswordsBubbleView::ConfirmNeverView::ButtonPressed(
655 views::Button* sender,
656 const ui::Event& event) {
657 DCHECK(sender == confirm_button_ || sender == undo_button_);
658 if (sender == confirm_button_)
659 parent_->NotifyConfirmedNeverForThisSite();
660 else
661 parent_->NotifyUndoNeverForThisSite();
664 // ManagePasswordsBubbleView::ManageView --------------------------------------
666 // A view offering the user a list of her currently saved credentials
667 // for the current page, along with a "Manage passwords" link and a
668 // "Done" button.
669 class ManagePasswordsBubbleView::ManageView : public views::View,
670 public views::ButtonListener,
671 public views::LinkListener {
672 public:
673 explicit ManageView(ManagePasswordsBubbleView* parent);
674 ~ManageView() override;
676 private:
677 // views::ButtonListener:
678 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
680 // views::LinkListener:
681 void LinkClicked(views::Link* source, int event_flags) override;
683 ManagePasswordsBubbleView* parent_;
685 views::Link* manage_link_;
686 views::LabelButton* done_button_;
688 DISALLOW_COPY_AND_ASSIGN(ManageView);
691 ManagePasswordsBubbleView::ManageView::ManageView(
692 ManagePasswordsBubbleView* parent)
693 : parent_(parent) {
694 views::GridLayout* layout = new views::GridLayout(this);
695 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
696 SetLayoutManager(layout);
698 // Add the title.
699 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
700 AddTitleRow(layout, parent_->model());
702 // If we have a list of passwords to store for the current site, display
703 // them to the user for management. Otherwise, render a "No passwords for
704 // this site" message.
705 if (!parent_->model()->local_credentials().empty()) {
706 ManagePasswordItemsView* item = new ManagePasswordItemsView(
707 parent_->model(), parent_->model()->local_credentials().get());
708 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
709 layout->AddView(item);
710 } else {
711 views::Label* empty_label = new views::Label(
712 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_NO_PASSWORDS));
713 empty_label->SetMultiLine(true);
714 empty_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
715 empty_label->SetFontList(
716 ui::ResourceBundle::GetSharedInstance().GetFontList(
717 ui::ResourceBundle::SmallFont));
719 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
720 layout->AddView(empty_label);
721 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
724 // Then add the "manage passwords" link and "Done" button.
725 manage_link_ = new views::Link(parent_->model()->manage_link());
726 manage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
727 manage_link_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
728 ui::ResourceBundle::SmallFont));
729 manage_link_->SetUnderline(false);
730 manage_link_->set_listener(this);
732 done_button_ =
733 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_DONE));
734 done_button_->SetStyle(views::Button::STYLE_BUTTON);
735 done_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
736 ui::ResourceBundle::SmallFont));
738 BuildColumnSet(layout, LINK_BUTTON_COLUMN_SET);
739 layout->StartRowWithPadding(
740 0, LINK_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
741 layout->AddView(manage_link_);
742 layout->AddView(done_button_);
744 // Extra padding for visual awesomeness.
745 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
747 parent_->set_initially_focused_view(done_button_);
750 ManagePasswordsBubbleView::ManageView::~ManageView() {
753 void ManagePasswordsBubbleView::ManageView::ButtonPressed(
754 views::Button* sender,
755 const ui::Event& event) {
756 DCHECK(sender == done_button_);
757 parent_->model()->OnDoneClicked();
758 parent_->Close();
761 void ManagePasswordsBubbleView::ManageView::LinkClicked(views::Link* source,
762 int event_flags) {
763 DCHECK_EQ(source, manage_link_);
764 parent_->model()->OnManageLinkClicked();
765 parent_->Close();
768 // ManagePasswordsBubbleView::ManageAccountsView ------------------------------
770 // A view offering the user a list of his currently saved through the Credential
771 // Manager API accounts for the current page.
772 class ManagePasswordsBubbleView::ManageAccountsView
773 : public views::View,
774 public views::ButtonListener,
775 public views::LinkListener {
776 public:
777 explicit ManageAccountsView(ManagePasswordsBubbleView* parent);
779 private:
780 // views::ButtonListener:
781 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
783 // views::LinkListener:
784 void LinkClicked(views::Link* source, int event_flags) override;
786 ManagePasswordsBubbleView* parent_;
788 views::Link* manage_link_;
789 views::LabelButton* done_button_;
791 DISALLOW_COPY_AND_ASSIGN(ManageAccountsView);
794 ManagePasswordsBubbleView::ManageAccountsView::ManageAccountsView(
795 ManagePasswordsBubbleView* parent)
796 : parent_(parent) {
797 views::GridLayout* layout = new views::GridLayout(this);
798 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
799 SetLayoutManager(layout);
801 // Add the title.
802 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
803 AddTitleRow(layout, parent_->model());
805 if (!parent_->model()->local_credentials().empty()) {
806 for (const autofill::PasswordForm* form :
807 parent_->model()->local_credentials()) {
808 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
809 layout->AddView(new ManageCredentialItemView(parent_->model(), form));
811 } else {
812 views::Label* empty_label = new views::Label(
813 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_NO_PASSWORDS),
814 ui::ResourceBundle::GetSharedInstance().GetFontList(
815 ui::ResourceBundle::SmallFont));
816 empty_label->SetMultiLine(true);
817 empty_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
819 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
820 layout->AddView(empty_label);
821 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
824 // Then add the "manage passwords" link and "Done" button.
825 manage_link_ = new views::Link(parent_->model()->manage_link());
826 manage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
827 manage_link_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
828 ui::ResourceBundle::SmallFont));
829 manage_link_->SetUnderline(false);
830 manage_link_->set_listener(this);
832 done_button_ =
833 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_DONE));
834 done_button_->SetStyle(views::Button::STYLE_BUTTON);
835 done_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
836 ui::ResourceBundle::SmallFont));
838 BuildColumnSet(layout, LINK_BUTTON_COLUMN_SET);
839 layout->StartRowWithPadding(
840 0, LINK_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
841 layout->AddView(manage_link_);
842 layout->AddView(done_button_);
844 // Extra padding for visual awesomeness.
845 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
847 parent_->set_initially_focused_view(done_button_);
850 void ManagePasswordsBubbleView::ManageAccountsView::ButtonPressed(
851 views::Button* sender, const ui::Event& event) {
852 DCHECK(sender == done_button_);
853 parent_->model()->OnDoneClicked();
854 parent_->Close();
857 void ManagePasswordsBubbleView::ManageAccountsView::LinkClicked(
858 views::Link* source, int event_flags) {
859 DCHECK_EQ(source, manage_link_);
860 parent_->model()->OnManageLinkClicked();
861 parent_->Close();
864 // ManagePasswordsBubbleView::BlacklistedView ---------------------------------
866 // A view offering the user the ability to re-enable the password manager for
867 // a specific site after she's decided to "never save passwords".
868 class ManagePasswordsBubbleView::BlacklistedView
869 : public views::View,
870 public views::ButtonListener {
871 public:
872 explicit BlacklistedView(ManagePasswordsBubbleView* parent);
873 ~BlacklistedView() override;
875 private:
876 // views::ButtonListener:
877 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
879 ManagePasswordsBubbleView* parent_;
881 views::BlueButton* unblacklist_button_;
882 views::LabelButton* done_button_;
884 DISALLOW_COPY_AND_ASSIGN(BlacklistedView);
887 ManagePasswordsBubbleView::BlacklistedView::BlacklistedView(
888 ManagePasswordsBubbleView* parent)
889 : parent_(parent) {
890 views::GridLayout* layout = new views::GridLayout(this);
891 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
892 SetLayoutManager(layout);
894 // Add the title.
895 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
896 AddTitleRow(layout, parent_->model());
898 // Add the "Hey! You blacklisted this site!" text.
899 views::Label* blacklisted = new views::Label(
900 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_BLACKLISTED));
901 blacklisted->SetMultiLine(true);
902 blacklisted->SetHorizontalAlignment(gfx::ALIGN_LEFT);
903 blacklisted->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
904 ui::ResourceBundle::SmallFont));
905 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
906 layout->AddView(blacklisted);
907 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
909 // Then add the "enable password manager" and "Done" buttons.
910 unblacklist_button_ = new views::BlueButton(
911 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UNBLACKLIST_BUTTON));
912 unblacklist_button_->SetFontList(
913 ui::ResourceBundle::GetSharedInstance().GetFontList(
914 ui::ResourceBundle::SmallFont));
915 done_button_ =
916 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_DONE));
917 done_button_->SetStyle(views::Button::STYLE_BUTTON);
918 done_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
919 ui::ResourceBundle::SmallFont));
921 BuildColumnSet(layout, DOUBLE_BUTTON_COLUMN_SET);
922 layout->StartRowWithPadding(
923 0, DOUBLE_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
924 layout->AddView(unblacklist_button_);
925 layout->AddView(done_button_);
927 // Extra padding for visual awesomeness.
928 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
930 parent_->set_initially_focused_view(unblacklist_button_);
933 ManagePasswordsBubbleView::BlacklistedView::~BlacklistedView() {
936 void ManagePasswordsBubbleView::BlacklistedView::ButtonPressed(
937 views::Button* sender,
938 const ui::Event& event) {
939 if (sender == done_button_)
940 parent_->model()->OnDoneClicked();
941 else if (sender == unblacklist_button_)
942 parent_->model()->OnUnblacklistClicked();
943 else
944 NOTREACHED();
945 parent_->Close();
948 // ManagePasswordsBubbleView::SaveConfirmationView ----------------------------
950 // A view confirming to the user that a password was saved and offering a link
951 // to the Google account manager.
952 class ManagePasswordsBubbleView::SaveConfirmationView
953 : public views::View,
954 public views::ButtonListener,
955 public views::StyledLabelListener {
956 public:
957 explicit SaveConfirmationView(ManagePasswordsBubbleView* parent);
958 ~SaveConfirmationView() override;
960 private:
961 // views::ButtonListener:
962 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
964 // views::StyledLabelListener implementation
965 void StyledLabelLinkClicked(const gfx::Range& range,
966 int event_flags) override;
968 ManagePasswordsBubbleView* parent_;
969 views::LabelButton* ok_button_;
971 DISALLOW_COPY_AND_ASSIGN(SaveConfirmationView);
974 ManagePasswordsBubbleView::SaveConfirmationView::SaveConfirmationView(
975 ManagePasswordsBubbleView* parent)
976 : parent_(parent) {
977 views::GridLayout* layout = new views::GridLayout(this);
978 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
979 SetLayoutManager(layout);
981 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
982 AddTitleRow(layout, parent_->model());
984 views::StyledLabel* confirmation =
985 new views::StyledLabel(parent_->model()->save_confirmation_text(), this);
986 confirmation->SetBaseFontList(
987 ui::ResourceBundle::GetSharedInstance().GetFontList(
988 ui::ResourceBundle::SmallFont));
989 confirmation->AddStyleRange(
990 parent_->model()->save_confirmation_link_range(),
991 views::StyledLabel::RangeStyleInfo::CreateForLink());
993 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
994 layout->AddView(confirmation);
996 ok_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_OK));
997 ok_button_->SetStyle(views::Button::STYLE_BUTTON);
998 ok_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
999 ui::ResourceBundle::SmallFont));
1001 BuildColumnSet(layout, SINGLE_BUTTON_COLUMN_SET);
1002 layout->StartRowWithPadding(
1003 0, SINGLE_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
1004 layout->AddView(ok_button_);
1006 // Extra padding for visual awesomeness.
1007 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1009 parent_->set_initially_focused_view(ok_button_);
1012 ManagePasswordsBubbleView::SaveConfirmationView::~SaveConfirmationView() {
1015 void ManagePasswordsBubbleView::SaveConfirmationView::StyledLabelLinkClicked(
1016 const gfx::Range& range, int event_flags) {
1017 DCHECK_EQ(range, parent_->model()->save_confirmation_link_range());
1018 parent_->model()->OnManageLinkClicked();
1019 parent_->Close();
1022 void ManagePasswordsBubbleView::SaveConfirmationView::ButtonPressed(
1023 views::Button* sender, const ui::Event& event) {
1024 DCHECK_EQ(sender, ok_button_);
1025 parent_->model()->OnOKClicked();
1026 parent_->Close();
1029 // ManagePasswordsBubbleView::WebContentMouseHandler --------------------------
1031 // The class listens for WebContentsView events and notifies the bubble if the
1032 // view was clicked on or received keystrokes.
1033 class ManagePasswordsBubbleView::WebContentMouseHandler
1034 : public ui::EventHandler {
1035 public:
1036 explicit WebContentMouseHandler(ManagePasswordsBubbleView* bubble);
1038 void OnKeyEvent(ui::KeyEvent* event) override;
1039 void OnMouseEvent(ui::MouseEvent* event) override;
1040 void OnTouchEvent(ui::TouchEvent* event) override;
1042 private:
1043 ManagePasswordsBubbleView* bubble_;
1044 scoped_ptr<views::EventMonitor> event_monitor_;
1046 DISALLOW_COPY_AND_ASSIGN(WebContentMouseHandler);
1049 ManagePasswordsBubbleView::WebContentMouseHandler::WebContentMouseHandler(
1050 ManagePasswordsBubbleView* bubble)
1051 : bubble_(bubble) {
1052 content::WebContents* web_contents = bubble_->web_contents();
1053 DCHECK(web_contents);
1054 event_monitor_ = views::EventMonitor::CreateWindowMonitor(
1055 this, web_contents->GetTopLevelNativeWindow());
1058 void ManagePasswordsBubbleView::WebContentMouseHandler::OnKeyEvent(
1059 ui::KeyEvent* event) {
1060 content::WebContents* web_contents = bubble_->web_contents();
1061 content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
1062 if (rvh->IsFocusedElementEditable() &&
1063 event->type() == ui::ET_KEY_PRESSED)
1064 bubble_->Close();
1067 void ManagePasswordsBubbleView::WebContentMouseHandler::OnMouseEvent(
1068 ui::MouseEvent* event) {
1069 if (event->type() == ui::ET_MOUSE_PRESSED)
1070 bubble_->Close();
1073 void ManagePasswordsBubbleView::WebContentMouseHandler::OnTouchEvent(
1074 ui::TouchEvent* event) {
1075 if (event->type() == ui::ET_TOUCH_PRESSED)
1076 bubble_->Close();
1079 // ManagePasswordsBubbleView --------------------------------------------------
1081 // static
1082 ManagePasswordsBubbleView* ManagePasswordsBubbleView::manage_passwords_bubble_ =
1083 NULL;
1085 // static
1086 void ManagePasswordsBubbleView::ShowBubble(content::WebContents* web_contents,
1087 DisplayReason reason) {
1088 Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
1089 DCHECK(browser);
1090 DCHECK(browser->window());
1091 DCHECK(!manage_passwords_bubble_ ||
1092 !manage_passwords_bubble_->GetWidget()->IsVisible());
1094 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
1095 bool is_fullscreen = browser_view->IsFullscreen();
1096 ManagePasswordsIconView* anchor_view =
1097 is_fullscreen
1098 ? NULL
1099 : browser_view->GetLocationBarView()->manage_passwords_icon_view();
1100 manage_passwords_bubble_ = new ManagePasswordsBubbleView(
1101 web_contents, anchor_view, reason);
1103 if (is_fullscreen)
1104 manage_passwords_bubble_->set_parent_window(web_contents->GetNativeView());
1106 views::BubbleDelegateView::CreateBubble(manage_passwords_bubble_);
1108 // Adjust for fullscreen after creation as it relies on the content size.
1109 if (is_fullscreen) {
1110 manage_passwords_bubble_->AdjustForFullscreen(
1111 browser_view->GetBoundsInScreen());
1113 if (reason == AUTOMATIC)
1114 manage_passwords_bubble_->GetWidget()->ShowInactive();
1115 else
1116 manage_passwords_bubble_->GetWidget()->Show();
1119 // static
1120 void ManagePasswordsBubbleView::CloseBubble() {
1121 if (manage_passwords_bubble_)
1122 manage_passwords_bubble_->Close();
1125 // static
1126 void ManagePasswordsBubbleView::ActivateBubble() {
1127 DCHECK(manage_passwords_bubble_);
1128 DCHECK(manage_passwords_bubble_->GetWidget()->IsVisible());
1129 manage_passwords_bubble_->GetWidget()->Activate();
1132 content::WebContents* ManagePasswordsBubbleView::web_contents() const {
1133 return model()->web_contents();
1136 ManagePasswordsBubbleView::ManagePasswordsBubbleView(
1137 content::WebContents* web_contents,
1138 ManagePasswordsIconView* anchor_view,
1139 DisplayReason reason)
1140 : ManagePasswordsBubble(web_contents, reason),
1141 ManagedFullScreenBubbleDelegateView(anchor_view, web_contents),
1142 anchor_view_(anchor_view),
1143 initially_focused_view_(NULL) {
1144 // Compensate for built-in vertical padding in the anchor view's image.
1145 set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));
1146 if (anchor_view)
1147 anchor_view->SetActive(true);
1148 mouse_handler_.reset(new WebContentMouseHandler(this));
1151 ManagePasswordsBubbleView::~ManagePasswordsBubbleView() {
1152 if (manage_passwords_bubble_ == this)
1153 manage_passwords_bubble_ = NULL;
1156 views::View* ManagePasswordsBubbleView::GetInitiallyFocusedView() {
1157 return initially_focused_view_;
1160 void ManagePasswordsBubbleView::Init() {
1161 views::FillLayout* layout = new views::FillLayout();
1162 SetLayoutManager(layout);
1164 Refresh();
1167 void ManagePasswordsBubbleView::Close() {
1168 mouse_handler_.reset();
1169 ManagedFullScreenBubbleDelegateView::Close();
1172 void ManagePasswordsBubbleView::OnWidgetClosing(views::Widget* /*widget*/) {
1173 if (anchor_view_)
1174 anchor_view_->SetActive(false);
1177 void ManagePasswordsBubbleView::Refresh() {
1178 RemoveAllChildViews(true);
1179 initially_focused_view_ = NULL;
1180 if (model()->state() == password_manager::ui::PENDING_PASSWORD_STATE) {
1181 if (model()->never_save_passwords()) {
1182 AddChildView(new ConfirmNeverView(this));
1183 } else {
1184 if (model()->IsNewUIActive())
1185 AddChildView(new SaveAccountView(this));
1186 else
1187 AddChildView(new PendingView(this));
1189 } else if (model()->state() == password_manager::ui::BLACKLIST_STATE) {
1190 AddChildView(new BlacklistedView(this));
1191 } else if (model()->state() == password_manager::ui::CONFIRMATION_STATE) {
1192 AddChildView(new SaveConfirmationView(this));
1193 } else if (model()->state() ==
1194 password_manager::ui::CREDENTIAL_REQUEST_STATE) {
1195 AddChildView(new AccountChooserView(this));
1196 } else if (model()->state() == password_manager::ui::AUTO_SIGNIN_STATE) {
1197 AddChildView(new AutoSigninView(this));
1198 } else {
1199 if (model()->IsNewUIActive())
1200 AddChildView(new ManageAccountsView(this));
1201 else
1202 AddChildView(new ManageView(this));
1204 GetLayoutManager()->Layout(this);
1207 void ManagePasswordsBubbleView::NotifyConfirmedNeverForThisSite() {
1208 model()->OnNeverForThisSiteClicked();
1209 Close();
1212 void ManagePasswordsBubbleView::NotifyUndoNeverForThisSite() {
1213 model()->OnUndoNeverForThisSite();
1214 Refresh();
1215 SizeToContents();
1218 void ManagePasswordsBubbleView::NotifyNeverForThisSiteClicked() {
1219 if (model()->local_credentials().empty()) {
1220 // Skip confirmation if there are no existing passwords for this site.
1221 NotifyConfirmedNeverForThisSite();
1222 } else {
1223 model()->OnConfirmationForNeverForThisSite();
1224 Refresh();
1225 SizeToContents();