Chromium Code Reviews| 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/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/metrics/user_metrics.h" | 8 #include "base/metrics/user_metrics.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 10 #include "base/timer/timer.h" | 10 #include "base/timer/timer.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 // Helpers -------------------------------------------------------------------- | 57 // Helpers -------------------------------------------------------------------- |
| 58 | 58 |
| 59 namespace { | 59 namespace { |
| 60 | 60 |
| 61 enum ColumnSetType { | 61 enum ColumnSetType { |
| 62 // | | (FILL, FILL) | | | 62 // | | (FILL, FILL) | | |
| 63 // Used for the bubble's header, the credentials list, and for simple | 63 // Used for the bubble's header, the credentials list, and for simple |
| 64 // messages like "No passwords". | 64 // messages like "No passwords". |
| 65 SINGLE_VIEW_COLUMN_SET, | 65 SINGLE_VIEW_COLUMN_SET, |
| 66 | 66 |
| 67 // | | (FILL, FILL) | | (FILL, FILL) | | | |
| 68 // Used for the credentials line of the bubble, for the pending view. | |
| 69 DOUBLE_VIEW_COLUMN_SET, | |
| 70 | |
| 67 // | | (TRAILING, CENTER) | | (TRAILING, CENTER) | | | 71 // | | (TRAILING, CENTER) | | (TRAILING, CENTER) | | |
| 68 // Used for buttons at the bottom of the bubble which should nest at the | 72 // Used for buttons at the bottom of the bubble which should nest at the |
| 69 // bottom-right corner. | 73 // bottom-right corner. |
| 70 DOUBLE_BUTTON_COLUMN_SET, | 74 DOUBLE_BUTTON_COLUMN_SET, |
| 71 | 75 |
| 72 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | | | 76 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | | |
| 73 // Used for buttons at the bottom of the bubble which should occupy | 77 // Used for buttons at the bottom of the bubble which should occupy |
| 74 // the corners. | 78 // the corners. |
| 75 LINK_BUTTON_COLUMN_SET, | 79 LINK_BUTTON_COLUMN_SET, |
| 76 | 80 |
| 77 // | | (TRAILING, CENTER) | | | 81 // | | (TRAILING, CENTER) | | |
| 78 // Used when there is only one button which should next at the bottom-right | 82 // Used when there is only one button which should next at the bottom-right |
| 79 // corner. | 83 // corner. |
| 80 SINGLE_BUTTON_COLUMN_SET, | 84 SINGLE_BUTTON_COLUMN_SET, |
| 81 | 85 |
| 82 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | | (TRAILING, CENTER) | | | 86 // | | (LEADING, CENTER) | | (TRAILING, CENTER) | | (TRAILING, CENTER) | | |
| 83 // Used when there are three buttons. | 87 // Used when there are three buttons. |
| 84 TRIPLE_BUTTON_COLUMN_SET, | 88 TRIPLE_BUTTON_COLUMN_SET, |
| 85 }; | 89 }; |
| 86 | 90 |
| 87 enum TextRowType { ROW_SINGLE, ROW_MULTILINE }; | 91 enum TextRowType { ROW_SINGLE, ROW_MULTILINE }; |
| 88 | 92 |
| 89 // Construct an appropriate ColumnSet for the given |type|, and add it | 93 // Construct an appropriate ColumnSet for the given |type|, and add it |
| 90 // to |layout|. | 94 // to |layout|. |
| 91 void BuildColumnSet(views::GridLayout* layout, ColumnSetType type) { | 95 void BuildColumnSet(views::GridLayout* layout, ColumnSetType type) { |
| 92 views::ColumnSet* column_set = layout->AddColumnSet(type); | 96 views::ColumnSet* column_set = layout->AddColumnSet(type); |
| 93 int full_width = ManagePasswordsBubbleView::kDesiredBubbleWidth; | 97 int full_width = ManagePasswordsBubbleView::kDesiredBubbleWidth; |
| 94 const int button_divider = ChromeLayoutProvider::Get()->GetDistanceMetric( | 98 const int button_divider = ChromeLayoutProvider::Get()->GetDistanceMetric( |
| 95 views::DISTANCE_RELATED_BUTTON_HORIZONTAL); | 99 views::DISTANCE_RELATED_BUTTON_HORIZONTAL); |
| 100 const int column_divider = ChromeLayoutProvider::Get()->GetDistanceMetric( | |
| 101 views::DISTANCE_RELATED_CONTROL_HORIZONTAL); | |
| 96 switch (type) { | 102 switch (type) { |
| 97 case SINGLE_VIEW_COLUMN_SET: | 103 case SINGLE_VIEW_COLUMN_SET: |
| 98 column_set->AddColumn(views::GridLayout::FILL, | 104 column_set->AddColumn(views::GridLayout::FILL, |
| 99 views::GridLayout::FILL, | 105 views::GridLayout::FILL, |
| 100 0, | 106 0, |
| 101 views::GridLayout::FIXED, | 107 views::GridLayout::FIXED, |
| 102 full_width, | 108 full_width, |
| 103 0); | 109 0); |
| 104 break; | 110 break; |
| 111 case DOUBLE_VIEW_COLUMN_SET: | |
| 112 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, | |
| 113 views::GridLayout::USE_PREF, 0, 0); | |
| 114 column_set->AddPaddingColumn(0, column_divider); | |
| 115 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, | |
| 116 views::GridLayout::USE_PREF, 0, 0); | |
| 117 break; | |
| 105 case DOUBLE_BUTTON_COLUMN_SET: | 118 case DOUBLE_BUTTON_COLUMN_SET: |
| 106 column_set->AddColumn(views::GridLayout::TRAILING, | 119 column_set->AddColumn(views::GridLayout::TRAILING, |
| 107 views::GridLayout::CENTER, | 120 views::GridLayout::CENTER, |
| 108 1, | 121 1, |
| 109 views::GridLayout::USE_PREF, | 122 views::GridLayout::USE_PREF, |
| 110 0, | 123 0, |
| 111 0); | 124 0); |
| 112 column_set->AddPaddingColumn(0, button_divider); | 125 column_set->AddPaddingColumn(0, button_divider); |
| 113 column_set->AddColumn(views::GridLayout::TRAILING, | 126 column_set->AddColumn(views::GridLayout::TRAILING, |
| 114 views::GridLayout::CENTER, | 127 views::GridLayout::CENTER, |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 void ManagePasswordsBubbleView::AutoSigninView::OnTimer() { | 275 void ManagePasswordsBubbleView::AutoSigninView::OnTimer() { |
| 263 parent_->model()->OnAutoSignInToastTimeout(); | 276 parent_->model()->OnAutoSignInToastTimeout(); |
| 264 parent_->CloseBubble(); | 277 parent_->CloseBubble(); |
| 265 } | 278 } |
| 266 | 279 |
| 267 // ManagePasswordsBubbleView::PendingView ------------------------------------- | 280 // ManagePasswordsBubbleView::PendingView ------------------------------------- |
| 268 | 281 |
| 269 // A view offering the user the ability to save credentials. Contains a | 282 // A view offering the user the ability to save credentials. Contains a |
| 270 // single ManagePasswordItemsView, along with a "Save Passwords" button, | 283 // single ManagePasswordItemsView, along with a "Save Passwords" button, |
| 271 // a "Never" button and an "Edit" button to edit username field. | 284 // a "Never" button and an "Edit" button to edit username field. |
| 272 class ManagePasswordsBubbleView::PendingView : public views::View, | 285 class ManagePasswordsBubbleView::PendingView |
| 273 public views::ButtonListener { | 286 : public views::View, |
| 287 public views::ButtonListener, | |
| 288 public views::FocusChangeListener { | |
| 274 public: | 289 public: |
| 275 explicit PendingView(ManagePasswordsBubbleView* parent); | 290 explicit PendingView(ManagePasswordsBubbleView* parent); |
| 276 ~PendingView() override; | 291 ~PendingView() override; |
| 277 | 292 |
| 278 private: | 293 private: |
| 294 void CreateAndSetLayout(); | |
| 279 // views::ButtonListener: | 295 // views::ButtonListener: |
| 280 void ButtonPressed(views::Button* sender, const ui::Event& event) override; | 296 void ButtonPressed(views::Button* sender, const ui::Event& event) override; |
| 297 // views::FocusChangeListener: | |
| 298 void OnWillChangeFocus(View* focused_before, View* focused_now) override; | |
| 299 void OnDidChangeFocus(View* focused_before, View* focused_now) override; | |
| 300 // views::View: | |
| 301 bool OnKeyPressed(const ui::KeyEvent& event) override; | |
| 302 | |
| 303 void UpdateUsernameField(); | |
|
vasilii
2017/07/06 13:46:43
Call it "ToggleEditingState" or something
irmakk
2017/07/06 14:19:12
Done.
| |
| 281 | 304 |
| 282 ManagePasswordsBubbleView* parent_; | 305 ManagePasswordsBubbleView* parent_; |
| 283 | 306 |
| 284 views::Button* edit_button_; | 307 views::Button* edit_button_; |
| 285 views::Button* save_button_; | 308 views::Button* save_button_; |
| 286 views::Button* never_button_; | 309 views::Button* never_button_; |
| 310 views::View* username_field_; | |
| 311 views::View* password_field_; | |
| 312 | |
| 313 bool editing_; | |
| 287 | 314 |
| 288 DISALLOW_COPY_AND_ASSIGN(PendingView); | 315 DISALLOW_COPY_AND_ASSIGN(PendingView); |
| 289 }; | 316 }; |
| 290 | 317 |
| 291 ManagePasswordsBubbleView::PendingView::PendingView( | 318 ManagePasswordsBubbleView::PendingView::PendingView( |
| 292 ManagePasswordsBubbleView* parent) | 319 ManagePasswordsBubbleView* parent) |
| 293 : parent_(parent), edit_button_(nullptr) { | 320 : parent_(parent), |
| 321 edit_button_(nullptr), | |
| 322 save_button_(nullptr), | |
| 323 never_button_(nullptr), | |
| 324 username_field_(nullptr), | |
| 325 password_field_(nullptr), | |
| 326 editing_(false) { | |
| 327 CreateAndSetLayout(); | |
| 328 parent_->set_initially_focused_view(save_button_); | |
| 329 } | |
| 330 | |
| 331 void ManagePasswordsBubbleView::PendingView::CreateAndSetLayout() { | |
| 294 views::GridLayout* layout = new views::GridLayout(this); | 332 views::GridLayout* layout = new views::GridLayout(this); |
| 295 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0)); | 333 layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0)); |
| 296 SetLayoutManager(layout); | 334 SetLayoutManager(layout); |
| 297 | 335 |
| 298 // Create the pending credential item, save button and refusal combobox. | 336 // Create the edit, save and never buttons. |
| 299 ManagePasswordItemsView* item = nullptr; | 337 if (!edit_button_ && |
| 300 if (!parent->model()->pending_password().username_value.empty()) { | 338 base::FeatureList::IsEnabled( |
| 301 item = new ManagePasswordItemsView(parent_->model(), | |
| 302 &parent->model()->pending_password()); | |
| 303 } | |
| 304 if (base::FeatureList::IsEnabled( | |
| 305 password_manager::features::kEnableUsernameCorrection)) { | 339 password_manager::features::kEnableUsernameCorrection)) { |
| 306 edit_button_ = views::MdTextButton::CreateSecondaryUiButton( | 340 edit_button_ = views::MdTextButton::CreateSecondaryUiButton( |
| 307 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EDIT_BUTTON)); | 341 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EDIT_BUTTON)); |
| 308 } | 342 } |
| 309 save_button_ = views::MdTextButton::CreateSecondaryUiBlueButton( | 343 if (!save_button_) { |
| 310 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON)); | 344 save_button_ = views::MdTextButton::CreateSecondaryUiBlueButton( |
| 311 never_button_ = views::MdTextButton::CreateSecondaryUiButton( | 345 this, l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON)); |
| 312 this, | 346 } |
| 313 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BUBBLE_BLACKLIST_BUTTON)); | 347 if (!never_button_) { |
| 348 never_button_ = views::MdTextButton::CreateSecondaryUiButton( | |
| 349 this, l10n_util::GetStringUTF16( | |
| 350 IDS_PASSWORD_MANAGER_BUBBLE_BLACKLIST_BUTTON)); | |
| 351 } | |
| 314 | 352 |
| 315 BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET); | 353 // Credentials row. |
| 316 | 354 BuildColumnSet(layout, DOUBLE_VIEW_COLUMN_SET); |
| 317 // Credential row. | 355 if (!parent_->model()->pending_password().username_value.empty() || |
| 318 if (item) { | 356 edit_button_) { |
| 319 layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); | 357 layout->StartRow(0, DOUBLE_VIEW_COLUMN_SET); |
| 320 layout->AddView(item); | 358 const autofill::PasswordForm* password_form = |
| 359 &parent_->model()->pending_password(); | |
| 360 DCHECK_EQ(username_field_, nullptr); | |
|
vasilii
2017/07/06 13:46:43
DCHECK_EQ(nullptr, username_field_) or DCHECK(!use
irmakk
2017/07/06 14:19:12
Done.
| |
| 361 if (editing_) { | |
| 362 username_field_ = GenerateUsernameEditable(*password_form).release(); | |
| 363 } else { | |
| 364 username_field_ = GenerateUsernameLabel(*password_form).release(); | |
| 365 } | |
| 366 if (!password_field_) { | |
| 367 password_field_ = GeneratePasswordLabel(*password_form).release(); | |
| 368 } | |
| 369 layout->AddView(username_field_); | |
| 370 layout->AddView(password_field_); | |
| 321 layout->AddPaddingRow(0, | 371 layout->AddPaddingRow(0, |
| 322 ChromeLayoutProvider::Get() | 372 ChromeLayoutProvider::Get() |
| 323 ->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS) | 373 ->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS) |
| 324 .bottom()); | 374 .bottom()); |
| 325 } | 375 } |
| 326 | |
| 327 // Button row. | 376 // Button row. |
| 328 ColumnSetType column_set_type = | 377 ColumnSetType column_set_type = |
| 329 edit_button_ ? TRIPLE_BUTTON_COLUMN_SET : DOUBLE_BUTTON_COLUMN_SET; | 378 edit_button_ ? TRIPLE_BUTTON_COLUMN_SET : DOUBLE_BUTTON_COLUMN_SET; |
| 330 BuildColumnSet(layout, column_set_type); | 379 BuildColumnSet(layout, column_set_type); |
| 331 layout->StartRow(0, column_set_type); | 380 layout->StartRow(0, column_set_type); |
| 332 if (column_set_type == TRIPLE_BUTTON_COLUMN_SET) { | 381 if (column_set_type == TRIPLE_BUTTON_COLUMN_SET) { |
| 333 layout->AddView(edit_button_); | 382 layout->AddView(edit_button_); |
| 334 } | 383 } |
| 335 layout->AddView(save_button_); | 384 layout->AddView(save_button_); |
| 336 layout->AddView(never_button_); | 385 layout->AddView(never_button_); |
| 337 | |
| 338 parent_->set_initially_focused_view(save_button_); | |
| 339 } | 386 } |
| 340 | 387 |
| 341 ManagePasswordsBubbleView::PendingView::~PendingView() { | 388 ManagePasswordsBubbleView::PendingView::~PendingView() { |
| 342 } | 389 } |
| 343 | 390 |
| 344 void ManagePasswordsBubbleView::PendingView::ButtonPressed( | 391 void ManagePasswordsBubbleView::PendingView::ButtonPressed( |
| 345 views::Button* sender, | 392 views::Button* sender, |
| 346 const ui::Event& event) { | 393 const ui::Event& event) { |
| 347 // TODO(https://crbug.com/734965): Implement edit button logic. | 394 // TODO(https://crbug.com/734965): Implement edit button logic. |
| 348 if (sender == edit_button_) { | 395 if (sender == edit_button_) { |
| 396 UpdateUsernameField(); | |
| 349 return; | 397 return; |
| 350 } else if (sender == save_button_) { | 398 } |
| 399 if (sender == save_button_) { | |
| 351 parent_->model()->OnSaveClicked(); | 400 parent_->model()->OnSaveClicked(); |
| 352 if (parent_->model()->ReplaceToShowPromotionIfNeeded()) { | 401 if (parent_->model()->ReplaceToShowPromotionIfNeeded()) { |
| 353 parent_->Refresh(); | 402 parent_->Refresh(); |
| 354 return; | 403 return; |
| 355 } | 404 } |
| 356 } else if (sender == never_button_) { | 405 } else if (sender == never_button_) { |
| 357 parent_->model()->OnNeverForThisSiteClicked(); | 406 parent_->model()->OnNeverForThisSiteClicked(); |
| 358 } else { | 407 } else { |
| 359 NOTREACHED(); | 408 NOTREACHED(); |
| 360 } | 409 } |
| 361 | 410 |
| 362 parent_->CloseBubble(); | 411 parent_->CloseBubble(); |
| 363 } | 412 } |
| 364 | 413 |
| 414 void ManagePasswordsBubbleView::PendingView::OnWillChangeFocus( | |
| 415 View* focused_before, | |
| 416 View* focused_now) { | |
| 417 // Nothing to do here. | |
| 418 } | |
| 419 | |
| 420 void ManagePasswordsBubbleView::PendingView::OnDidChangeFocus( | |
| 421 View* focused_before, | |
| 422 View* focused_now) { | |
| 423 if (editing_ && focused_before == username_field_) { | |
| 424 UpdateUsernameField(); | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 bool ManagePasswordsBubbleView::PendingView::OnKeyPressed( | |
| 429 const ui::KeyEvent& event) { | |
| 430 if (editing_ && (event.key_code() == ui::KeyboardCode::VKEY_RETURN || | |
| 431 event.key_code() == ui::KeyboardCode::VKEY_ESCAPE)) { | |
| 432 UpdateUsernameField(); | |
| 433 return true; | |
| 434 } | |
| 435 return false; | |
| 436 } | |
| 437 | |
| 438 void ManagePasswordsBubbleView::PendingView::UpdateUsernameField() { | |
| 439 editing_ = !editing_; | |
| 440 edit_button_->SetEnabled(!editing_); | |
| 441 RemoveChildView(username_field_); | |
| 442 username_field_ = nullptr; | |
| 443 CreateAndSetLayout(); | |
| 444 Layout(); | |
| 445 if (editing_) { | |
| 446 GetFocusManager()->SetFocusedView(username_field_); | |
| 447 GetFocusManager()->AddFocusChangeListener(this); | |
| 448 } else { | |
| 449 GetFocusManager()->SetFocusedView(save_button_); | |
| 450 GetFocusManager()->RemoveFocusChangeListener(this); | |
|
vasilii
2017/07/06 13:46:43
I'd swap these lines to avoid unnecessary notifica
irmakk
2017/07/06 14:19:12
Done.
| |
| 451 } | |
| 452 parent_->SizeToContents(); | |
| 453 } | |
| 454 | |
| 365 // ManagePasswordsBubbleView::ManageView -------------------------------------- | 455 // ManagePasswordsBubbleView::ManageView -------------------------------------- |
| 366 | 456 |
| 367 // A view offering the user a list of their currently saved credentials | 457 // A view offering the user a list of their currently saved credentials |
| 368 // for the current page, along with a "Manage passwords" link and a | 458 // for the current page, along with a "Manage passwords" link and a |
| 369 // "Done" button. | 459 // "Done" button. |
| 370 class ManagePasswordsBubbleView::ManageView : public views::View, | 460 class ManagePasswordsBubbleView::ManageView : public views::View, |
| 371 public views::ButtonListener, | 461 public views::ButtonListener, |
| 372 public views::LinkListener { | 462 public views::LinkListener { |
| 373 public: | 463 public: |
| 374 explicit ManageView(ManagePasswordsBubbleView* parent); | 464 explicit ManageView(ManagePasswordsBubbleView* parent); |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 879 } else if (model_.state() == | 969 } else if (model_.state() == |
| 880 password_manager::ui::CHROME_DESKTOP_IOS_PROMO_STATE) { | 970 password_manager::ui::CHROME_DESKTOP_IOS_PROMO_STATE) { |
| 881 AddChildView(new DesktopIOSPromotionBubbleView( | 971 AddChildView(new DesktopIOSPromotionBubbleView( |
| 882 model_.GetProfile(), | 972 model_.GetProfile(), |
| 883 desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE)); | 973 desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE)); |
| 884 #endif | 974 #endif |
| 885 } else { | 975 } else { |
| 886 AddChildView(new ManageView(this)); | 976 AddChildView(new ManageView(this)); |
| 887 } | 977 } |
| 888 } | 978 } |
| OLD | NEW |