manage_password_item_view.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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 "chrome/grit/generated_resources.h" 9#include "ui/base/l10n/l10n_util.h" 10#include "ui/base/resource/resource_bundle.h" 11#include "ui/resources/grit/ui_resources.h" 12#include "ui/views/border.h" 13#include "ui/views/controls/button/button.h" 14#include "ui/views/controls/button/image_button.h" 15#include "ui/views/controls/label.h" 16#include "ui/views/controls/link.h" 17#include "ui/views/controls/link_listener.h" 18#include "ui/views/layout/fill_layout.h" 19#include "ui/views/layout/grid_layout.h" 20#include "ui/views/layout/layout_constants.h" 21 22namespace { 23 24enum ColumnSets { 25 TWO_COLUMN_SET, 26 THREE_COLUMN_SET 27}; 28 29void BuildColumnSet(views::GridLayout* layout, int column_set_id) { 30 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 31 32 // The username/"Deleted!" field. 33 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 34 column_set->AddColumn(views::GridLayout::FILL, 35 views::GridLayout::FILL, 36 2, 37 views::GridLayout::USE_PREF, 38 0, 39 0); 40 41 // The password/"Undo!" field. 42 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 43 column_set->AddColumn(views::GridLayout::FILL, 44 views::GridLayout::FILL, 45 1, 46 views::GridLayout::USE_PREF, 47 0, 48 0); 49 50 // If we're in manage-mode, we need another column for the delete button. 51 if (column_set_id == THREE_COLUMN_SET) { 52 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 53 column_set->AddColumn(views::GridLayout::TRAILING, 54 views::GridLayout::FILL, 55 0, 56 views::GridLayout::USE_PREF, 57 0, 58 0); 59 } 60 column_set->AddPaddingColumn(0, views::kItemLabelSpacing); 61} 62 63views::Label* GenerateUsernameLabel(const autofill::PasswordForm& form) { 64 views::Label* label = new views::Label(form.username_value); 65 label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 66 ui::ResourceBundle::SmallFont)); 67 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 68 return label; 69} 70 71views::Label* GeneratePasswordLabel(const autofill::PasswordForm& form) { 72 views::Label* label = new views::Label(form.password_value); 73 label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 74 ui::ResourceBundle::SmallFont)); 75 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 76 label->SetObscured(true); 77 return label; 78} 79 80} // namespace 81 82// Render credentials in two columns: username and password. 83class ManagePasswordItemView::PendingView : public views::View { 84 public: 85 explicit PendingView(ManagePasswordItemView* parent); 86 87 private: 88 virtual ~PendingView(); 89}; 90 91ManagePasswordItemView::PendingView::PendingView( 92 ManagePasswordItemView* parent) { 93 views::GridLayout* layout = new views::GridLayout(this); 94 SetLayoutManager(layout); 95 96 BuildColumnSet(layout, TWO_COLUMN_SET); 97 layout->StartRowWithPadding( 98 0, TWO_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); 99 layout->AddView(GenerateUsernameLabel(parent->password_form_)); 100 layout->AddView(GeneratePasswordLabel(parent->password_form_)); 101 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 102} 103 104ManagePasswordItemView::PendingView::~PendingView() { 105} 106 107// Render credentials in three columns: username, password, and delete. 108class ManagePasswordItemView::ManageView : public views::View, 109 public views::ButtonListener { 110 public: 111 explicit ManageView(ManagePasswordItemView* parent); 112 113 private: 114 virtual ~ManageView(); 115 116 // views::ButtonListener: 117 virtual void ButtonPressed(views::Button* sender, 118 const ui::Event& event) OVERRIDE; 119 120 views::ImageButton* delete_button_; 121 ManagePasswordItemView* parent_; 122}; 123 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 147ManagePasswordItemView::ManageView::~ManageView() { 148} 149 150void ManagePasswordItemView::ManageView::ButtonPressed(views::Button* sender, 151 const ui::Event& event) { 152 DCHECK_EQ(delete_button_, sender); 153 parent_->NotifyClickedDelete(); 154} 155 156// Render a notification to the user that a password has been removed, and 157// offer an undo link. 158class ManagePasswordItemView::UndoView : public views::View, 159 public views::LinkListener { 160 public: 161 explicit UndoView(ManagePasswordItemView* parent); 162 163 private: 164 virtual ~UndoView(); 165 166 // views::LinkListener: 167 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 168 169 views::Link* undo_link_; 170 ManagePasswordItemView* parent_; 171}; 172 173ManagePasswordItemView::UndoView::UndoView(ManagePasswordItemView* parent) 174 : parent_(parent) { 175 views::GridLayout* layout = new views::GridLayout(this); 176 SetLayoutManager(layout); 177 178 views::Label* text = 179 new views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED)); 180 text->SetHorizontalAlignment(gfx::ALIGN_LEFT); 181 text->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 182 ui::ResourceBundle::SmallFont)); 183 184 undo_link_ = 185 new views::Link(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_UNDO)); 186 undo_link_->SetHorizontalAlignment(gfx::ALIGN_RIGHT); 187 undo_link_->set_listener(this); 188 undo_link_->SetUnderline(false); 189 undo_link_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( 190 ui::ResourceBundle::SmallFont)); 191 192 BuildColumnSet(layout, TWO_COLUMN_SET); 193 layout->StartRowWithPadding( 194 0, TWO_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); 195 layout->AddView(text); 196 layout->AddView(undo_link_); 197 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 198} 199 200ManagePasswordItemView::UndoView::~UndoView() { 201} 202 203void ManagePasswordItemView::UndoView::LinkClicked(views::Link* sender, 204 int event_flags) { 205 DCHECK_EQ(undo_link_, sender); 206 parent_->NotifyClickedUndo(); 207} 208 209// ManagePasswordItemView 210ManagePasswordItemView::ManagePasswordItemView( 211 ManagePasswordsBubbleModel* manage_passwords_bubble_model, 212 const autofill::PasswordForm& password_form, 213 password_manager::ui::PasswordItemPosition position) 214 : model_(manage_passwords_bubble_model), 215 password_form_(password_form), 216 delete_password_(false) { 217 views::FillLayout* layout = new views::FillLayout(); 218 SetLayoutManager(layout); 219 220 // When a password is displayed as the first item in a list, it has borders 221 // on both the top and bottom. When it's in the middle of a list, or at the 222 // end, it has a border only on the bottom. 223 SetBorder(views::Border::CreateSolidSidedBorder( 224 position == password_manager::ui::FIRST_ITEM ? 1 : 0, 225 0, 226 1, 227 0, 228 GetNativeTheme()->GetSystemColor( 229 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor))); 230 231 if (password_manager::ui::IsPendingState(model_->state())) { 232 AddChildView(new PendingView(this)); 233 } else { 234 AddChildView(new ManageView(this)); 235 } 236 GetLayoutManager()->Layout(this); 237} 238 239ManagePasswordItemView::~ManagePasswordItemView() { 240} 241 242void ManagePasswordItemView::NotifyClickedDelete() { 243 delete_password_ = true; 244 Refresh(); 245} 246 247void ManagePasswordItemView::NotifyClickedUndo() { 248 delete_password_ = false; 249 Refresh(); 250} 251 252void ManagePasswordItemView::Refresh() { 253 DCHECK(!password_manager::ui::IsPendingState(model_->state())); 254 255 RemoveAllChildViews(true); 256 if (delete_password_) 257 AddChildView(new UndoView(this)); 258 else 259 AddChildView(new ManageView(this)); 260 GetLayoutManager()->Layout(this); 261 262 // After the view is consistent, notify the model that the password needs to 263 // be updated (either removed or put back into the store, as appropriate. 264 model_->OnPasswordAction(password_form_, 265 delete_password_ 266 ? ManagePasswordsBubbleModel::REMOVE_PASSWORD 267 : ManagePasswordsBubbleModel::ADD_PASSWORD); 268} 269