manage_password_item_view.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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. 4 5#include "chrome/browser/ui/views/passwords/manage_password_item_view.h" 6 7#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" 8#include "components/password_manager/core/common/password_manager_ui.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/resources/grit/ui_resources.h" 13#include "ui/views/controls/button/button.h" 14#include "ui/views/controls/button/image_button.h" 15#include "ui/views/layout/fill_layout.h" 16#include "ui/views/layout/grid_layout.h" 17#include "ui/views/layout/layout_constants.h" 18 19namespace { 20 21enum FieldType { USERNAME_FIELD, PASSWORD_FIELD }; 22 23// Upper limit on the size of the username and password fields. 24const int kUsernameFieldSize = 30; 25const int kPasswordFieldSize = 22; 26 27// Returns the width of |type| field. 28int GetFieldWidth(FieldType type) { 29 return ui::ResourceBundle::GetSharedInstance() 30 .GetFontList(ui::ResourceBundle::SmallFont) 31 .GetExpectedTextWidth(type == USERNAME_FIELD ? kUsernameFieldSize 32 : kPasswordFieldSize); 33} 34 35int FirstFieldWidth() { 36 return std::max( 37 GetFieldWidth(USERNAME_FIELD), 38 views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED)) 39 .GetPreferredSize() 40 .width()); 41} 42 43int SecondFieldWidth() { 44 return std::max( 45 GetFieldWidth(PASSWORD_FIELD), 46 views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_UNDO)) 47 .GetPreferredSize() 48 .width()); 49} 50 51enum ColumnSets { TWO_COLUMN_SET = 0, THREE_COLUMN_SET }; 52 53void BuildColumnSet(views::GridLayout* layout, int column_set_id) { 54 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 55 56 // The username/"Deleted!" field. 57 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 58 column_set->AddColumn(views::GridLayout::FILL, 59 views::GridLayout::FILL, 60 0, 61 views::GridLayout::FIXED, 62 FirstFieldWidth(), 63 FirstFieldWidth()); 64 65 // The password/"Undo!" field. 66 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 67 column_set->AddColumn(views::GridLayout::FILL, 68 views::GridLayout::FILL, 69 1, 70 views::GridLayout::USE_PREF, 71 SecondFieldWidth(), 72 SecondFieldWidth()); 73 74 // If we're in manage-mode, we need another column for the delete button. 75 if (column_set_id == THREE_COLUMN_SET) { 76 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 77 column_set->AddColumn(views::GridLayout::TRAILING, 78 views::GridLayout::FILL, 79 0, 80 views::GridLayout::USE_PREF, 81 0, 82 0); 83 } 84 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 85} 86 87views::Label* GenerateUsernameLabel(const autofill::PasswordForm& form) { 88 views::Label* label = new views::Label(form.username_value); 89 label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 90 ui::ResourceBundle::SmallFont)); 91 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 92 return label; 93} 94 95views::Label* GeneratePasswordLabel(const autofill::PasswordForm& form) { 96 views::Label* label = new views::Label(form.password_value); 97 label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 98 ui::ResourceBundle::SmallFont)); 99 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 100 label->SetObscured(true); 101 return label; 102} 103 104} // namespace 105 106// Pending View 107ManagePasswordItemView::PendingView::PendingView( 108 ManagePasswordItemView* parent) { 109 views::GridLayout* layout = new views::GridLayout(this); 110 SetLayoutManager(layout); 111 112 BuildColumnSet(layout, TWO_COLUMN_SET); 113 layout->StartRowWithPadding( 114 0, TWO_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); 115 layout->AddView(GenerateUsernameLabel(parent->password_form_)); 116 layout->AddView(GeneratePasswordLabel(parent->password_form_)); 117 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 118} 119 120ManagePasswordItemView::PendingView::~PendingView() { 121} 122 123// Manage View 124ManagePasswordItemView::ManageView::ManageView(ManagePasswordItemView* parent) 125 : parent_(parent) { 126 views::GridLayout* layout = new views::GridLayout(this); 127 SetLayoutManager(layout); 128 129 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); 130 delete_button_ = new views::ImageButton(this); 131 delete_button_->SetImage(views::ImageButton::STATE_NORMAL, 132 rb->GetImageNamed(IDR_CLOSE_2).ToImageSkia()); 133 delete_button_->SetImage(views::ImageButton::STATE_HOVERED, 134 rb->GetImageNamed(IDR_CLOSE_2_H).ToImageSkia()); 135 delete_button_->SetImage(views::ImageButton::STATE_PRESSED, 136 rb->GetImageNamed(IDR_CLOSE_2_P).ToImageSkia()); 137 138 BuildColumnSet(layout, THREE_COLUMN_SET); 139 layout->StartRowWithPadding( 140 0, THREE_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); 141 layout->AddView(GenerateUsernameLabel(parent->password_form_)); 142 layout->AddView(GeneratePasswordLabel(parent->password_form_)); 143 layout->AddView(delete_button_); 144 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 145} 146 147void ManagePasswordItemView::ManageView::ButtonPressed(views::Button* sender, 148 const ui::Event& event) { 149 DCHECK_EQ(delete_button_, sender); 150 parent_->NotifyClickedDelete(); 151} 152 153ManagePasswordItemView::ManageView::~ManageView() { 154} 155 156// Undo View 157ManagePasswordItemView::UndoView::UndoView(ManagePasswordItemView* parent) 158 : parent_(parent) { 159 views::GridLayout* layout = new views::GridLayout(this); 160 SetLayoutManager(layout); 161 162 views::Label* text = 163 new views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED)); 164 text->SetHorizontalAlignment(gfx::ALIGN_LEFT); 165 text->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 166 ui::ResourceBundle::SmallFont)); 167 168 undo_link_ = 169 new views::Link(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_UNDO)); 170 undo_link_->SetHorizontalAlignment(gfx::ALIGN_RIGHT); 171 undo_link_->set_listener(this); 172 undo_link_->SetUnderline(false); 173 undo_link_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 174 ui::ResourceBundle::SmallFont)); 175 176 BuildColumnSet(layout, TWO_COLUMN_SET); 177 layout->StartRowWithPadding( 178 0, TWO_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); 179 layout->AddView(text); 180 layout->AddView(undo_link_); 181 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 182} 183 184void ManagePasswordItemView::UndoView::LinkClicked(views::Link* sender, 185 int event_flags) { 186 DCHECK_EQ(undo_link_, sender); 187 parent_->NotifyClickedUndo(); 188} 189 190ManagePasswordItemView::UndoView::~UndoView() { 191} 192 193// ManagePasswordItemView 194ManagePasswordItemView::ManagePasswordItemView( 195 ManagePasswordsBubbleModel* manage_passwords_bubble_model, 196 autofill::PasswordForm password_form, 197 password_manager::ui::PasswordItemPosition position) 198 : model_(manage_passwords_bubble_model), 199 password_form_(password_form), 200 delete_password_(false) { 201 views::FillLayout* layout = new views::FillLayout(); 202 SetLayoutManager(layout); 203 204 // When a password is displayed as the first item in a list, it has borders 205 // on both the top and bottom. When it's in the middle of a list, or at the 206 // end, it has a border only on the bottom. 207 SetBorder(views::Border::CreateSolidSidedBorder( 208 position == password_manager::ui::FIRST_ITEM ? 1 : 0, 209 0, 210 1, 211 0, 212 GetNativeTheme()->GetSystemColor( 213 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor))); 214 215 if (password_manager::ui::IsPendingState(model_->state())) { 216 AddChildView(new PendingView(this)); 217 } else { 218 AddChildView(new ManageView(this)); 219 } 220 GetLayoutManager()->Layout(this); 221} 222 223ManagePasswordItemView::~ManagePasswordItemView() { 224} 225 226void ManagePasswordItemView::Refresh() { 227 DCHECK(!password_manager::ui::IsPendingState(model_->state())); 228 229 RemoveAllChildViews(true); 230 if (delete_password_) 231 AddChildView(new UndoView(this)); 232 else 233 AddChildView(new ManageView(this)); 234 GetLayoutManager()->Layout(this); 235 236 // After the view is consistent, notify the model that the password needs to 237 // be updated (either removed or put back into the store, as appropriate. 238 model_->OnPasswordAction(password_form_, 239 delete_password_ 240 ? ManagePasswordsBubbleModel::REMOVE_PASSWORD 241 : ManagePasswordsBubbleModel::ADD_PASSWORD); 242} 243 244void ManagePasswordItemView::NotifyClickedDelete() { 245 delete_password_ = true; 246 Refresh(); 247} 248 249void ManagePasswordItemView::NotifyClickedUndo() { 250 delete_password_ = false; 251 Refresh(); 252} 253