Commit b1cabb61 authored by mkwst@chromium.org's avatar mkwst@chromium.org

Password bubble: Keep the bubble in sync with the password store.

When passwords for the current site are added, updated, or removed from
the password store, we should add, update, or remove them from the
bubble in order to keep things up to date.

This patch deals with the common case of removing passwords from the
settings page while the password bubble is instantiated on a separate
tab. A future patch will deal with adding or removing the site from the
blacklist.

BUG=330154
R=vabr@chromium.org,markusheintz@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263011 0039d316-1c4b-4281-b951-d872f2087c98
parent e72a5906
...@@ -24,24 +24,16 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel( ...@@ -24,24 +24,16 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
ManagePasswordsBubbleUIController* manage_passwords_bubble_ui_controller = ManagePasswordsBubbleUIController* manage_passwords_bubble_ui_controller =
ManagePasswordsBubbleUIController::FromWebContents(web_contents_); ManagePasswordsBubbleUIController::FromWebContents(web_contents_);
password_submitted_ = if (manage_passwords_bubble_ui_controller->password_to_be_saved())
manage_passwords_bubble_ui_controller->password_submitted(); manage_passwords_bubble_state_ = PASSWORD_TO_BE_SAVED;
if (password_submitted_) { else
if (manage_passwords_bubble_ui_controller->password_to_be_saved())
manage_passwords_bubble_state_ = PASSWORD_TO_BE_SAVED;
else
manage_passwords_bubble_state_ = MANAGE_PASSWORDS_AFTER_SAVING;
} else {
manage_passwords_bubble_state_ = MANAGE_PASSWORDS; manage_passwords_bubble_state_ = MANAGE_PASSWORDS;
}
title_ = l10n_util::GetStringUTF16( title_ = l10n_util::GetStringUTF16(
(manage_passwords_bubble_state_ == PASSWORD_TO_BE_SAVED) ? (manage_passwords_bubble_state_ == PASSWORD_TO_BE_SAVED) ?
IDS_SAVE_PASSWORD : IDS_MANAGE_PASSWORDS); IDS_SAVE_PASSWORD : IDS_MANAGE_PASSWORDS);
if (password_submitted_) { pending_credentials_ =
pending_credentials_ = manage_passwords_bubble_ui_controller->pending_credentials();
manage_passwords_bubble_ui_controller->pending_credentials();
}
best_matches_ = manage_passwords_bubble_ui_controller->best_matches(); best_matches_ = manage_passwords_bubble_ui_controller->best_matches();
manage_link_ = manage_link_ =
l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK); l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK);
...@@ -66,7 +58,7 @@ void ManagePasswordsBubbleModel::OnSaveClicked() { ...@@ -66,7 +58,7 @@ void ManagePasswordsBubbleModel::OnSaveClicked() {
ManagePasswordsBubbleUIController::FromWebContents(web_contents_); ManagePasswordsBubbleUIController::FromWebContents(web_contents_);
manage_passwords_bubble_ui_controller->SavePassword(); manage_passwords_bubble_ui_controller->SavePassword();
manage_passwords_bubble_ui_controller->unset_password_to_be_saved(); manage_passwords_bubble_ui_controller->unset_password_to_be_saved();
manage_passwords_bubble_state_ = MANAGE_PASSWORDS_AFTER_SAVING; manage_passwords_bubble_state_ = MANAGE_PASSWORDS;
} }
void ManagePasswordsBubbleModel::OnManageLinkClicked() { void ManagePasswordsBubbleModel::OnManageLinkClicked() {
...@@ -89,18 +81,6 @@ void ManagePasswordsBubbleModel::OnPasswordAction( ...@@ -89,18 +81,6 @@ void ManagePasswordsBubbleModel::OnPasswordAction(
password_store->RemoveLogin(password_form); password_store->RemoveLogin(password_form);
else else
password_store->AddLogin(password_form); password_store->AddLogin(password_form);
// This is necessary in case the bubble is instantiated again, we thus do not
// display the pending credentials if they were deleted.
if (password_form.username_value == pending_credentials_.username_value) {
ManagePasswordsBubbleUIController::FromWebContents(web_contents_)
->set_password_submitted(action == ADD_PASSWORD);
}
}
void ManagePasswordsBubbleModel::DeleteFromBestMatches(
autofill::PasswordForm password_form) {
ManagePasswordsBubbleUIController::FromWebContents(web_contents_)->
RemoveFromBestMatches(password_form);
} }
void ManagePasswordsBubbleModel::WebContentsDestroyed( void ManagePasswordsBubbleModel::WebContentsDestroyed(
......
...@@ -23,7 +23,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver { ...@@ -23,7 +23,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver {
enum ManagePasswordsBubbleState { enum ManagePasswordsBubbleState {
PASSWORD_TO_BE_SAVED, PASSWORD_TO_BE_SAVED,
MANAGE_PASSWORDS_AFTER_SAVING,
MANAGE_PASSWORDS, MANAGE_PASSWORDS,
NEVER_SAVE_PASSWORDS, NEVER_SAVE_PASSWORDS,
}; };
...@@ -48,12 +47,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver { ...@@ -48,12 +47,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver {
void OnPasswordAction(const autofill::PasswordForm& password_form, void OnPasswordAction(const autofill::PasswordForm& password_form,
PasswordAction action); PasswordAction action);
// Called by the view code when the ManagePasswordItemView is destroyed and
// the user chose to delete the password.
// TODO(npentrel): Remove this once best_matches_ are newly made on bubble
// opening.
void DeleteFromBestMatches(autofill::PasswordForm password_form);
ManagePasswordsBubbleState manage_passwords_bubble_state() { ManagePasswordsBubbleState manage_passwords_bubble_state() {
return manage_passwords_bubble_state_; return manage_passwords_bubble_state_;
} }
...@@ -62,7 +55,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver { ...@@ -62,7 +55,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver {
return manage_passwords_bubble_state() == PASSWORD_TO_BE_SAVED; return manage_passwords_bubble_state() == PASSWORD_TO_BE_SAVED;
} }
bool password_submitted() { return password_submitted_; }
const base::string16& title() { return title_; } const base::string16& title() { return title_; }
const autofill::PasswordForm& pending_credentials() { const autofill::PasswordForm& pending_credentials() {
return pending_credentials_; return pending_credentials_;
...@@ -77,7 +69,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver { ...@@ -77,7 +69,6 @@ class ManagePasswordsBubbleModel : public content::WebContentsObserver {
content::WebContents* web_contents_; content::WebContents* web_contents_;
ManagePasswordsBubbleState manage_passwords_bubble_state_; ManagePasswordsBubbleState manage_passwords_bubble_state_;
bool password_submitted_;
base::string16 title_; base::string16 title_;
autofill::PasswordForm pending_credentials_; autofill::PasswordForm pending_credentials_;
autofill::PasswordFormMap best_matches_; autofill::PasswordFormMap best_matches_;
......
...@@ -5,14 +5,27 @@ ...@@ -5,14 +5,27 @@
#include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h" #include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/omnibox/location_bar.h" #include "chrome/browser/ui/omnibox/location_bar.h"
#include "components/password_manager/core/browser/password_store.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
using autofill::PasswordFormMap; using autofill::PasswordFormMap;
using password_manager::PasswordFormManager; using password_manager::PasswordFormManager;
namespace {
password_manager::PasswordStore* GetPasswordStore(
content::WebContents* web_contents) {
return PasswordStoreFactory::GetForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext()),
Profile::EXPLICIT_ACCESS).get();
}
} // namespace
DEFINE_WEB_CONTENTS_USER_DATA_KEY(ManagePasswordsBubbleUIController); DEFINE_WEB_CONTENTS_USER_DATA_KEY(ManagePasswordsBubbleUIController);
ManagePasswordsBubbleUIController::ManagePasswordsBubbleUIController( ManagePasswordsBubbleUIController::ManagePasswordsBubbleUIController(
...@@ -21,8 +34,12 @@ ManagePasswordsBubbleUIController::ManagePasswordsBubbleUIController( ...@@ -21,8 +34,12 @@ ManagePasswordsBubbleUIController::ManagePasswordsBubbleUIController(
manage_passwords_icon_to_be_shown_(false), manage_passwords_icon_to_be_shown_(false),
password_to_be_saved_(false), password_to_be_saved_(false),
manage_passwords_bubble_needs_showing_(false), manage_passwords_bubble_needs_showing_(false),
password_submitted_(false), autofill_blocked_(false) {
autofill_blocked_(false) {} password_manager::PasswordStore* password_store =
GetPasswordStore(web_contents);
if (password_store)
password_store->AddObserver(this);
}
ManagePasswordsBubbleUIController::~ManagePasswordsBubbleUIController() {} ManagePasswordsBubbleUIController::~ManagePasswordsBubbleUIController() {}
...@@ -41,10 +58,10 @@ void ManagePasswordsBubbleUIController::OnPasswordSubmitted( ...@@ -41,10 +58,10 @@ void ManagePasswordsBubbleUIController::OnPasswordSubmitted(
PasswordFormManager* form_manager) { PasswordFormManager* form_manager) {
form_manager_.reset(form_manager); form_manager_.reset(form_manager);
password_form_map_ = form_manager_->best_matches(); password_form_map_ = form_manager_->best_matches();
origin_ = pending_credentials().origin;
manage_passwords_icon_to_be_shown_ = true; manage_passwords_icon_to_be_shown_ = true;
password_to_be_saved_ = true; password_to_be_saved_ = true;
manage_passwords_bubble_needs_showing_ = true; manage_passwords_bubble_needs_showing_ = true;
password_submitted_ = true;
autofill_blocked_ = false; autofill_blocked_ = false;
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
...@@ -52,10 +69,10 @@ void ManagePasswordsBubbleUIController::OnPasswordSubmitted( ...@@ -52,10 +69,10 @@ void ManagePasswordsBubbleUIController::OnPasswordSubmitted(
void ManagePasswordsBubbleUIController::OnPasswordAutofilled( void ManagePasswordsBubbleUIController::OnPasswordAutofilled(
const PasswordFormMap& password_form_map) { const PasswordFormMap& password_form_map) {
password_form_map_ = password_form_map; password_form_map_ = password_form_map;
origin_ = password_form_map_.begin()->second->origin;
manage_passwords_icon_to_be_shown_ = true; manage_passwords_icon_to_be_shown_ = true;
password_to_be_saved_ = false; password_to_be_saved_ = false;
manage_passwords_bubble_needs_showing_ = false; manage_passwords_bubble_needs_showing_ = false;
password_submitted_ = false;
autofill_blocked_ = false; autofill_blocked_ = false;
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
...@@ -64,14 +81,36 @@ void ManagePasswordsBubbleUIController::OnBlacklistBlockedAutofill() { ...@@ -64,14 +81,36 @@ void ManagePasswordsBubbleUIController::OnBlacklistBlockedAutofill() {
manage_passwords_icon_to_be_shown_ = true; manage_passwords_icon_to_be_shown_ = true;
password_to_be_saved_ = false; password_to_be_saved_ = false;
manage_passwords_bubble_needs_showing_ = false; manage_passwords_bubble_needs_showing_ = false;
password_submitted_ = false;
autofill_blocked_ = true; autofill_blocked_ = true;
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
void ManagePasswordsBubbleUIController::RemoveFromBestMatches( void ManagePasswordsBubbleUIController::WebContentsDestroyed(
autofill::PasswordForm password_form) { content::WebContents* web_contents) {
password_form_map_.erase(password_form.username_value); password_manager::PasswordStore* password_store =
GetPasswordStore(web_contents);
if (password_store)
password_store->RemoveObserver(this);
}
void ManagePasswordsBubbleUIController::OnLoginsChanged(
const password_manager::PasswordStoreChangeList& changes) {
for (password_manager::PasswordStoreChangeList::const_iterator it =
changes.begin();
it != changes.end();
it++) {
const autofill::PasswordForm& changed_form = it->form();
if (changed_form.origin != origin_)
continue;
if (it->type() == password_manager::PasswordStoreChange::REMOVE) {
password_form_map_.erase(changed_form.username_value);
} else {
autofill::PasswordForm* new_form =
new autofill::PasswordForm(changed_form);
password_form_map_[changed_form.username_value] = new_form;
}
}
} }
void ManagePasswordsBubbleUIController::OnBubbleShown() { void ManagePasswordsBubbleUIController::OnBubbleShown() {
...@@ -97,6 +136,5 @@ void ManagePasswordsBubbleUIController::DidNavigateMainFrame( ...@@ -97,6 +136,5 @@ void ManagePasswordsBubbleUIController::DidNavigateMainFrame(
manage_passwords_icon_to_be_shown_ = false; manage_passwords_icon_to_be_shown_ = false;
password_to_be_saved_ = false; password_to_be_saved_ = false;
manage_passwords_bubble_needs_showing_ = false; manage_passwords_bubble_needs_showing_ = false;
password_submitted_ = false;
UpdateBubbleAndIconVisibility(); UpdateBubbleAndIconVisibility();
} }
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_BUBBLE_UI_CONTROLLER_H_ #define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_BUBBLE_UI_CONTROLLER_H_
#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/password_store_change.h"
#include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_details.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_contents_user_data.h"
...@@ -17,7 +19,8 @@ class WebContents; ...@@ -17,7 +19,8 @@ class WebContents;
// Per-tab class to control the Omnibox password icon and bubble. // Per-tab class to control the Omnibox password icon and bubble.
class ManagePasswordsBubbleUIController class ManagePasswordsBubbleUIController
: public content::WebContentsObserver, : public content::WebContentsObserver,
public content::WebContentsUserData<ManagePasswordsBubbleUIController> { public content::WebContentsUserData<ManagePasswordsBubbleUIController>,
public password_manager::PasswordStore::Observer {
public: public:
virtual ~ManagePasswordsBubbleUIController(); virtual ~ManagePasswordsBubbleUIController();
...@@ -36,12 +39,9 @@ class ManagePasswordsBubbleUIController ...@@ -36,12 +39,9 @@ class ManagePasswordsBubbleUIController
// Called when a form is _not_ autofilled due to user blacklisting. // Called when a form is _not_ autofilled due to user blacklisting.
void OnBlacklistBlockedAutofill(); void OnBlacklistBlockedAutofill();
// TODO(npentrel) This ought to be changed. Best matches should be newly // PasswordStore::Observer implementation.
// made when opening the ManagePasswordsBubble because there may have been virtual void OnLoginsChanged(
// changes to the best matches via the settings page. At the moment this also const password_manager::PasswordStoreChangeList& changes) OVERRIDE;
// fails if one deletes a password when they are autofilled, as it still shows
// up after logging in and saving a password.
void RemoveFromBestMatches(autofill::PasswordForm password_form);
void SavePassword(); void SavePassword();
...@@ -79,14 +79,6 @@ class ManagePasswordsBubbleUIController ...@@ -79,14 +79,6 @@ class ManagePasswordsBubbleUIController
return password_form_map_; return password_form_map_;
} }
bool password_submitted() const {
return password_submitted_;
}
void set_password_submitted(bool password_submitted) {
password_submitted_ = password_submitted;
}
bool autofill_blocked() const { return autofill_blocked_; } bool autofill_blocked() const { return autofill_blocked_; }
void set_autofill_blocked(bool autofill_blocked) { void set_autofill_blocked(bool autofill_blocked) {
autofill_blocked_ = autofill_blocked; autofill_blocked_ = autofill_blocked;
...@@ -107,6 +99,8 @@ class ManagePasswordsBubbleUIController ...@@ -107,6 +99,8 @@ class ManagePasswordsBubbleUIController
virtual void DidNavigateMainFrame( virtual void DidNavigateMainFrame(
const content::LoadCommittedDetails& details, const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) OVERRIDE; const content::FrameNavigateParams& params) OVERRIDE;
virtual void WebContentsDestroyed(
content::WebContents* web_contents) OVERRIDE;
// Set by OnPasswordSubmitted() when the user submits a form containing login // Set by OnPasswordSubmitted() when the user submits a form containing login
// information. If the user responds to a subsequent "Do you want to save // information. If the user responds to a subsequent "Do you want to save
...@@ -121,14 +115,16 @@ class ManagePasswordsBubbleUIController ...@@ -121,14 +115,16 @@ class ManagePasswordsBubbleUIController
bool manage_passwords_icon_to_be_shown_; bool manage_passwords_icon_to_be_shown_;
bool password_to_be_saved_; bool password_to_be_saved_;
bool manage_passwords_bubble_needs_showing_; bool manage_passwords_bubble_needs_showing_;
// Stores whether a new password has been submitted, if so we have
// |pending_credentials|.
bool password_submitted_;
// Stores whether autofill was blocked due to a user's decision to blacklist // Stores whether autofill was blocked due to a user's decision to blacklist
// the current site ("Never save passwords for this site"). // the current site ("Never save passwords for this site").
bool autofill_blocked_; bool autofill_blocked_;
// The origin of the form we're currently dealing with; we'll use this to
// determine which PasswordStore changes we should care about when updating
// |password_form_map_|.
GURL origin_;
DISALLOW_COPY_AND_ASSIGN(ManagePasswordsBubbleUIController); DISALLOW_COPY_AND_ASSIGN(ManagePasswordsBubbleUIController);
}; };
......
...@@ -127,10 +127,7 @@ ManagePasswordItemView::ManagePasswordItemView( ...@@ -127,10 +127,7 @@ ManagePasswordItemView::ManagePasswordItemView(
GetLayoutManager()->Layout(this); GetLayoutManager()->Layout(this);
} }
ManagePasswordItemView::~ManagePasswordItemView() { ManagePasswordItemView::~ManagePasswordItemView() {}
if (delete_password_)
manage_passwords_bubble_model_->DeleteFromBestMatches(password_form_);
}
void ManagePasswordItemView::BuildColumnSet(views::GridLayout* layout, void ManagePasswordItemView::BuildColumnSet(views::GridLayout* layout,
int column_set_id) { int column_set_id) {
......
...@@ -320,7 +320,6 @@ void ManagePasswordsBubbleView::Init() { ...@@ -320,7 +320,6 @@ void ManagePasswordsBubbleView::Init() {
// TODO(mkwst): Do we really want the "No passwords" case? It would probably // TODO(mkwst): Do we really want the "No passwords" case? It would probably
// be better to only clear the pending password upon navigation, rather than // be better to only clear the pending password upon navigation, rather than
// as soon as the bubble closes. // as soon as the bubble closes.
int num_items_displayed = 0;
if (!manage_passwords_bubble_model_->best_matches().empty()) { if (!manage_passwords_bubble_model_->best_matches().empty()) {
for (autofill::PasswordFormMap::const_iterator i( for (autofill::PasswordFormMap::const_iterator i(
manage_passwords_bubble_model_->best_matches().begin()); manage_passwords_bubble_model_->best_matches().begin());
...@@ -330,14 +329,14 @@ void ManagePasswordsBubbleView::Init() { ...@@ -330,14 +329,14 @@ void ManagePasswordsBubbleView::Init() {
*i->second, *i->second,
first_field_width, first_field_width,
second_field_width, second_field_width,
num_items_displayed == 0 ? ManagePasswordItemView::FIRST_ITEM i == manage_passwords_bubble_model_->best_matches().begin()
: ManagePasswordItemView::SUBSEQUENT_ITEM); ? ManagePasswordItemView::FIRST_ITEM
: ManagePasswordItemView::SUBSEQUENT_ITEM);
layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
layout->AddView(item); layout->AddView(item);
num_items_displayed++;
} }
} else if (!manage_passwords_bubble_model_->password_submitted()) { } else {
views::Label* empty_label = new views::Label( views::Label* empty_label = new views::Label(
l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_NO_PASSWORDS)); l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_NO_PASSWORDS));
empty_label->SetMultiLine(true); empty_label->SetMultiLine(true);
...@@ -346,22 +345,6 @@ void ManagePasswordsBubbleView::Init() { ...@@ -346,22 +345,6 @@ void ManagePasswordsBubbleView::Init() {
layout->AddView(empty_label); layout->AddView(empty_label);
} }
// If the user just saved a password, it won't be in the 'best matches' list
// we just walked through. Display it explicitly.
if (manage_passwords_bubble_model_->password_submitted()) {
ManagePasswordItemView* item = new ManagePasswordItemView(
manage_passwords_bubble_model_,
manage_passwords_bubble_model_->pending_credentials(),
first_field_width,
second_field_width,
num_items_displayed ? ManagePasswordItemView::FIRST_ITEM
: ManagePasswordItemView::SUBSEQUENT_ITEM);
layout->StartRow(0, SINGLE_VIEW_COLUMN_SET);
layout->AddView(item);
num_items_displayed++;
}
// Build a "manage" link and "done" button, and throw them both into a new // Build a "manage" link and "done" button, and throw them both into a new
// row // row
// containing a double-view columnset. // containing a double-view columnset.
......
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