OLD | NEW |
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/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
8 #include "chrome/browser/chrome_notification_types.h" | 8 #include "chrome/browser/chrome_notification_types.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/browser_window.h" | 11 #include "chrome/browser/ui/browser_window.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_bubble_ui_controller.h" | 13 #include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h" |
14 #include "chrome/browser/ui/views/frame/browser_view.h" | 14 #include "chrome/browser/ui/views/frame/browser_view.h" |
15 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 15 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
16 #include "chrome/browser/ui/views/passwords/manage_password_item_view.h" | 16 #include "chrome/browser/ui/views/passwords/manage_password_item_view.h" |
17 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" | 17 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" |
18 #include "content/public/browser/notification_source.h" | 18 #include "content/public/browser/notification_source.h" |
19 #include "content/public/browser/web_contents_view.h" | 19 #include "content/public/browser/web_contents_view.h" |
20 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" |
21 #include "ui/base/l10n/l10n_util.h" | 21 #include "ui/base/l10n/l10n_util.h" |
22 #include "ui/base/models/combobox_model.h" | 22 #include "ui/base/models/combobox_model.h" |
23 #include "ui/base/resource/resource_bundle.h" | 23 #include "ui/base/resource/resource_bundle.h" |
24 #include "ui/gfx/text_utils.h" | 24 #include "ui/gfx/text_utils.h" |
25 #include "ui/views/controls/button/blue_button.h" | 25 #include "ui/views/controls/button/blue_button.h" |
26 #include "ui/views/controls/button/label_button.h" | 26 #include "ui/views/controls/button/label_button.h" |
27 #include "ui/views/controls/combobox/combobox.h" | 27 #include "ui/views/controls/combobox/combobox.h" |
| 28 #include "ui/views/layout/fill_layout.h" |
28 #include "ui/views/layout/grid_layout.h" | 29 #include "ui/views/layout/grid_layout.h" |
29 #include "ui/views/layout/layout_constants.h" | 30 #include "ui/views/layout/layout_constants.h" |
30 | 31 |
31 | 32 |
32 // Helpers -------------------------------------------------------------------- | 33 // Helpers -------------------------------------------------------------------- |
33 | 34 |
34 namespace { | 35 namespace { |
35 | 36 |
36 enum FieldType { USERNAME_FIELD, PASSWORD_FIELD }; | |
37 | |
38 // Upper limit on the size of the username and password fields. | |
39 const int kUsernameFieldSize = 30; | |
40 const int kPasswordFieldSize = 22; | |
41 | |
42 // Returns the width of |type| field. | |
43 int GetFieldWidth(FieldType type) { | |
44 return ui::ResourceBundle::GetSharedInstance() | |
45 .GetFontList(ui::ResourceBundle::SmallFont) | |
46 .GetExpectedTextWidth(type == USERNAME_FIELD ? kUsernameFieldSize | |
47 : kPasswordFieldSize); | |
48 } | |
49 | |
50 class SavePasswordRefusalComboboxModel : public ui::ComboboxModel { | 37 class SavePasswordRefusalComboboxModel : public ui::ComboboxModel { |
51 public: | 38 public: |
52 enum { INDEX_NOPE = 0, INDEX_NEVER_FOR_THIS_SITE = 1, }; | 39 enum { INDEX_NOPE = 0, INDEX_NEVER_FOR_THIS_SITE = 1, }; |
53 | 40 |
54 SavePasswordRefusalComboboxModel() { | 41 SavePasswordRefusalComboboxModel() { |
55 items_.push_back( | 42 items_.push_back( |
56 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CANCEL_BUTTON)); | 43 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CANCEL_BUTTON)); |
57 items_.push_back( | 44 items_.push_back( |
58 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON)); | 45 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON)); |
59 } | 46 } |
(...skipping 25 matching lines...) Expand all Loading... |
85 ManagePasswordsBubbleUIController::FromWebContents(web_contents); | 72 ManagePasswordsBubbleUIController::FromWebContents(web_contents); |
86 ManagePasswordsBubbleView::ShowBubble( | 73 ManagePasswordsBubbleView::ShowBubble( |
87 web_contents, | 74 web_contents, |
88 controller->manage_passwords_bubble_needs_showing() | 75 controller->manage_passwords_bubble_needs_showing() |
89 ? ManagePasswordsBubbleView::AUTOMATIC | 76 ? ManagePasswordsBubbleView::AUTOMATIC |
90 : ManagePasswordsBubbleView::USER_ACTION); | 77 : ManagePasswordsBubbleView::USER_ACTION); |
91 } | 78 } |
92 | 79 |
93 } // namespace chrome | 80 } // namespace chrome |
94 | 81 |
| 82 // ManagePasswordsBubbleView::PendingView ------------------------------------- |
| 83 |
| 84 ManagePasswordsBubbleView::PendingView::PendingView( |
| 85 ManagePasswordsBubbleView* parent) |
| 86 : parent_(parent) { |
| 87 views::GridLayout* layout = new views::GridLayout(this); |
| 88 SetLayoutManager(layout); |
| 89 |
| 90 // Create the pending credential item, save button and refusal combobox. |
| 91 ManagePasswordItemView* item = |
| 92 new ManagePasswordItemView(parent->model(), |
| 93 parent->model()->pending_credentials(), |
| 94 ManagePasswordItemView::FIRST_ITEM); |
| 95 save_button_ = new views::BlueButton( |
| 96 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON)); |
| 97 refuse_combobox_ = |
| 98 new views::Combobox(new SavePasswordRefusalComboboxModel()); |
| 99 refuse_combobox_->set_listener(this); |
| 100 refuse_combobox_->SetStyle(views::Combobox::STYLE_ACTION); |
| 101 |
| 102 // Title row. |
| 103 parent->BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET); |
| 104 parent->AddTitleRow(layout); |
| 105 |
| 106 // Credential row. |
| 107 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); |
| 108 layout->AddView(item); |
| 109 |
| 110 // Button row. |
| 111 parent->BuildColumnSet(layout, DOUBLE_BUTTON_COLUMN_SET); |
| 112 layout->StartRowWithPadding( |
| 113 0, DOUBLE_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); |
| 114 layout->AddView(save_button_); |
| 115 layout->AddView(refuse_combobox_); |
| 116 |
| 117 // Extra padding for visual awesomeness. |
| 118 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 119 } |
| 120 |
| 121 ManagePasswordsBubbleView::PendingView::~PendingView() { |
| 122 } |
| 123 |
| 124 void ManagePasswordsBubbleView::PendingView::ButtonPressed( |
| 125 views::Button* sender, |
| 126 const ui::Event& event) { |
| 127 DCHECK(sender == save_button_); |
| 128 parent_->model()->OnSaveClicked(); |
| 129 parent_->Close(); |
| 130 } |
| 131 |
| 132 void ManagePasswordsBubbleView::PendingView::OnPerformAction( |
| 133 views::Combobox* source) { |
| 134 DCHECK_EQ(source, refuse_combobox_); |
| 135 switch (refuse_combobox_->selected_index()) { |
| 136 case SavePasswordRefusalComboboxModel::INDEX_NOPE: |
| 137 parent_->model()->OnNopeClicked(); |
| 138 break; |
| 139 case SavePasswordRefusalComboboxModel::INDEX_NEVER_FOR_THIS_SITE: |
| 140 parent_->model()->OnNeverForThisSiteClicked(); |
| 141 break; |
| 142 } |
| 143 parent_->Close(); |
| 144 } |
| 145 |
| 146 // ManagePasswordsBubbleView::ManageView -------------------------------------- |
| 147 |
| 148 ManagePasswordsBubbleView::ManageView::ManageView( |
| 149 ManagePasswordsBubbleView* parent) |
| 150 : parent_(parent) { |
| 151 views::GridLayout* layout = new views::GridLayout(this); |
| 152 SetLayoutManager(layout); |
| 153 |
| 154 // Add the title. |
| 155 parent->BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET); |
| 156 parent->AddTitleRow(layout); |
| 157 |
| 158 // If we have a list of passwords to store for the current site, display |
| 159 // them to the user for management. Otherwise, render a "No passwords for |
| 160 // this site" message. |
| 161 if (!parent_->model()->best_matches().empty()) { |
| 162 for (autofill::PasswordFormMap::const_iterator i( |
| 163 parent_->model()->best_matches().begin()); |
| 164 i != parent_->model()->best_matches().end(); |
| 165 ++i) { |
| 166 ManagePasswordItemView* item = new ManagePasswordItemView( |
| 167 parent_->model(), |
| 168 *i->second, |
| 169 i == parent_->model()->best_matches().begin() |
| 170 ? ManagePasswordItemView::FIRST_ITEM |
| 171 : ManagePasswordItemView::SUBSEQUENT_ITEM); |
| 172 |
| 173 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); |
| 174 layout->AddView(item); |
| 175 } |
| 176 } else { |
| 177 views::Label* empty_label = new views::Label( |
| 178 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_NO_PASSWORDS)); |
| 179 empty_label->SetMultiLine(true); |
| 180 |
| 181 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); |
| 182 layout->AddView(empty_label); |
| 183 } |
| 184 |
| 185 // Then add the "manage passwords" link and "Done" button. |
| 186 manage_link_ = new views::Link(parent_->model()->manage_link()); |
| 187 manage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 188 manage_link_->SetUnderline(false); |
| 189 manage_link_->set_listener(this); |
| 190 |
| 191 done_button_ = |
| 192 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_DONE)); |
| 193 done_button_->SetStyle(views::Button::STYLE_BUTTON); |
| 194 |
| 195 parent->BuildColumnSet(layout, LINK_BUTTON_COLUMN_SET); |
| 196 layout->StartRowWithPadding( |
| 197 0, LINK_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); |
| 198 layout->AddView(manage_link_); |
| 199 layout->AddView(done_button_); |
| 200 |
| 201 // Extra padding for visual awesomeness. |
| 202 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 203 } |
| 204 |
| 205 ManagePasswordsBubbleView::ManageView::~ManageView() { |
| 206 } |
| 207 |
| 208 void ManagePasswordsBubbleView::ManageView::ButtonPressed( |
| 209 views::Button* sender, |
| 210 const ui::Event& event) { |
| 211 DCHECK(sender == done_button_); |
| 212 parent_->model()->OnDoneClicked(); |
| 213 parent_->Close(); |
| 214 } |
| 215 |
| 216 void ManagePasswordsBubbleView::ManageView::LinkClicked(views::Link* source, |
| 217 int event_flags) { |
| 218 DCHECK_EQ(source, manage_link_); |
| 219 parent_->model()->OnManageLinkClicked(); |
| 220 parent_->Close(); |
| 221 } |
| 222 |
95 // ManagePasswordsBubbleView -------------------------------------------------- | 223 // ManagePasswordsBubbleView -------------------------------------------------- |
96 | 224 |
97 // static | 225 // static |
98 ManagePasswordsBubbleView* ManagePasswordsBubbleView::manage_passwords_bubble_ = | 226 ManagePasswordsBubbleView* ManagePasswordsBubbleView::manage_passwords_bubble_ = |
99 NULL; | 227 NULL; |
100 | 228 |
101 // static | 229 // static |
102 void ManagePasswordsBubbleView::ShowBubble(content::WebContents* web_contents, | 230 void ManagePasswordsBubbleView::ShowBubble(content::WebContents* web_contents, |
103 DisplayReason reason) { | 231 DisplayReason reason) { |
104 Browser* browser = chrome::FindBrowserWithWebContents(web_contents); | 232 Browser* browser = chrome::FindBrowserWithWebContents(web_contents); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 views::GridLayout::CENTER, | 329 views::GridLayout::CENTER, |
202 0, | 330 0, |
203 views::GridLayout::USE_PREF, | 331 views::GridLayout::USE_PREF, |
204 0, | 332 0, |
205 0); | 333 0); |
206 break; | 334 break; |
207 } | 335 } |
208 column_set->AddPaddingColumn(0, views::kPanelHorizMargin); | 336 column_set->AddPaddingColumn(0, views::kPanelHorizMargin); |
209 } | 337 } |
210 | 338 |
| 339 void ManagePasswordsBubbleView::AddTitleRow(views::GridLayout* layout) const { |
| 340 // Build the title label, and populate it with whatever title our model feels |
| 341 // is appropriate for the bubble's state. |
| 342 views::Label* title_label = new views::Label(model()->title()); |
| 343 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 344 title_label->SetMultiLine(true); |
| 345 title_label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( |
| 346 ui::ResourceBundle::MediumFont)); |
| 347 |
| 348 // Add the title to the layout with appropriate padding. |
| 349 layout->StartRowWithPadding( |
| 350 0, SINGLE_VIEW_COLUMN_SET, 0, views::kRelatedControlSmallVerticalSpacing); |
| 351 layout->AddView(title_label); |
| 352 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); |
| 353 } |
| 354 |
211 void ManagePasswordsBubbleView::AdjustForFullscreen( | 355 void ManagePasswordsBubbleView::AdjustForFullscreen( |
212 const gfx::Rect& screen_bounds) { | 356 const gfx::Rect& screen_bounds) { |
213 if (GetAnchorView()) | 357 if (GetAnchorView()) |
214 return; | 358 return; |
215 | 359 |
216 // The bubble's padding from the screen edge, used in fullscreen. | 360 // The bubble's padding from the screen edge, used in fullscreen. |
217 const int kFullscreenPaddingEnd = 20; | 361 const int kFullscreenPaddingEnd = 20; |
218 const size_t bubble_half_width = width() / 2; | 362 const size_t bubble_half_width = width() / 2; |
219 const int x_pos = base::i18n::IsRTL() ? | 363 const int x_pos = base::i18n::IsRTL() ? |
220 screen_bounds.x() + bubble_half_width + kFullscreenPaddingEnd : | 364 screen_bounds.x() + bubble_half_width + kFullscreenPaddingEnd : |
221 screen_bounds.right() - bubble_half_width - kFullscreenPaddingEnd; | 365 screen_bounds.right() - bubble_half_width - kFullscreenPaddingEnd; |
222 SetAnchorRect(gfx::Rect(x_pos, screen_bounds.y(), 0, 0)); | 366 SetAnchorRect(gfx::Rect(x_pos, screen_bounds.y(), 0, 0)); |
223 } | 367 } |
224 | 368 |
225 void ManagePasswordsBubbleView::Close() { | 369 void ManagePasswordsBubbleView::Close() { |
226 GetWidget()->Close(); | 370 GetWidget()->Close(); |
227 } | 371 } |
228 | 372 |
229 void ManagePasswordsBubbleView::CloseWithoutLogging() { | 373 void ManagePasswordsBubbleView::CloseWithoutLogging() { |
230 model()->OnCloseWithoutLogging(); | 374 model()->OnCloseWithoutLogging(); |
231 GetWidget()->Close(); | 375 GetWidget()->Close(); |
232 } | 376 } |
233 | 377 |
234 void ManagePasswordsBubbleView::Init() { | 378 void ManagePasswordsBubbleView::Init() { |
235 using views::GridLayout; | 379 views::FillLayout* layout = new views::FillLayout(); |
| 380 SetLayoutManager(layout); |
| 381 SetFocusable(true); |
236 | 382 |
237 GridLayout* layout = new GridLayout(this); | 383 if (model()->WaitingToSavePassword()) |
238 SetFocusable(true); | 384 AddChildView(new PendingView(this)); |
239 SetLayoutManager(layout); | 385 else |
240 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET); | 386 AddChildView(new ManageView(this)); |
241 BuildColumnSet(layout, DOUBLE_BUTTON_COLUMN_SET); | |
242 BuildColumnSet(layout, LINK_BUTTON_COLUMN_SET); | |
243 | |
244 // This calculates the necessary widths for credential columns in the bubble. | |
245 const int first_field_width = std::max( | |
246 GetFieldWidth(USERNAME_FIELD), | |
247 views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED)) | |
248 .GetPreferredSize() | |
249 .width()); | |
250 | |
251 const int second_field_width = std::max( | |
252 GetFieldWidth(PASSWORD_FIELD), | |
253 views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_UNDO)) | |
254 .GetPreferredSize() | |
255 .width()); | |
256 | |
257 // Build and populate the header. | |
258 views::Label* title_label = new views::Label(model()->title()); | |
259 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
260 title_label->SetMultiLine(true); | |
261 title_label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( | |
262 ui::ResourceBundle::MediumFont)); | |
263 | |
264 layout->StartRowWithPadding( | |
265 0, SINGLE_VIEW_COLUMN_SET, 0, views::kRelatedControlSmallVerticalSpacing); | |
266 layout->AddView(title_label); | |
267 layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); | |
268 | |
269 if (model()->WaitingToSavePassword()) { | |
270 // If we've got a password that we're deciding whether or not to save, | |
271 // then we need to display a single-view columnset containing the | |
272 // ManagePasswordItemView, followed by double-view columnset containing | |
273 // a "Save" and "Reject" button. | |
274 ManagePasswordItemView* item = | |
275 new ManagePasswordItemView(model(), | |
276 model()->pending_credentials(), | |
277 first_field_width, | |
278 second_field_width, | |
279 ManagePasswordItemView::FIRST_ITEM); | |
280 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); | |
281 layout->AddView(item); | |
282 | |
283 refuse_combobox_ = | |
284 new views::Combobox(new SavePasswordRefusalComboboxModel()); | |
285 refuse_combobox_->set_listener(this); | |
286 refuse_combobox_->SetStyle(views::Combobox::STYLE_ACTION); | |
287 | |
288 save_button_ = new views::BlueButton( | |
289 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON)); | |
290 | |
291 layout->StartRowWithPadding( | |
292 0, DOUBLE_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); | |
293 layout->AddView(save_button_); | |
294 layout->AddView(refuse_combobox_); | |
295 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | |
296 } else { | |
297 // If we have a list of passwords to store for the current site, display | |
298 // them to the user for management. Otherwise, render a "No passwords for | |
299 // this site" message. | |
300 // | |
301 // TODO(mkwst): Do we really want the "No passwords" case? It would probably | |
302 // be better to only clear the pending password upon navigation, rather than | |
303 // as soon as the bubble closes. | |
304 if (!model()->best_matches().empty()) { | |
305 for (autofill::PasswordFormMap::const_iterator i( | |
306 model()->best_matches().begin()); | |
307 i != model()->best_matches().end(); | |
308 ++i) { | |
309 ManagePasswordItemView* item = new ManagePasswordItemView( | |
310 model(), | |
311 *i->second, | |
312 first_field_width, | |
313 second_field_width, | |
314 i == model()->best_matches().begin() | |
315 ? ManagePasswordItemView::FIRST_ITEM | |
316 : ManagePasswordItemView::SUBSEQUENT_ITEM); | |
317 | |
318 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); | |
319 layout->AddView(item); | |
320 } | |
321 } else { | |
322 views::Label* empty_label = new views::Label( | |
323 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_NO_PASSWORDS)); | |
324 empty_label->SetMultiLine(true); | |
325 | |
326 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); | |
327 layout->AddView(empty_label); | |
328 } | |
329 | |
330 // Build a "manage" link and "done" button, and throw them both into a new | |
331 // row | |
332 // containing a double-view columnset. | |
333 manage_link_ = new views::Link(model()->manage_link()); | |
334 manage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
335 manage_link_->SetUnderline(false); | |
336 manage_link_->set_listener(this); | |
337 | |
338 done_button_ = | |
339 new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_DONE)); | |
340 done_button_->SetStyle(views::Button::STYLE_BUTTON); | |
341 | |
342 layout->StartRowWithPadding( | |
343 0, LINK_BUTTON_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing); | |
344 layout->AddView(manage_link_); | |
345 layout->AddView(done_button_); | |
346 } | |
347 } | 387 } |
348 | 388 |
349 void ManagePasswordsBubbleView::WindowClosing() { | 389 void ManagePasswordsBubbleView::WindowClosing() { |
350 // Close() closes the window asynchronously, so by the time we reach here, | 390 // Close() closes the window asynchronously, so by the time we reach here, |
351 // |manage_passwords_bubble_| may have already been reset. | 391 // |manage_passwords_bubble_| may have already been reset. |
352 if (manage_passwords_bubble_ == this) | 392 if (manage_passwords_bubble_ == this) |
353 manage_passwords_bubble_ = NULL; | 393 manage_passwords_bubble_ = NULL; |
354 } | 394 } |
355 | |
356 void ManagePasswordsBubbleView::ButtonPressed(views::Button* sender, | |
357 const ui::Event& event) { | |
358 DCHECK(sender == save_button_ || sender == done_button_); | |
359 | |
360 if (sender == save_button_) | |
361 model()->OnSaveClicked(); | |
362 else | |
363 model()->OnDoneClicked(); | |
364 Close(); | |
365 } | |
366 | |
367 void ManagePasswordsBubbleView::LinkClicked(views::Link* source, | |
368 int event_flags) { | |
369 DCHECK_EQ(source, manage_link_); | |
370 model()->OnManageLinkClicked(); | |
371 Close(); | |
372 } | |
373 | |
374 void ManagePasswordsBubbleView::OnPerformAction(views::Combobox* source) { | |
375 DCHECK_EQ(source, refuse_combobox_); | |
376 switch (refuse_combobox_->selected_index()) { | |
377 case SavePasswordRefusalComboboxModel::INDEX_NOPE: | |
378 model()->OnNopeClicked(); | |
379 break; | |
380 case SavePasswordRefusalComboboxModel::INDEX_NEVER_FOR_THIS_SITE: | |
381 model()->OnNeverForThisSiteClicked(); | |
382 break; | |
383 default: | |
384 NOTREACHED(); | |
385 break; | |
386 } | |
387 Close(); | |
388 } | |
OLD | NEW |