OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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/options/passwords_page_view.h" | |
6 | |
7 #include "base/i18n/rtl.h" | |
8 #include "base/string_util.h" | |
9 #include "base/utf_string_conversions.h" | |
10 #include "chrome/browser/password_manager/password_store.h" | |
11 #include "chrome/browser/prefs/pref_service.h" | |
12 #include "chrome/browser/profiles/profile.h" | |
13 #include "chrome/common/pref_names.h" | |
14 #include "grit/generated_resources.h" | |
15 #include "ui/base/l10n/l10n_util.h" | |
16 #include "views/background.h" | |
17 #include "views/controls/button/native_button.h" | |
18 #include "views/layout/grid_layout.h" | |
19 #include "views/layout/layout_constants.h" | |
20 | |
21 using views::ColumnSet; | |
22 using views::GridLayout; | |
23 using webkit_glue::PasswordForm; | |
24 | |
25 /////////////////////////////////////////////////////////////////////////////// | |
26 // MultiLabelButtons | |
27 MultiLabelButtons::MultiLabelButtons(views::ButtonListener* listener, | |
28 const std::wstring& label, | |
29 const std::wstring& alt_label) | |
30 : NativeButton(listener, label), | |
31 label_(label), | |
32 alt_label_(alt_label) { | |
33 } | |
34 | |
35 gfx::Size MultiLabelButtons::GetPreferredSize() { | |
36 if (!IsVisible()) | |
37 return gfx::Size(); | |
38 | |
39 if (pref_size_.IsEmpty()) { | |
40 // Let's compute our preferred size. | |
41 std::wstring current_label = label(); | |
42 SetLabel(label_); | |
43 pref_size_ = NativeButton::GetPreferredSize(); | |
44 SetLabel(alt_label_); | |
45 gfx::Size alt_pref_size = NativeButton::GetPreferredSize(); | |
46 // Revert to the original label. | |
47 SetLabel(current_label); | |
48 pref_size_.SetSize(std::max(pref_size_.width(), alt_pref_size.width()), | |
49 std::max(pref_size_.height(), alt_pref_size.height())); | |
50 } | |
51 return gfx::Size(pref_size_.width(), pref_size_.height()); | |
52 } | |
53 | |
54 /////////////////////////////////////////////////////////////////////////////// | |
55 // PasswordsTableModel, public | |
56 PasswordsTableModel::PasswordsTableModel(Profile* profile) | |
57 : observer_(NULL), | |
58 row_count_observer_(NULL), | |
59 pending_login_query_(NULL), | |
60 saved_signons_cleanup_(&saved_signons_), | |
61 profile_(profile) { | |
62 DCHECK(profile && profile->GetPasswordStore(Profile::EXPLICIT_ACCESS)); | |
63 } | |
64 | |
65 PasswordsTableModel::~PasswordsTableModel() { | |
66 CancelLoginsQuery(); | |
67 } | |
68 | |
69 int PasswordsTableModel::RowCount() { | |
70 return static_cast<int>(saved_signons_.size()); | |
71 } | |
72 | |
73 string16 PasswordsTableModel::GetText(int row, | |
74 int col_id) { | |
75 switch (col_id) { | |
76 case IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN: { // Site. | |
77 // Force URL to have LTR directionality. | |
78 std::wstring url(saved_signons_[row]->display_url.display_url()); | |
79 return base::i18n::GetDisplayStringInLTRDirectionality( | |
80 WideToUTF16Hack(url)); | |
81 } | |
82 case IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN: { // Username. | |
83 std::wstring username = GetPasswordFormAt(row)->username_value; | |
84 base::i18n::AdjustStringForLocaleDirection(&username); | |
85 return WideToUTF16Hack(username); | |
86 } | |
87 default: | |
88 NOTREACHED() << "Invalid column."; | |
89 return string16(); | |
90 } | |
91 } | |
92 | |
93 int PasswordsTableModel::CompareValues(int row1, int row2, | |
94 int column_id) { | |
95 if (column_id == IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN) { | |
96 return saved_signons_[row1]->display_url.Compare( | |
97 saved_signons_[row2]->display_url, GetCollator()); | |
98 } | |
99 return TableModel::CompareValues(row1, row2, column_id); | |
100 } | |
101 | |
102 void PasswordsTableModel::SetObserver(ui::TableModelObserver* observer) { | |
103 observer_ = observer; | |
104 } | |
105 | |
106 void PasswordsTableModel::GetAllSavedLoginsForProfile() { | |
107 DCHECK(!pending_login_query_); | |
108 pending_login_query_ = password_store()->GetAutofillableLogins(this); | |
109 } | |
110 | |
111 void PasswordsTableModel::OnPasswordStoreRequestDone( | |
112 int handle, const std::vector<PasswordForm*>& result) { | |
113 DCHECK_EQ(pending_login_query_, handle); | |
114 pending_login_query_ = NULL; | |
115 | |
116 STLDeleteElements<PasswordRows>(&saved_signons_); | |
117 saved_signons_.resize(result.size(), NULL); | |
118 std::string languages = profile_->GetPrefs()->GetString( | |
119 prefs::kAcceptLanguages); | |
120 for (size_t i = 0; i < result.size(); ++i) { | |
121 saved_signons_[i] = new PasswordRow( | |
122 ui::SortedDisplayURL(result[i]->origin, languages), result[i]); | |
123 } | |
124 if (observer_) | |
125 observer_->OnModelChanged(); | |
126 if (row_count_observer_) | |
127 row_count_observer_->OnRowCountChanged(RowCount()); | |
128 } | |
129 | |
130 PasswordForm* PasswordsTableModel::GetPasswordFormAt(int row) { | |
131 DCHECK(row >= 0 && row < RowCount()); | |
132 return saved_signons_[row]->form.get(); | |
133 } | |
134 | |
135 void PasswordsTableModel::ForgetAndRemoveSignon(int row) { | |
136 DCHECK(row >= 0 && row < RowCount()); | |
137 PasswordRows::iterator target_iter = saved_signons_.begin() + row; | |
138 // Remove from DB, memory, and vector. | |
139 PasswordRow* password_row = *target_iter; | |
140 password_store()->RemoveLogin(*(password_row->form.get())); | |
141 delete password_row; | |
142 saved_signons_.erase(target_iter); | |
143 if (observer_) | |
144 observer_->OnItemsRemoved(row, 1); | |
145 if (row_count_observer_) | |
146 row_count_observer_->OnRowCountChanged(RowCount()); | |
147 } | |
148 | |
149 void PasswordsTableModel::ForgetAndRemoveAllSignons() { | |
150 PasswordRows::iterator iter = saved_signons_.begin(); | |
151 while (iter != saved_signons_.end()) { | |
152 // Remove from DB, memory, and vector. | |
153 PasswordRow* row = *iter; | |
154 password_store()->RemoveLogin(*(row->form.get())); | |
155 delete row; | |
156 iter = saved_signons_.erase(iter); | |
157 } | |
158 if (observer_) | |
159 observer_->OnModelChanged(); | |
160 if (row_count_observer_) | |
161 row_count_observer_->OnRowCountChanged(RowCount()); | |
162 } | |
163 | |
164 /////////////////////////////////////////////////////////////////////////////// | |
165 // PasswordsTableModel, private | |
166 void PasswordsTableModel::CancelLoginsQuery() { | |
167 if (pending_login_query_) { | |
168 password_store()->CancelLoginsQuery(pending_login_query_); | |
169 pending_login_query_ = NULL; | |
170 } | |
171 } | |
172 | |
173 /////////////////////////////////////////////////////////////////////////////// | |
174 // PasswordsPageView, public | |
175 PasswordsPageView::PasswordsPageView(Profile* profile) | |
176 : OptionsPageView(profile), | |
177 ALLOW_THIS_IN_INITIALIZER_LIST(show_button_( | |
178 this, | |
179 UTF16ToWide(l10n_util::GetStringUTF16( | |
180 IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON)), | |
181 UTF16ToWide(l10n_util::GetStringUTF16( | |
182 IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON)))), | |
183 ALLOW_THIS_IN_INITIALIZER_LIST(remove_button_( | |
184 this, | |
185 UTF16ToWide(l10n_util::GetStringUTF16( | |
186 IDS_PASSWORDS_PAGE_VIEW_REMOVE_BUTTON)))), | |
187 ALLOW_THIS_IN_INITIALIZER_LIST(remove_all_button_( | |
188 this, | |
189 UTF16ToWide(l10n_util::GetStringUTF16( | |
190 IDS_PASSWORDS_PAGE_VIEW_REMOVE_ALL_BUTTON)))), | |
191 table_model_(profile), | |
192 table_view_(NULL), | |
193 current_selected_password_(NULL) { | |
194 allow_show_passwords_.Init(prefs::kPasswordManagerAllowShowPasswords, | |
195 profile->GetPrefs(), | |
196 this); | |
197 } | |
198 | |
199 PasswordsPageView::~PasswordsPageView() { | |
200 // The model is going away, prevent the table from accessing it. | |
201 if (table_view_) | |
202 table_view_->SetModel(NULL); | |
203 } | |
204 | |
205 void PasswordsPageView::OnSelectionChanged() { | |
206 bool has_selection = table_view_->SelectedRowCount() > 0; | |
207 remove_button_.SetEnabled(has_selection); | |
208 | |
209 PasswordForm* selected = NULL; | |
210 if (has_selection) { | |
211 views::TableSelectionIterator iter = table_view_->SelectionBegin(); | |
212 selected = table_model_.GetPasswordFormAt(*iter); | |
213 DCHECK(++iter == table_view_->SelectionEnd()); | |
214 } | |
215 | |
216 if (selected != current_selected_password_) { | |
217 // Reset the password related views. | |
218 show_button_.SetLabel(UTF16ToWide( | |
219 l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON))); | |
220 show_button_.SetEnabled(has_selection); | |
221 password_label_.SetText(std::wstring()); | |
222 | |
223 current_selected_password_ = selected; | |
224 } | |
225 } | |
226 | |
227 void PasswordsPageView::ButtonPressed( | |
228 views::Button* sender, const views::Event& event) { | |
229 // Close will result in our destruction. | |
230 if (sender == &remove_all_button_) { | |
231 ConfirmMessageBoxDialog::Run( | |
232 GetWindow()->GetNativeWindow(), | |
233 this, | |
234 UTF16ToWide(l10n_util::GetStringUTF16( | |
235 IDS_PASSWORDS_PAGE_VIEW_TEXT_DELETE_ALL_PASSWORDS)), | |
236 UTF16ToWide(l10n_util::GetStringUTF16( | |
237 IDS_PASSWORDS_PAGE_VIEW_CAPTION_DELETE_ALL_PASSWORDS))); | |
238 return; | |
239 } | |
240 | |
241 // The following require a selection (and only one, since table is single- | |
242 // select only). | |
243 views::TableSelectionIterator iter = table_view_->SelectionBegin(); | |
244 int row = *iter; | |
245 PasswordForm* selected = table_model_.GetPasswordFormAt(row); | |
246 DCHECK(++iter == table_view_->SelectionEnd()); | |
247 | |
248 if (sender == &remove_button_) { | |
249 table_model_.ForgetAndRemoveSignon(row); | |
250 } else if (sender == &show_button_) { | |
251 if (password_label_.GetText().length() == 0 && | |
252 allow_show_passwords_.GetValue()) { | |
253 password_label_.SetText(selected->password_value); | |
254 show_button_.SetLabel(UTF16ToWide( | |
255 l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON))); | |
256 } else { | |
257 HidePassword(); | |
258 } | |
259 } else { | |
260 NOTREACHED() << "Invalid button."; | |
261 } | |
262 } | |
263 | |
264 void PasswordsPageView::OnRowCountChanged(size_t rows) { | |
265 remove_all_button_.SetEnabled(rows > 0); | |
266 } | |
267 | |
268 void PasswordsPageView::OnConfirmMessageAccept() { | |
269 table_model_.ForgetAndRemoveAllSignons(); | |
270 } | |
271 | |
272 /////////////////////////////////////////////////////////////////////////////// | |
273 // PasswordsPageView, protected | |
274 void PasswordsPageView::InitControlLayout() { | |
275 SetupButtonsAndLabels(); | |
276 SetupTable(); | |
277 | |
278 // Do the layout thing. | |
279 const int top_column_set_id = 0; | |
280 GridLayout* layout = GridLayout::CreatePanel(this); | |
281 SetLayoutManager(layout); | |
282 | |
283 // Design the grid. | |
284 ColumnSet* column_set = layout->AddColumnSet(top_column_set_id); | |
285 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, | |
286 GridLayout::USE_PREF, 0, 0); | |
287 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); | |
288 column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, | |
289 GridLayout::USE_PREF, 0, 0); | |
290 | |
291 // Fill the grid. | |
292 layout->StartRow(0, top_column_set_id); | |
293 layout->AddView(table_view_, 1, 8, GridLayout::FILL, | |
294 GridLayout::FILL); | |
295 layout->AddView(&remove_button_); | |
296 layout->StartRowWithPadding(0, top_column_set_id, 0, | |
297 views::kRelatedControlVerticalSpacing); | |
298 layout->SkipColumns(1); | |
299 layout->AddView(&remove_all_button_); | |
300 layout->StartRowWithPadding(0, top_column_set_id, 0, | |
301 views::kRelatedControlVerticalSpacing); | |
302 layout->SkipColumns(1); | |
303 layout->AddView(&show_button_); | |
304 layout->StartRowWithPadding(0, top_column_set_id, 0, | |
305 views::kRelatedControlVerticalSpacing); | |
306 layout->SkipColumns(1); | |
307 layout->AddView(&password_label_); | |
308 layout->AddPaddingRow(1, 0); | |
309 | |
310 // Ask the database for saved password data. | |
311 table_model_.GetAllSavedLoginsForProfile(); | |
312 } | |
313 | |
314 /////////////////////////////////////////////////////////////////////////////// | |
315 // PasswordsPageView, private | |
316 void PasswordsPageView::SetupButtonsAndLabels() { | |
317 // Disable all buttons in the first place. | |
318 show_button_.set_parent_owned(false); | |
319 show_button_.SetEnabled(false); | |
320 | |
321 remove_button_.set_parent_owned(false); | |
322 remove_button_.SetEnabled(false); | |
323 | |
324 remove_all_button_.set_parent_owned(false); | |
325 remove_all_button_.SetEnabled(false); | |
326 | |
327 password_label_.set_parent_owned(false); | |
328 } | |
329 | |
330 void PasswordsPageView::SetupTable() { | |
331 // Tell the table model we are concern about how many rows it has. | |
332 table_model_.set_row_count_observer(this); | |
333 | |
334 // Creates the different columns for the table. | |
335 // The float resize values are the result of much tinkering. | |
336 std::vector<ui::TableColumn> columns; | |
337 columns.push_back(ui::TableColumn(IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN, | |
338 ui::TableColumn::LEFT, -1, 0.55f)); | |
339 columns.back().sortable = true; | |
340 columns.push_back(ui::TableColumn( | |
341 IDS_PASSWORDS_PAGE_VIEW_USERNAME_COLUMN, ui::TableColumn::LEFT, | |
342 -1, 0.37f)); | |
343 columns.back().sortable = true; | |
344 table_view_ = new views::TableView(&table_model_, columns, views::TEXT_ONLY, | |
345 true, true, true); | |
346 // Make the table initially sorted by host. | |
347 views::TableView::SortDescriptors sort; | |
348 sort.push_back(views::TableView::SortDescriptor( | |
349 IDS_PASSWORDS_PAGE_VIEW_SITE_COLUMN, true)); | |
350 table_view_->SetSortDescriptors(sort); | |
351 table_view_->SetObserver(this); | |
352 } | |
353 | |
354 void PasswordsPageView::HidePassword() { | |
355 password_label_.SetText(L""); | |
356 show_button_.SetLabel(UTF16ToWide( | |
357 l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_SHOW_BUTTON))); | |
358 } | |
359 | |
360 void PasswordsPageView::NotifyPrefChanged(const std::string* pref_name) { | |
361 if (!pref_name || *pref_name == prefs::kPasswordManagerAllowShowPasswords) { | |
362 bool show = allow_show_passwords_.GetValue(); | |
363 if (!show) | |
364 HidePassword(); | |
365 show_button_.SetVisible(show); | |
366 password_label_.SetVisible(show); | |
367 // Update the layout (it may depend on the button size). | |
368 show_button_.InvalidateLayout(); | |
369 Layout(); | |
370 } | |
371 } | |
OLD | NEW |