Commit b7970f8e authored by vasilii's avatar vasilii Committed by Commit bot

New "Save password" bubble for the Credential Manager API.

The new bubble replaces the old one in case the Credential Manager API is activated in chrome://flags.

BUG=400674

Review URL: https://codereview.chromium.org/1001553005

Cr-Commit-Position: refs/heads/master@{#321549}
parent 685eb7e3
...@@ -7707,6 +7707,9 @@ Keep your key file in a safe place. You will need it to create new versions of y ...@@ -7707,6 +7707,9 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Save button text for password manager"> <message name="IDS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Save button text for password manager">
Save password Save password
</message> </message>
<message name="IDS_PASSWORD_MANAGER_SAVE_ACCOUNT_BUTTON" desc="Save button text for password manager">
Save
</message>
<message name="IDS_PASSWORD_MANAGER_UNBLACKLIST_BUTTON" desc="Buton text to re-enable the password manager after blacklisting."> <message name="IDS_PASSWORD_MANAGER_UNBLACKLIST_BUTTON" desc="Buton text to re-enable the password manager after blacklisting.">
Undo Undo
</message> </message>
...@@ -7722,6 +7725,12 @@ Keep your key file in a safe place. You will need it to create new versions of y ...@@ -7722,6 +7725,12 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE" desc="Text for the 'Manage Passwords' icon's 'saving passwords' state"> <message name="IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE" desc="Text for the 'Manage Passwords' icon's 'saving passwords' state">
Manage your passwords Manage your passwords
</message> </message>
<message name="IDS_PASSWORD_MANAGER_MORE_BUTTON" desc="Text for the 'More' drop down button in the 'Save password' dialog">
More
</message>
<message name="IDS_PASSWORD_MANAGER_SETTINGS_LINK" desc="Text for the link to chrome://settings/passwords in the 'Save password' dialog">
Settings
</message>
</if> </if>
<if expr="is_android"> <if expr="is_android">
<message name="IDS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Mobile: Button text for the 'Save Password' infobar's 'Remember password' option"> <message name="IDS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Mobile: Button text for the 'Save Password' infobar's 'Remember password' option">
......
...@@ -57,13 +57,6 @@ void RecordExperimentStatistics(content::WebContents* web_contents, ...@@ -57,13 +57,6 @@ void RecordExperimentStatistics(content::WebContents* web_contents,
password_bubble_experiment::RecordBubbleClosed(profile->GetPrefs(), reason); password_bubble_experiment::RecordBubbleClosed(profile->GetPrefs(), reason);
} }
base::string16 PendingStateTitleBasedOnSavePasswordPref(
bool never_save_passwords) {
return l10n_util::GetStringUTF16(
never_save_passwords ? IDS_MANAGE_PASSWORDS_BLACKLIST_CONFIRMATION_TITLE
: IDS_SAVE_PASSWORD);
}
ScopedVector<const autofill::PasswordForm> DeepCopyForms( ScopedVector<const autofill::PasswordForm> DeepCopyForms(
const std::vector<const autofill::PasswordForm*>& forms) { const std::vector<const autofill::PasswordForm*>& forms) {
ScopedVector<const autofill::PasswordForm> result; ScopedVector<const autofill::PasswordForm> result;
...@@ -103,7 +96,7 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel( ...@@ -103,7 +96,7 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
} }
if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) { if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) {
title_ = PendingStateTitleBasedOnSavePasswordPref(never_save_passwords_); title_ = PendingStateTitleBasedOnSavePasswordPref();
} else if (state_ == password_manager::ui::BLACKLIST_STATE) { } else if (state_ == password_manager::ui::BLACKLIST_STATE) {
title_ = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_BLACKLISTED_TITLE); title_ = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_BLACKLISTED_TITLE);
} else if (state_ == password_manager::ui::CONFIRMATION_STATE) { } else if (state_ == password_manager::ui::CONFIRMATION_STATE) {
...@@ -197,12 +190,12 @@ void ManagePasswordsBubbleModel::OnNopeClicked() { ...@@ -197,12 +190,12 @@ void ManagePasswordsBubbleModel::OnNopeClicked() {
void ManagePasswordsBubbleModel::OnConfirmationForNeverForThisSite() { void ManagePasswordsBubbleModel::OnConfirmationForNeverForThisSite() {
never_save_passwords_ = true; never_save_passwords_ = true;
title_ = PendingStateTitleBasedOnSavePasswordPref(never_save_passwords_); title_ = PendingStateTitleBasedOnSavePasswordPref();
} }
void ManagePasswordsBubbleModel::OnUndoNeverForThisSite() { void ManagePasswordsBubbleModel::OnUndoNeverForThisSite() {
never_save_passwords_ = false; never_save_passwords_ = false;
title_ = PendingStateTitleBasedOnSavePasswordPref(never_save_passwords_); title_ = PendingStateTitleBasedOnSavePasswordPref();
} }
void ManagePasswordsBubbleModel::OnNeverForThisSiteClicked() { void ManagePasswordsBubbleModel::OnNeverForThisSiteClicked() {
...@@ -306,3 +299,15 @@ int ManagePasswordsBubbleModel::UsernameFieldWidth() { ...@@ -306,3 +299,15 @@ int ManagePasswordsBubbleModel::UsernameFieldWidth() {
int ManagePasswordsBubbleModel::PasswordFieldWidth() { int ManagePasswordsBubbleModel::PasswordFieldWidth() {
return GetFieldWidth(PASSWORD_FIELD); return GetFieldWidth(PASSWORD_FIELD);
} }
base::string16
ManagePasswordsBubbleModel::PendingStateTitleBasedOnSavePasswordPref() const {
int message_id = 0;
if (never_save_passwords_)
message_id = IDS_MANAGE_PASSWORDS_BLACKLIST_CONFIRMATION_TITLE;
else if (IsNewUIActive())
message_id = IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SMART_LOCK_PROMPT;
else
message_id = IDS_SAVE_PASSWORD;
return l10n_util::GetStringUTF16(message_id);
}
...@@ -146,6 +146,8 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver { ...@@ -146,6 +146,8 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver {
static int PasswordFieldWidth(); static int PasswordFieldWidth();
private: private:
// Returns the title for the PENDING_PASSWORD_STATE.
base::string16 PendingStateTitleBasedOnSavePasswordPref() const;
// URL of the page from where this bubble was triggered. // URL of the page from where this bubble was triggered.
GURL origin_; GURL origin_;
password_manager::ui::State state_; password_manager::ui::State state_;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "chrome/browser/ui/views/passwords/manage_credential_item_view.h" #include "chrome/browser/ui/views/passwords/manage_credential_item_view.h"
#include "chrome/browser/ui/views/passwords/manage_password_items_view.h" #include "chrome/browser/ui/views/passwords/manage_password_items_view.h"
#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h" #include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h"
#include "chrome/browser/ui/views/passwords/save_account_more_combobox_model.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -48,22 +49,26 @@ enum ColumnSetType { ...@@ -48,22 +49,26 @@ enum ColumnSetType {
// | | (FILL, FILL) | | // | | (FILL, FILL) | |
// Used for the bubble's header, the credentials list, and for simple // Used for the bubble's header, the credentials list, and for simple
// messages like "No passwords". // messages like "No passwords".
SINGLE_VIEW_COLUMN_SET = 0, SINGLE_VIEW_COLUMN_SET,
// | | (TRAILING, CENTER) | | (TRAILING, CENTER) | | // | | (TRAILING, CENTER) | | (TRAILING, CENTER) | |
// Used for buttons at the bottom of the bubble which should nest at the // Used for buttons at the bottom of the bubble which should nest at the
// bottom-right corner. // bottom-right corner.
DOUBLE_BUTTON_COLUMN_SET = 1, DOUBLE_BUTTON_COLUMN_SET,
// | | (LEADING, CENTER) | | (TRAILING, CENTER) | | // | | (LEADING, CENTER) | | (TRAILING, CENTER) | |
// Used for buttons at the bottom of the bubble which should occupy // Used for buttons at the bottom of the bubble which should occupy
// the corners. // the corners.
LINK_BUTTON_COLUMN_SET = 2, LINK_BUTTON_COLUMN_SET,
// | | (TRAILING, CENTER) | | // | | (TRAILING, CENTER) | |
// Used when there is only one button which should next at the bottom-right // Used when there is only one button which should next at the bottom-right
// corner. // corner.
SINGLE_BUTTON_COLUMN_SET = 3, SINGLE_BUTTON_COLUMN_SET,
// | | (LEADING, CENTER) | | (TRAILING, CENTER) | | (TRAILING, CENTER) | |
// Used when there are three buttons.
TRIPLE_BUTTON_COLUMN_SET,
}; };
enum TextRowType { ROW_SINGLE, ROW_MULTILINE }; enum TextRowType { ROW_SINGLE, ROW_MULTILINE };
...@@ -121,6 +126,28 @@ void BuildColumnSet(views::GridLayout* layout, ColumnSetType type) { ...@@ -121,6 +126,28 @@ void BuildColumnSet(views::GridLayout* layout, ColumnSetType type) {
views::GridLayout::USE_PREF, views::GridLayout::USE_PREF,
0, 0,
0); 0);
case TRIPLE_BUTTON_COLUMN_SET:
column_set->AddColumn(views::GridLayout::LEADING,
views::GridLayout::CENTER,
1,
views::GridLayout::USE_PREF,
0,
0);
column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
column_set->AddColumn(views::GridLayout::TRAILING,
views::GridLayout::CENTER,
0,
views::GridLayout::USE_PREF,
0,
0);
column_set->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
column_set->AddColumn(views::GridLayout::TRAILING,
views::GridLayout::CENTER,
0,
views::GridLayout::USE_PREF,
0,
0);
break;
} }
column_set->AddPaddingColumn(0, views::kPanelHorizMargin); column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
} }
...@@ -387,7 +414,108 @@ void ManagePasswordsBubbleView::PendingView::OnPerformAction( ...@@ -387,7 +414,108 @@ void ManagePasswordsBubbleView::PendingView::OnPerformAction(
} }
} }
// ManagePasswordsBubbleView::ConfirmNeverView --------------------------------- // ManagePasswordsBubbleView::SaveAccountView ---------------------------------
// A view offering the user the ability to save credentials. Contains 2 buttons
// and a "More" combobox.
class ManagePasswordsBubbleView::SaveAccountView
: public views::View,
public views::ButtonListener,
public views::ComboboxListener {
public:
explicit SaveAccountView(ManagePasswordsBubbleView* parent);
private:
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// Handles the event when the user changes an index of a combobox.
void OnPerformAction(views::Combobox* source) override;
ManagePasswordsBubbleView* parent_;
views::BlueButton* save_button_;
views::LabelButton* no_button_;
// The combobox doesn't take ownership of its model. If we created a
// combobox we need to ensure that we delete the model here, and because the
// combobox uses the model in it's destructor, we need to make sure we
// delete the model _after_ the combobox itself is deleted.
SaveAccountMoreComboboxModel combobox_model_;
scoped_ptr<views::Combobox> more_combobox_;
};
ManagePasswordsBubbleView::SaveAccountView::SaveAccountView(
ManagePasswordsBubbleView* parent)
: parent_(parent) {
DCHECK(parent_->model()->IsNewUIActive());
views::GridLayout* layout = new views::GridLayout(this);
layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0));
SetLayoutManager(layout);
save_button_ = new views::BlueButton(
this,
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_ACCOUNT_BUTTON));
save_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
ui::ResourceBundle::SmallFont));
no_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SMART_LOCK_NO_THANKS_BUTTON));
no_button_->SetStyle(views::Button::STYLE_BUTTON);
no_button_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
ui::ResourceBundle::SmallFont));
more_combobox_.reset(new views::Combobox(&combobox_model_));
more_combobox_->set_owned_by_client();
more_combobox_->set_listener(this);
more_combobox_->SetStyle(views::Combobox::STYLE_ACTION);
// Title row.
BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET);
AddTitleRow(layout, parent_->model());
// Button row.
BuildColumnSet(layout, TRIPLE_BUTTON_COLUMN_SET);
layout->StartRow(0, TRIPLE_BUTTON_COLUMN_SET);
layout->AddView(more_combobox_.get());
layout->AddView(save_button_);
layout->AddView(no_button_);
// Extra padding for visual awesomeness.
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
parent_->set_initially_focused_view(save_button_);
}
void ManagePasswordsBubbleView::SaveAccountView::ButtonPressed(
views::Button* sender,
const ui::Event& event) {
if (sender == save_button_)
parent_->model()->OnSaveClicked();
else if (sender == no_button_)
parent_->model()->OnNopeClicked();
else
NOTREACHED();
parent_->Close();
}
void ManagePasswordsBubbleView::SaveAccountView::OnPerformAction(
views::Combobox* source) {
DCHECK_EQ(source, more_combobox_);
switch (more_combobox_->selected_index()) {
case SaveAccountMoreComboboxModel::INDEX_MORE:
break;
case SaveAccountMoreComboboxModel::INDEX_NEVER_FOR_THIS_SITE:
parent_->NotifyNeverForThisSiteClicked();
break;
case SaveAccountMoreComboboxModel::INDEX_SETTINGS:
parent_->model()->OnManageLinkClicked();
parent_->Close();
break;
}
}
// ManagePasswordsBubbleView::ConfirmNeverView --------------------------------
// A view offering the user the ability to undo her decision to never save // A view offering the user the ability to undo her decision to never save
// passwords for a particular site. // passwords for a particular site.
...@@ -982,10 +1110,14 @@ void ManagePasswordsBubbleView::Refresh() { ...@@ -982,10 +1110,14 @@ void ManagePasswordsBubbleView::Refresh() {
RemoveAllChildViews(true); RemoveAllChildViews(true);
initially_focused_view_ = NULL; initially_focused_view_ = NULL;
if (model()->state() == password_manager::ui::PENDING_PASSWORD_STATE) { if (model()->state() == password_manager::ui::PENDING_PASSWORD_STATE) {
if (model()->never_save_passwords()) if (model()->never_save_passwords()) {
AddChildView(new ConfirmNeverView(this)); AddChildView(new ConfirmNeverView(this));
else } else {
AddChildView(new PendingView(this)); if (model()->IsNewUIActive())
AddChildView(new SaveAccountView(this));
else
AddChildView(new PendingView(this));
}
} else if (model()->state() == password_manager::ui::BLACKLIST_STATE) { } else if (model()->state() == password_manager::ui::BLACKLIST_STATE) {
AddChildView(new BlacklistedView(this)); AddChildView(new BlacklistedView(this));
} else if (model()->state() == password_manager::ui::CONFIRMATION_STATE) { } else if (model()->state() == password_manager::ui::CONFIRMATION_STATE) {
...@@ -1012,6 +1144,7 @@ void ManagePasswordsBubbleView::NotifyConfirmedNeverForThisSite() { ...@@ -1012,6 +1144,7 @@ void ManagePasswordsBubbleView::NotifyConfirmedNeverForThisSite() {
void ManagePasswordsBubbleView::NotifyUndoNeverForThisSite() { void ManagePasswordsBubbleView::NotifyUndoNeverForThisSite() {
model()->OnUndoNeverForThisSite(); model()->OnUndoNeverForThisSite();
Refresh(); Refresh();
SizeToContents();
} }
void ManagePasswordsBubbleView::NotifyNeverForThisSiteClicked() { void ManagePasswordsBubbleView::NotifyNeverForThisSiteClicked() {
...@@ -1021,5 +1154,6 @@ void ManagePasswordsBubbleView::NotifyNeverForThisSiteClicked() { ...@@ -1021,5 +1154,6 @@ void ManagePasswordsBubbleView::NotifyNeverForThisSiteClicked() {
} else { } else {
model()->OnConfirmationForNeverForThisSite(); model()->OnConfirmationForNeverForThisSite();
Refresh(); Refresh();
SizeToContents();
} }
} }
...@@ -57,6 +57,7 @@ class ManagePasswordsBubbleView : public ManagePasswordsBubble, ...@@ -57,6 +57,7 @@ class ManagePasswordsBubbleView : public ManagePasswordsBubble,
class ManageView; class ManageView;
class ManageAccountsView; class ManageAccountsView;
class PendingView; class PendingView;
class SaveAccountView;
class SaveConfirmationView; class SaveConfirmationView;
class WebContentMouseHandler; class WebContentMouseHandler;
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/passwords/save_account_more_combobox_model.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
SaveAccountMoreComboboxModel::SaveAccountMoreComboboxModel() {
items_.push_back(
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_MORE_BUTTON));
items_.push_back(
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON));
items_.push_back(
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SETTINGS_LINK));
}
SaveAccountMoreComboboxModel::~SaveAccountMoreComboboxModel() {}
int SaveAccountMoreComboboxModel::GetItemCount() const {
return items_.size();
}
base::string16 SaveAccountMoreComboboxModel::GetItemAt(int index) {
return items_[index];
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_PASSWORDS_SAVE_ACCOUNT_MORE_COMBOBOX_MODEL_H_
#define CHROME_BROWSER_UI_VIEWS_PASSWORDS_SAVE_ACCOUNT_MORE_COMBOBOX_MODEL_H_
#include <vector>
#include "base/basictypes.h"
#include "base/strings/string16.h"
#include "ui/base/models/combobox_model.h"
class SaveAccountMoreComboboxModel : public ui::ComboboxModel {
public:
// The order of the values shouldn't be changed without reordering the strings
// in the constructor.
enum {
INDEX_MORE = 0,
INDEX_NEVER_FOR_THIS_SITE,
INDEX_SETTINGS,
};
SaveAccountMoreComboboxModel();
~SaveAccountMoreComboboxModel() override;
private:
// Overridden from ui::ComboboxModel:
int GetItemCount() const override;
base::string16 GetItemAt(int index) override;
std::vector<base::string16> items_;
DISALLOW_COPY_AND_ASSIGN(SaveAccountMoreComboboxModel);
};
#endif // CHROME_BROWSER_UI_VIEWS_PASSWORDS_SAVE_ACCOUNT_MORE_COMBOBOX_MODEL_H_
...@@ -2221,6 +2221,8 @@ ...@@ -2221,6 +2221,8 @@
'browser/ui/views/passwords/manage_passwords_bubble_view.h', 'browser/ui/views/passwords/manage_passwords_bubble_view.h',
'browser/ui/views/passwords/manage_passwords_icon_view.cc', 'browser/ui/views/passwords/manage_passwords_icon_view.cc',
'browser/ui/views/passwords/manage_passwords_icon_view.h', 'browser/ui/views/passwords/manage_passwords_icon_view.h',
'browser/ui/views/passwords/save_account_more_combobox_model.cc',
'browser/ui/views/passwords/save_account_more_combobox_model.h',
'browser/ui/views/pdf_password_dialog.cc', 'browser/ui/views/pdf_password_dialog.cc',
'browser/ui/views/process_singleton_dialog_linux.cc', 'browser/ui/views/process_singleton_dialog_linux.cc',
'browser/ui/views/profiles/avatar_menu_bubble_view.cc', 'browser/ui/views/profiles/avatar_menu_bubble_view.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment