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_password_items_view.h"
7 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
8 #include "chrome/grit/generated_resources.h"
9 #include "components/autofill/core/common/password_form.h"
10 #include "grit/components_strings.h"
11 #include "ui/base/l10n/l10n_util.h"
12 #include "ui/base/resource/resource_bundle.h"
13 #include "ui/resources/grit/ui_resources.h"
14 #include "ui/views/border.h"
15 #include "ui/views/controls/button/button.h"
16 #include "ui/views/controls/button/image_button.h"
17 #include "ui/views/controls/label.h"
18 #include "ui/views/controls/link.h"
19 #include "ui/views/controls/link_listener.h"
20 #include "ui/views/controls/separator.h"
21 #include "ui/views/layout/fill_layout.h"
22 #include "ui/views/layout/grid_layout.h"
23 #include "ui/views/layout/layout_constants.h"
33 void BuildColumnSetIfNeeded(views::GridLayout
* layout
, int column_set_id
) {
34 if (layout
->GetColumnSet(column_set_id
))
36 views::ColumnSet
* column_set
= layout
->AddColumnSet(column_set_id
);
38 // The username/"Deleted!"/Border field.
39 column_set
->AddPaddingColumn(0, views::kItemLabelSpacing
);
40 column_set
->AddColumn(views::GridLayout::FILL
,
41 views::GridLayout::FILL
,
43 views::GridLayout::USE_PREF
,
46 if (column_set_id
>= TWO_COLUMN_SET
) {
47 // The password/"Undo!" field.
48 column_set
->AddPaddingColumn(0, views::kItemLabelSpacing
);
49 column_set
->AddColumn(views::GridLayout::FILL
,
50 views::GridLayout::FILL
,
52 views::GridLayout::USE_PREF
,
56 // If we're in manage-mode, we need another column for the delete button.
57 if (column_set_id
== THREE_COLUMN_SET
) {
58 column_set
->AddPaddingColumn(0, views::kItemLabelSpacing
);
59 column_set
->AddColumn(views::GridLayout::TRAILING
,
60 views::GridLayout::FILL
,
62 views::GridLayout::USE_PREF
,
66 column_set
->AddPaddingColumn(0, views::kItemLabelSpacing
);
69 void AddBorderRow(views::GridLayout
* layout
, SkColor color
) {
70 BuildColumnSetIfNeeded(layout
, ONE_COLUMN_SET
);
71 layout
->StartRowWithPadding(0, ONE_COLUMN_SET
, 0,
72 views::kRelatedControlVerticalSpacing
);
73 views::Separator
* border
= new views::Separator(views::Separator::HORIZONTAL
);
74 border
->SetColor(color
);
75 layout
->AddView(border
);
78 views::Label
* GenerateUsernameLabel(const autofill::PasswordForm
& form
) {
79 views::Label
* label
= new views::Label(
80 form
.username_value
.empty()
81 ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN
)
82 : form
.username_value
);
83 label
->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
84 ui::ResourceBundle::SmallFont
));
85 label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
89 views::Label
* GeneratePasswordLabel(const autofill::PasswordForm
& form
) {
90 views::Label
* label
= new views::Label(form
.password_value
);
91 label
->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
92 ui::ResourceBundle::SmallFont
));
93 label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
94 label
->SetObscured(true);
100 // Manage credentials: stores credentials state and adds proper row to layout
101 // based on credential state.
102 class ManagePasswordItemsView::PasswordFormRow
: public views::ButtonListener
,
103 public views::LinkListener
{
105 PasswordFormRow(ManagePasswordItemsView
* host
,
106 const autofill::PasswordForm
* password_form
);
107 ~PasswordFormRow() override
= default;
109 void AddRow(views::GridLayout
* layout
);
112 void AddCredentialsRow(views::GridLayout
* layout
);
113 void AddUndoRow(views::GridLayout
* layout
);
115 // views::ButtonListener:
116 void ButtonPressed(views::Button
* sender
, const ui::Event
& event
) override
;
117 // views::LinkListener:
118 void LinkClicked(views::Link
* source
, int event_flags
) override
;
120 void ResetControls();
122 ManagePasswordItemsView
* host_
;
123 const autofill::PasswordForm
* password_form_
;
124 views::Link
* undo_link_
;
125 views::ImageButton
* delete_button_
;
129 ManagePasswordItemsView::PasswordFormRow::PasswordFormRow(
130 ManagePasswordItemsView
* host
, const autofill::PasswordForm
* password_form
)
132 password_form_(password_form
),
134 delete_button_(nullptr),
137 void ManagePasswordItemsView::PasswordFormRow::AddRow(
138 views::GridLayout
* layout
) {
142 AddCredentialsRow(layout
);
146 void ManagePasswordItemsView::PasswordFormRow::AddCredentialsRow(
147 views::GridLayout
* layout
) {
150 password_manager::ui::IsPendingState(host_
->model_
->state())
153 BuildColumnSetIfNeeded(layout
, column_set_id
);
154 layout
->StartRowWithPadding(0, column_set_id
, 0,
155 views::kRelatedControlVerticalSpacing
);
156 layout
->AddView(GenerateUsernameLabel(*password_form_
));
157 layout
->AddView(GeneratePasswordLabel(*password_form_
));
158 if (column_set_id
== THREE_COLUMN_SET
) {
159 ui::ResourceBundle
* rb
= &ui::ResourceBundle::GetSharedInstance();
160 delete_button_
= new views::ImageButton(this);
161 delete_button_
->SetImage(views::ImageButton::STATE_NORMAL
,
162 rb
->GetImageNamed(IDR_CLOSE_2
).ToImageSkia());
163 delete_button_
->SetImage(views::ImageButton::STATE_HOVERED
,
164 rb
->GetImageNamed(IDR_CLOSE_2_H
).ToImageSkia());
165 delete_button_
->SetImage(views::ImageButton::STATE_PRESSED
,
166 rb
->GetImageNamed(IDR_CLOSE_2_P
).ToImageSkia());
167 layout
->AddView(delete_button_
);
171 void ManagePasswordItemsView::PasswordFormRow::AddUndoRow(
172 views::GridLayout
* layout
) {
175 new views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED
));
176 text
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
177 text
->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
178 ui::ResourceBundle::SmallFont
));
180 new views::Link(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_UNDO
));
181 undo_link_
->SetHorizontalAlignment(gfx::ALIGN_RIGHT
);
182 undo_link_
->set_listener(this);
183 undo_link_
->SetUnderline(false);
184 undo_link_
->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
185 ui::ResourceBundle::SmallFont
));
186 BuildColumnSetIfNeeded(layout
, TWO_COLUMN_SET
);
187 layout
->StartRowWithPadding(0, TWO_COLUMN_SET
, 0,
188 views::kRelatedControlVerticalSpacing
);
189 layout
->AddView(text
);
190 layout
->AddView(undo_link_
);
193 void ManagePasswordItemsView::PasswordFormRow::ButtonPressed(
194 views::Button
* sender
, const ui::Event
& event
) {
195 DCHECK_EQ(delete_button_
, sender
);
197 host_
->NotifyPasswordFormStatusChanged(*password_form_
, deleted_
);
200 void ManagePasswordItemsView::PasswordFormRow::LinkClicked(views::Link
* sender
,
202 DCHECK_EQ(undo_link_
, sender
);
204 host_
->NotifyPasswordFormStatusChanged(*password_form_
, deleted_
);
207 void ManagePasswordItemsView::PasswordFormRow::ResetControls() {
208 delete_button_
= nullptr;
209 undo_link_
= nullptr;
212 // ManagePasswordItemsView
213 ManagePasswordItemsView::ManagePasswordItemsView(
214 ManagePasswordsBubbleModel
* manage_passwords_bubble_model
,
215 const std::vector
<const autofill::PasswordForm
*>& password_forms
)
216 : model_(manage_passwords_bubble_model
) {
217 for (const autofill::PasswordForm
* password_form
: password_forms
) {
218 password_forms_rows_
.push_back(
219 ManagePasswordItemsView::PasswordFormRow(this, password_form
));
224 ManagePasswordItemsView::~ManagePasswordItemsView() = default;
226 void ManagePasswordItemsView::AddRows() {
227 views::GridLayout
* layout
= new views::GridLayout(this);
228 SetLayoutManager(layout
);
229 SkColor color
= GetNativeTheme()->GetSystemColor(
230 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor
);
231 AddBorderRow(layout
, color
);
232 for (auto& row
: password_forms_rows_
) {
234 AddBorderRow(layout
, color
);
236 GetLayoutManager()->Layout(this);
239 void ManagePasswordItemsView::NotifyPasswordFormStatusChanged(
240 const autofill::PasswordForm
& password_form
, bool deleted
) {
242 // After the view is consistent, notify the model that the password needs to
243 // be updated (either removed or put back into the store, as appropriate.
244 model_
->OnPasswordAction(password_form
,
246 ? ManagePasswordsBubbleModel::REMOVE_PASSWORD
247 : ManagePasswordsBubbleModel::ADD_PASSWORD
);
250 void ManagePasswordItemsView::Refresh() {
251 DCHECK(!password_manager::ui::IsPendingState(model_
->state()));
252 RemoveAllChildViews(true);