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

Side by Side Diff: chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc

Issue 1001553005: New "Save password" bubble for the Credential Manager API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments Created 5 years, 9 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h" 5 #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
6 6
7 #include "base/timer/timer.h" 7 #include "base/timer/timer.h"
8 #include "chrome/browser/profiles/profile.h" 8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_finder.h" 10 #include "chrome/browser/ui/browser_finder.h"
11 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" 11 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
12 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" 12 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
13 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" 13 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
14 #include "chrome/browser/ui/passwords/save_password_refusal_combobox_model.h" 14 #include "chrome/browser/ui/passwords/save_password_refusal_combobox_model.h"
15 #include "chrome/browser/ui/views/frame/browser_view.h" 15 #include "chrome/browser/ui/views/frame/browser_view.h"
16 #include "chrome/browser/ui/views/passwords/credentials_item_view.h" 16 #include "chrome/browser/ui/views/passwords/credentials_item_view.h"
17 #include "chrome/browser/ui/views/passwords/manage_credential_item_view.h" 17 #include "chrome/browser/ui/views/passwords/manage_credential_item_view.h"
18 #include "chrome/browser/ui/views/passwords/manage_password_items_view.h" 18 #include "chrome/browser/ui/views/passwords/manage_password_items_view.h"
19 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" 19 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h"
20 #include "chrome/browser/ui/views/passwords/save_account_more_combobox_model.h"
20 #include "chrome/grit/generated_resources.h" 21 #include "chrome/grit/generated_resources.h"
21 #include "content/public/browser/render_view_host.h" 22 #include "content/public/browser/render_view_host.h"
22 #include "ui/base/l10n/l10n_util.h" 23 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/resource/resource_bundle.h" 24 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/views/controls/button/blue_button.h" 25 #include "ui/views/controls/button/blue_button.h"
25 #include "ui/views/controls/button/label_button.h" 26 #include "ui/views/controls/button/label_button.h"
26 #include "ui/views/controls/combobox/combobox.h" 27 #include "ui/views/controls/combobox/combobox.h"
27 #include "ui/views/controls/combobox/combobox_listener.h" 28 #include "ui/views/controls/combobox/combobox_listener.h"
28 #include "ui/views/controls/link.h" 29 #include "ui/views/controls/link.h"
29 #include "ui/views/controls/link_listener.h" 30 #include "ui/views/controls/link_listener.h"
(...skipping 11 matching lines...) Expand all
41 42
42 namespace { 43 namespace {
43 44
44 const int kAutoSigninToastTimeout = 3; 45 const int kAutoSigninToastTimeout = 3;
45 const int kDesiredBubbleWidth = 370; 46 const int kDesiredBubbleWidth = 370;
46 47
47 enum ColumnSetType { 48 enum ColumnSetType {
48 // | | (FILL, FILL) | | 49 // | | (FILL, FILL) | |
49 // Used for the bubble's header, the credentials list, and for simple 50 // Used for the bubble's header, the credentials list, and for simple
50 // messages like "No passwords". 51 // messages like "No passwords".
51 SINGLE_VIEW_COLUMN_SET = 0, 52 SINGLE_VIEW_COLUMN_SET,
52 53
53 // | | (TRAILING, CENTER) | | (TRAILING, CENTER) | | 54 // | | (TRAILING, CENTER) | | (TRAILING, CENTER) | |
54 // Used for buttons at the bottom of the bubble which should nest at the 55 // Used for buttons at the bottom of the bubble which should nest at the
55 // bottom-right corner. 56 // bottom-right corner.
56 DOUBLE_BUTTON_COLUMN_SET = 1, 57 DOUBLE_BUTTON_COLUMN_SET,
57 58
58 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | | 59 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | |
59 // Used for buttons at the bottom of the bubble which should occupy 60 // Used for buttons at the bottom of the bubble which should occupy
60 // the corners. 61 // the corners.
61 LINK_BUTTON_COLUMN_SET = 2, 62 LINK_BUTTON_COLUMN_SET,
62 63
63 // | | (TRAILING, CENTER) | | 64 // | | (TRAILING, CENTER) | |
64 // Used when there is only one button which should next at the bottom-right 65 // Used when there is only one button which should next at the bottom-right
65 // corner. 66 // corner.
66 SINGLE_BUTTON_COLUMN_SET = 3, 67 SINGLE_BUTTON_COLUMN_SET,
68
69 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | | (TRAILING, CENTER) | |
70 // Used when there are three buttons.
71 TRIPLE_BUTTON_COLUMN_SET,
67 }; 72 };
68 73
69 enum TextRowType { ROW_SINGLE, ROW_MULTILINE }; 74 enum TextRowType { ROW_SINGLE, ROW_MULTILINE };
70 75
71 // Construct an appropriate ColumnSet for the given |type|, and add it 76 // Construct an appropriate ColumnSet for the given |type|, and add it
72 // to |layout|. 77 // to |layout|.
73 void BuildColumnSet(views::GridLayout* layout, ColumnSetType type) { 78 void BuildColumnSet(views::GridLayout* layout, ColumnSetType type) {
74 views::ColumnSet* column_set = layout->AddColumnSet(type); 79 views::ColumnSet* column_set = layout->AddColumnSet(type);
75 column_set->AddPaddingColumn(0, views::kPanelHorizMargin); 80 column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
76 int full_width = kDesiredBubbleWidth - (2 * views::kPanelHorizMargin); 81 int full_width = kDesiredBubbleWidth - (2 * views::kPanelHorizMargin);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 0, 119 0,
115 0); 120 0);
116 break; 121 break;
117 case SINGLE_BUTTON_COLUMN_SET: 122 case SINGLE_BUTTON_COLUMN_SET:
118 column_set->AddColumn(views::GridLayout::TRAILING, 123 column_set->AddColumn(views::GridLayout::TRAILING,
119 views::GridLayout::CENTER, 124 views::GridLayout::CENTER,
120 1, 125 1,
121 views::GridLayout::USE_PREF, 126 views::GridLayout::USE_PREF,
122 0, 127 0,
123 0); 128 0);
129 case TRIPLE_BUTTON_COLUMN_SET:
130 column_set->AddColumn(views::GridLayout::LEADING,
131 views::GridLayout::CENTER,
132 1,
133 views::GridLayout::USE_PREF,
134 0,
135 0);
136 column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
137 column_set->AddColumn(views::GridLayout::TRAILING,
138 views::GridLayout::CENTER,
139 0,
140 views::GridLayout::USE_PREF,
141 0,
142 0);
143 column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
144 column_set->AddColumn(views::GridLayout::TRAILING,
145 views::GridLayout::CENTER,
146 0,
147 views::GridLayout::USE_PREF,
148 0,
149 0);
150 break;
124 } 151 }
125 column_set->AddPaddingColumn(0, views::kPanelHorizMargin); 152 column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
126 } 153 }
127 154
128 // Given a layout and a model, add an appropriate title using a 155 // Given a layout and a model, add an appropriate title using a
129 // SINGLE_VIEW_COLUMN_SET, followed by a spacer row. 156 // SINGLE_VIEW_COLUMN_SET, followed by a spacer row.
130 void AddTitleRow(views::GridLayout* layout, ManagePasswordsBubbleModel* model) { 157 void AddTitleRow(views::GridLayout* layout, ManagePasswordsBubbleModel* model) {
131 views::Label* title_label = new views::Label(model->title()); 158 views::Label* title_label = new views::Label(model->title());
132 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 159 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
133 title_label->SetMultiLine(true); 160 title_label->SetMultiLine(true);
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 case SavePasswordRefusalComboboxModel::INDEX_NOPE: 407 case SavePasswordRefusalComboboxModel::INDEX_NOPE:
381 parent_->model()->OnNopeClicked(); 408 parent_->model()->OnNopeClicked();
382 parent_->Close(); 409 parent_->Close();
383 break; 410 break;
384 case SavePasswordRefusalComboboxModel::INDEX_NEVER_FOR_THIS_SITE: 411 case SavePasswordRefusalComboboxModel::INDEX_NEVER_FOR_THIS_SITE:
385 parent_->NotifyNeverForThisSiteClicked(); 412 parent_->NotifyNeverForThisSiteClicked();
386 break; 413 break;
387 } 414 }
388 } 415 }
389 416
390 // ManagePasswordsBubbleView::ConfirmNeverView --------------------------------- 417 // ManagePasswordsBubbleView::SaveAccountView ---------------------------------
418
419 // A view offering the user the ability to save credentials. Contains 2 buttons
420 // and a "More" combobox.
421 class ManagePasswordsBubbleView::SaveAccountView
422 : public views::View,
423 public views::ButtonListener,
424 public views::ComboboxListener {
425 public:
426 explicit SaveAccountView(ManagePasswordsBubbleView* parent);
427
428 private:
429 // views::ButtonListener:
430 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
431
432 // Handles the event when the user changes an index of a combobox.
433 void OnPerformAction(views::Combobox* source) override;
434
435 ManagePasswordsBubbleView* parent_;
436
437 views::BlueButton* save_button_;
438 views::LabelButton* no_button_;
439
440 // The combobox doesn't take ownership of its model. If we created a
441 // combobox we need to ensure that we delete the model here, and because the
442 // combobox uses the model in it's destructor, we need to make sure we
443 // delete the model _after_ the combobox itself is deleted.
444 SaveAccountMoreComboboxModel combobox_model_;
445 scoped_ptr<views::Combobox> more_combobox_;
446 };
447
448 ManagePasswordsBubbleView::SaveAccountView::SaveAccountView(
449 ManagePasswordsBubbleView* parent)
450 : parent_(parent) {
451 DCHECK(parent_->model()->IsNewUIActive());
452 views::GridLayout* layout = new views::GridLayout(this);
453 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
454 SetLayoutManager(layout);
455
456 save_button_ = new views::BlueButton(
457 this,
458 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_ACCOUNT_BUTTON));
459 save_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
460 ui::ResourceBundle::SmallFont));
461
462 no_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
463 IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SMART_LOCK_NO_THANKS_BUTTON));
464 no_button_->SetStyle(views::Button::STYLE_BUTTON);
465 no_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
466 ui::ResourceBundle::SmallFont));
467
468 more_combobox_.reset(new views::Combobox(&combobox_model_));
469 more_combobox_->set_owned_by_client();
470 more_combobox_->set_listener(this);
471 more_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
472
473 // Title row.
474 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
475 AddTitleRow(layout, parent_->model());
476
477 // Button row.
478 BuildColumnSet(layout, TRIPLE_BUTTON_COLUMN_SET);
479 layout->StartRow(0, TRIPLE_BUTTON_COLUMN_SET);
480 layout->AddView(more_combobox_.get());
481 layout->AddView(save_button_);
482 layout->AddView(no_button_);
483 // Extra padding for visual awesomeness.
484 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
485
486 parent_->set_initially_focused_view(save_button_);
487 }
488
489 void ManagePasswordsBubbleView::SaveAccountView::ButtonPressed(
490 views::Button* sender,
491 const ui::Event& event) {
492 if (sender == save_button_)
493 parent_->model()->OnSaveClicked();
494 else if (sender == no_button_)
495 parent_->model()->OnNopeClicked();
496 else
497 NOTREACHED();
498
499 parent_->Close();
500 }
501
502 void ManagePasswordsBubbleView::SaveAccountView::OnPerformAction(
503 views::Combobox* source) {
504 DCHECK_EQ(source, more_combobox_);
505 switch (more_combobox_->selected_index()) {
506 case SaveAccountMoreComboboxModel::INDEX_MORE:
507 break;
508 case SaveAccountMoreComboboxModel::INDEX_NEVER_FOR_THIS_SITE:
509 parent_->NotifyNeverForThisSiteClicked();
510 break;
511 case SaveAccountMoreComboboxModel::INDEX_SETTINGS:
512 parent_->model()->OnManageLinkClicked();
513 parent_->Close();
514 break;
515 }
516 }
517
518 // ManagePasswordsBubbleView::ConfirmNeverView --------------------------------
391 519
392 // A view offering the user the ability to undo her decision to never save 520 // A view offering the user the ability to undo her decision to never save
393 // passwords for a particular site. 521 // passwords for a particular site.
394 class ManagePasswordsBubbleView::ConfirmNeverView 522 class ManagePasswordsBubbleView::ConfirmNeverView
395 : public views::View, 523 : public views::View,
396 public views::ButtonListener { 524 public views::ButtonListener {
397 public: 525 public:
398 explicit ConfirmNeverView(ManagePasswordsBubbleView* parent); 526 explicit ConfirmNeverView(ManagePasswordsBubbleView* parent);
399 ~ConfirmNeverView() override; 527 ~ConfirmNeverView() override;
400 528
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 1103
976 void ManagePasswordsBubbleView::OnWidgetClosing(views::Widget* /*widget*/) { 1104 void ManagePasswordsBubbleView::OnWidgetClosing(views::Widget* /*widget*/) {
977 if (anchor_view_) 1105 if (anchor_view_)
978 anchor_view_->SetActive(false); 1106 anchor_view_->SetActive(false);
979 } 1107 }
980 1108
981 void ManagePasswordsBubbleView::Refresh() { 1109 void ManagePasswordsBubbleView::Refresh() {
982 RemoveAllChildViews(true); 1110 RemoveAllChildViews(true);
983 initially_focused_view_ = NULL; 1111 initially_focused_view_ = NULL;
984 if (model()->state() == password_manager::ui::PENDING_PASSWORD_STATE) { 1112 if (model()->state() == password_manager::ui::PENDING_PASSWORD_STATE) {
985 if (model()->never_save_passwords()) 1113 if (model()->never_save_passwords()) {
986 AddChildView(new ConfirmNeverView(this)); 1114 AddChildView(new ConfirmNeverView(this));
987 else 1115 } else {
988 AddChildView(new PendingView(this)); 1116 if (model()->IsNewUIActive())
1117 AddChildView(new SaveAccountView(this));
1118 else
1119 AddChildView(new PendingView(this));
1120 }
989 } else if (model()->state() == password_manager::ui::BLACKLIST_STATE) { 1121 } else if (model()->state() == password_manager::ui::BLACKLIST_STATE) {
990 AddChildView(new BlacklistedView(this)); 1122 AddChildView(new BlacklistedView(this));
991 } else if (model()->state() == password_manager::ui::CONFIRMATION_STATE) { 1123 } else if (model()->state() == password_manager::ui::CONFIRMATION_STATE) {
992 AddChildView(new SaveConfirmationView(this)); 1124 AddChildView(new SaveConfirmationView(this));
993 } else if (model()->state() == 1125 } else if (model()->state() ==
994 password_manager::ui::CREDENTIAL_REQUEST_STATE) { 1126 password_manager::ui::CREDENTIAL_REQUEST_STATE) {
995 AddChildView(new AccountChooserView(this)); 1127 AddChildView(new AccountChooserView(this));
996 } else if (model()->state() == password_manager::ui::AUTO_SIGNIN_STATE) { 1128 } else if (model()->state() == password_manager::ui::AUTO_SIGNIN_STATE) {
997 AddChildView(new AutoSigninView(this)); 1129 AddChildView(new AutoSigninView(this));
998 } else { 1130 } else {
999 if (model()->IsNewUIActive()) 1131 if (model()->IsNewUIActive())
1000 AddChildView(new ManageAccountsView(this)); 1132 AddChildView(new ManageAccountsView(this));
1001 else 1133 else
1002 AddChildView(new ManageView(this)); 1134 AddChildView(new ManageView(this));
1003 } 1135 }
1004 GetLayoutManager()->Layout(this); 1136 GetLayoutManager()->Layout(this);
1005 } 1137 }
1006 1138
1007 void ManagePasswordsBubbleView::NotifyConfirmedNeverForThisSite() { 1139 void ManagePasswordsBubbleView::NotifyConfirmedNeverForThisSite() {
1008 model()->OnNeverForThisSiteClicked(); 1140 model()->OnNeverForThisSiteClicked();
1009 Close(); 1141 Close();
1010 } 1142 }
1011 1143
1012 void ManagePasswordsBubbleView::NotifyUndoNeverForThisSite() { 1144 void ManagePasswordsBubbleView::NotifyUndoNeverForThisSite() {
1013 model()->OnUndoNeverForThisSite(); 1145 model()->OnUndoNeverForThisSite();
1014 Refresh(); 1146 Refresh();
1147 SizeToContents();
1015 } 1148 }
1016 1149
1017 void ManagePasswordsBubbleView::NotifyNeverForThisSiteClicked() { 1150 void ManagePasswordsBubbleView::NotifyNeverForThisSiteClicked() {
1018 if (model()->local_credentials().empty()) { 1151 if (model()->local_credentials().empty()) {
1019 // Skip confirmation if there are no existing passwords for this site. 1152 // Skip confirmation if there are no existing passwords for this site.
1020 NotifyConfirmedNeverForThisSite(); 1153 NotifyConfirmedNeverForThisSite();
1021 } else { 1154 } else {
1022 model()->OnConfirmationForNeverForThisSite(); 1155 model()->OnConfirmationForNeverForThisSite();
1023 Refresh(); 1156 Refresh();
1157 SizeToContents();
1024 } 1158 }
1025 } 1159 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698