Commit 9401da7c authored by Vasilii Sukhanov's avatar Vasilii Sukhanov Committed by Commit Bot

Change interface of FormSaver::Update.

This is a follow up to r649499. The Update method now matches Save() method.
The replacement logic is now in UpdateReplace().

Bug: 936011,831123
Change-Id: I59d65fe77ef3b386e80ba890e140370d190555c9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1596456
Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarDominic Battré <battre@chromium.org>
Cr-Commit-Position: refs/heads/master@{#657675}
parent 942cd543
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/password_store.h"
namespace password_manager { namespace password_manager {
...@@ -24,8 +25,10 @@ class FormSaver { ...@@ -24,8 +25,10 @@ class FormSaver {
virtual ~FormSaver() = default; virtual ~FormSaver() = default;
// Configures the |observed| form to become a blacklist entry and saves it. // Blacklist the origin described by |digest|. Returns the PasswordForm pushed
virtual void PermanentlyBlacklist(autofill::PasswordForm* observed) = 0; // to the store.
virtual autofill::PasswordForm PermanentlyBlacklist(
PasswordStore::FormDigest digest) WARN_UNUSED_RESULT = 0;
// Saves the |pending| form. // Saves the |pending| form.
// |matches| are relevant credentials for the site. After saving |pending|, // |matches| are relevant credentials for the site. After saving |pending|,
...@@ -35,21 +38,29 @@ class FormSaver { ...@@ -35,21 +38,29 @@ class FormSaver {
// - empty-username credentials with the same password are removed. // - empty-username credentials with the same password are removed.
// - if |old_password| is provided, the old credentials with the same username // - if |old_password| is provided, the old credentials with the same username
// and the old password are updated to the new password. // and the old password are updated to the new password.
virtual void Save(const autofill::PasswordForm& pending, virtual void Save(autofill::PasswordForm pending,
const std::vector<const autofill::PasswordForm*>& matches, const std::vector<const autofill::PasswordForm*>& matches,
const base::string16& old_password) = 0; const base::string16& old_password) = 0;
// Updates the |pending| form and updates the stored preference on // Updates the saved credential in the password store sharing the same key as
// |best_matches|. If |old_primary_key| is given, uses it for saving // the |pending| form.
// |pending|. It also updates the password store with all // The algorithm for handling |matches| and |old_password| is the same as
// |credentials_to_update|. // above.
// TODO(crbug/831123): it's a convoluted interface, switch to the one for Save virtual void Update(autofill::PasswordForm pending,
virtual void Update( const std::vector<const autofill::PasswordForm*>& matches,
const autofill::PasswordForm& pending, const base::string16& old_password) = 0;
const std::map<base::string16, const autofill::PasswordForm*>&
best_matches, // If any of the primary key fields (signon_realm, origin, username_element,
const std::vector<autofill::PasswordForm>* credentials_to_update, // username_value, password_element) are updated, then the this version of
const autofill::PasswordForm* old_primary_key) = 0; // the Update method must be used, which takes |old_primary_key|, i.e., the
// old values for the primary key fields (the rest of the fields are ignored).
// The algorithm for handling |matches| and |old_password| is the same as
// above.
virtual void UpdateReplace(
autofill::PasswordForm pending,
const std::vector<const autofill::PasswordForm*>& matches,
const base::string16& old_password,
const autofill::PasswordForm& old_unique_key) = 0;
// Removes |form| from the password store. // Removes |form| from the password store.
virtual void Remove(const autofill::PasswordForm& form) = 0; virtual void Remove(const autofill::PasswordForm& form) = 0;
......
...@@ -42,40 +42,25 @@ void SanitizeFormData(FormData* form) { ...@@ -42,40 +42,25 @@ void SanitizeFormData(FormData* form) {
} }
} }
} // namespace // Do the clean up of |matches| after |pending| was just pushed to the store.
void PostProcessMatches(const PasswordForm& pending,
FormSaverImpl::FormSaverImpl(PasswordStore* store) : store_(store) { const std::vector<const PasswordForm*>& matches,
DCHECK(store); const base::string16& old_password,
} PasswordStore* store) {
FormSaverImpl::~FormSaverImpl() = default;
void FormSaverImpl::PermanentlyBlacklist(PasswordForm* observed) {
*observed = password_manager_util::MakeNormalizedBlacklistedForm(
PasswordStore::FormDigest(*observed));
observed->date_created = base::Time::Now();
store_->AddLogin(*observed);
}
void FormSaverImpl::Save(const PasswordForm& pending,
const std::vector<const PasswordForm*>& matches,
const base::string16& old_password) {
DCHECK(!pending.blacklisted_by_user); DCHECK(!pending.blacklisted_by_user);
PasswordForm sanitized_pending(pending);
SanitizeFormData(&sanitized_pending.form_data);
store_->AddLogin(sanitized_pending);
// Update existing matches in the password store. // Update existing matches in the password store.
for (const auto* match : matches) { for (const auto* match : matches) {
DCHECK(pending.preferred); DCHECK(pending.preferred);
if (match->IsFederatedCredential()) if (match->IsFederatedCredential() ||
ArePasswordFormUniqueKeyEqual(pending, *match))
continue; continue;
// Delete obsolete empty username credentials. // Delete obsolete empty username credentials.
const bool same_password = match->password_value == pending.password_value; const bool same_password = match->password_value == pending.password_value;
const bool username_was_added = const bool username_was_added =
match->username_value.empty() && !pending.username_value.empty(); match->username_value.empty() && !pending.username_value.empty();
if (same_password && username_was_added && !match->is_public_suffix_match) { if (same_password && username_was_added && !match->is_public_suffix_match) {
store_->RemoveLogin(*match); store->RemoveLogin(*match);
continue; continue;
} }
base::Optional<PasswordForm> form_to_update; base::Optional<PasswordForm> form_to_update;
...@@ -95,72 +80,64 @@ void FormSaverImpl::Save(const PasswordForm& pending, ...@@ -95,72 +80,64 @@ void FormSaverImpl::Save(const PasswordForm& pending,
} }
if (form_to_update) { if (form_to_update) {
SanitizeFormData(&form_to_update->form_data); SanitizeFormData(&form_to_update->form_data);
store_->UpdateLogin(std::move(*form_to_update)); store->UpdateLogin(std::move(*form_to_update));
} }
} }
} }
void FormSaverImpl::Update( } // namespace
const PasswordForm& pending,
const std::map<base::string16, const PasswordForm*>& best_matches,
const std::vector<PasswordForm>* credentials_to_update,
const PasswordForm* old_primary_key) {
DCHECK(!pending.blacklisted_by_user);
if (!best_matches.empty()) { FormSaverImpl::FormSaverImpl(PasswordStore* store) : store_(store) {
DCHECK(pending.preferred); DCHECK(store);
UpdatePreferredLoginState(pending.username_value, best_matches);
}
PasswordForm sanitized_pending(pending);
SanitizeFormData(&sanitized_pending.form_data);
if (old_primary_key)
store_->UpdateLoginWithPrimaryKey(sanitized_pending, *old_primary_key);
else
store_->UpdateLogin(sanitized_pending);
if (credentials_to_update) {
for (const PasswordForm& credential : *credentials_to_update) {
store_->UpdateLogin(credential);
}
}
} }
void FormSaverImpl::Remove(const PasswordForm& form) { FormSaverImpl::~FormSaverImpl() = default;
store_->RemoveLogin(form);
PasswordForm FormSaverImpl::PermanentlyBlacklist(
PasswordStore::FormDigest digest) {
PasswordForm blacklisted =
password_manager_util::MakeNormalizedBlacklistedForm(std::move(digest));
blacklisted.date_created = base::Time::Now();
store_->AddLogin(blacklisted);
return blacklisted;
} }
std::unique_ptr<FormSaver> FormSaverImpl::Clone() { void FormSaverImpl::Save(PasswordForm pending,
return std::make_unique<FormSaverImpl>(store_); const std::vector<const PasswordForm*>& matches,
const base::string16& old_password) {
SanitizeFormData(&pending.form_data);
store_->AddLogin(pending);
// Update existing matches in the password store.
PostProcessMatches(pending, matches, old_password, store_);
} }
void FormSaverImpl::UpdatePreferredLoginState( void FormSaverImpl::Update(
const base::string16& preferred_username, autofill::PasswordForm pending,
const std::map<base::string16, const PasswordForm*>& best_matches) { const std::vector<const autofill::PasswordForm*>& matches,
for (const auto& key_value_pair : best_matches) { const base::string16& old_password) {
const PasswordForm& form = *key_value_pair.second; SanitizeFormData(&pending.form_data);
if (form.preferred && !form.is_public_suffix_match && store_->UpdateLogin(pending);
form.username_value != preferred_username) { // Update existing matches in the password store.
// This wasn't the selected login but it used to be preferred. PostProcessMatches(pending, matches, old_password, store_);
PasswordForm update(form);
SanitizeFormData(&update.form_data);
update.preferred = false;
store_->UpdateLogin(update);
}
}
} }
void FormSaverImpl::DeleteEmptyUsernameCredentials( void FormSaverImpl::UpdateReplace(
const PasswordForm& pending, autofill::PasswordForm pending,
const std::map<base::string16, const PasswordForm*>& best_matches) { const std::vector<const autofill::PasswordForm*>& matches,
DCHECK(!pending.username_value.empty()); const base::string16& old_password,
const autofill::PasswordForm& old_unique_key) {
SanitizeFormData(&pending.form_data);
store_->UpdateLoginWithPrimaryKey(pending, old_unique_key);
// Update existing matches in the password store.
PostProcessMatches(pending, matches, old_password, store_);
}
for (const auto& match : best_matches) { void FormSaverImpl::Remove(const PasswordForm& form) {
const PasswordForm* form = match.second; store_->RemoveLogin(form);
if (!form->is_public_suffix_match && form->username_value.empty() && }
form->password_value == pending.password_value) {
store_->RemoveLogin(*form); std::unique_ptr<FormSaver> FormSaverImpl::Clone() {
} return std::make_unique<FormSaverImpl>(store_);
}
} }
} // namespace password_manager } // namespace password_manager
...@@ -24,34 +24,22 @@ class FormSaverImpl : public FormSaver { ...@@ -24,34 +24,22 @@ class FormSaverImpl : public FormSaver {
~FormSaverImpl() override; ~FormSaverImpl() override;
// FormSaver: // FormSaver:
void PermanentlyBlacklist(autofill::PasswordForm* observed) override; autofill::PasswordForm PermanentlyBlacklist(
void Save(const autofill::PasswordForm& pending, PasswordStore::FormDigest digest) override WARN_UNUSED_RESULT;
void Save(autofill::PasswordForm pending,
const std::vector<const autofill::PasswordForm*>& matches, const std::vector<const autofill::PasswordForm*>& matches,
const base::string16& old_password) override; const base::string16& old_password) override;
void Update(const autofill::PasswordForm& pending, void Update(autofill::PasswordForm pending,
const std::map<base::string16, const autofill::PasswordForm*>& const std::vector<const autofill::PasswordForm*>& matches,
best_matches, const base::string16& old_password) override;
const std::vector<autofill::PasswordForm>* credentials_to_update, void UpdateReplace(autofill::PasswordForm pending,
const autofill::PasswordForm* old_primary_key) override; const std::vector<const autofill::PasswordForm*>& matches,
const base::string16& old_password,
const autofill::PasswordForm& old_unique_key) override;
void Remove(const autofill::PasswordForm& form) override; void Remove(const autofill::PasswordForm& form) override;
std::unique_ptr<FormSaver> Clone() override; std::unique_ptr<FormSaver> Clone() override;
private: private:
// Marks all of |best_matches| as not preferred unless the username is
// |preferred_username| or the credential is PSL matched.
void UpdatePreferredLoginState(
const base::string16& preferred_username,
const std::map<base::string16, const autofill::PasswordForm*>&
best_matches);
// Iterates over all |best_matches| and deletes from the password store all
// which are not PSL-matched, have an empty username, and a password equal to
// |pending.password_value|.
void DeleteEmptyUsernameCredentials(
const autofill::PasswordForm& pending,
const std::map<base::string16, const autofill::PasswordForm*>&
best_matches);
// The class is stateless. Don't introduce it. The methods are utilities for // The class is stateless. Don't introduce it. The methods are utilities for
// common tasks on the password store. The state should belong to either a // common tasks on the password store. The state should belong to either a
// form handler or origin handler which could embed FormSaver. // form handler or origin handler which could embed FormSaver.
......
...@@ -267,21 +267,10 @@ void NewPasswordFormManager::Save() { ...@@ -267,21 +267,10 @@ void NewPasswordFormManager::Save() {
pending_credentials_.date_created = base::Time::Now(); pending_credentials_.date_created = base::Time::Now();
votes_uploader_.SendVotesOnSave(observed_form_, *parsed_submitted_form_, votes_uploader_.SendVotesOnSave(observed_form_, *parsed_submitted_form_,
best_matches_, &pending_credentials_); best_matches_, &pending_credentials_);
base::string16 old_password; SavePendingToStore(false /*update*/);
if (password_overridden_) {
// |pending_credentials_| contains not only a new credential that is to be
// stored, but it also implies that existing credentials in the store need
// to get the password updated.
const PasswordForm* saved_form =
password_manager_util::GetMatchForUpdating(*parsed_submitted_form_,
best_matches_);
DCHECK(saved_form);
old_password = saved_form->password_value;
}
SavePendingToStore(false /*update*/, old_password);
} else { } else {
ProcessUpdate(); ProcessUpdate();
SavePendingToStore(true /*update*/, base::string16()); SavePendingToStore(true /*update*/);
} }
if (pending_credentials_.times_used == 1 && if (pending_credentials_.times_used == 1 &&
...@@ -311,7 +300,7 @@ void NewPasswordFormManager::Update(const PasswordForm& credentials_to_update) { ...@@ -311,7 +300,7 @@ void NewPasswordFormManager::Update(const PasswordForm& credentials_to_update) {
pending_credentials_.preferred = true; pending_credentials_.preferred = true;
is_new_login_ = false; is_new_login_ = false;
ProcessUpdate(); ProcessUpdate();
SavePendingToStore(true /*update*/, base::string16()); SavePendingToStore(true /*update*/);
client_->UpdateFormManagers(); client_->UpdateFormManagers();
} }
...@@ -406,7 +395,8 @@ void NewPasswordFormManager::PermanentlyBlacklist() { ...@@ -406,7 +395,8 @@ void NewPasswordFormManager::PermanentlyBlacklist() {
} }
blacklisted_matches_.push_back(new_blacklisted_.get()); blacklisted_matches_.push_back(new_blacklisted_.get());
} }
form_saver_->PermanentlyBlacklist(new_blacklisted_.get()); *new_blacklisted_ = form_saver_->PermanentlyBlacklist(
PasswordStore::FormDigest(*new_blacklisted_));
} }
void NewPasswordFormManager::OnPasswordsRevealed() { void NewPasswordFormManager::OnPasswordsRevealed() {
...@@ -988,29 +978,6 @@ void NewPasswordFormManager::FillHttpAuth() { ...@@ -988,29 +978,6 @@ void NewPasswordFormManager::FillHttpAuth() {
client_->AutofillHttpAuth(best_matches_, *preferred_match_); client_->AutofillHttpAuth(best_matches_, *preferred_match_);
} }
std::vector<PasswordForm> NewPasswordFormManager::FindOtherCredentialsToUpdate()
const {
std::vector<autofill::PasswordForm> credentials_to_update;
if (!pending_credentials_.federation_origin.opaque())
return credentials_to_update;
auto updated_password_it =
best_matches_.find(pending_credentials_.username_value);
DCHECK(best_matches_.end() != updated_password_it);
const base::string16& old_password =
updated_password_it->second->password_value;
for (auto* not_best_match : not_best_matches_) {
if (not_best_match->username_value == pending_credentials_.username_value &&
not_best_match->password_value == old_password) {
credentials_to_update.push_back(*not_best_match);
credentials_to_update.back().password_value =
pending_credentials_.password_value;
}
}
return credentials_to_update;
}
std::unique_ptr<PasswordForm> NewPasswordFormManager::ParseFormAndMakeLogging( std::unique_ptr<PasswordForm> NewPasswordFormManager::ParseFormAndMakeLogging(
const FormData& form, const FormData& form,
FormDataParser::Mode mode) { FormDataParser::Mode mode) {
...@@ -1108,17 +1075,18 @@ std::vector<const PasswordForm*> NewPasswordFormManager::GetAllMatches() const { ...@@ -1108,17 +1075,18 @@ std::vector<const PasswordForm*> NewPasswordFormManager::GetAllMatches() const {
return result; return result;
} }
void NewPasswordFormManager::SavePendingToStore( void NewPasswordFormManager::SavePendingToStore(bool update) {
bool update, const PasswordForm* saved_form = password_manager_util::GetMatchForUpdating(
const base::string16& old_password) { *parsed_submitted_form_, best_matches_);
if (update || password_overridden_)
DCHECK(saved_form);
base::string16 old_password =
saved_form ? saved_form->password_value : base::string16();
if (HasGeneratedPassword()) { if (HasGeneratedPassword()) {
generation_state_->CommitGeneratedPassword(pending_credentials_, generation_state_->CommitGeneratedPassword(pending_credentials_,
best_matches_, nullptr); GetAllMatches(), old_password);
} else if (update) { } else if (update) {
std::vector<PasswordForm> credentials_to_update = form_saver_->Update(pending_credentials_, GetAllMatches(), old_password);
FindOtherCredentialsToUpdate();
form_saver_->Update(pending_credentials_, best_matches_,
&credentials_to_update, nullptr);
} else { } else {
form_saver_->Save(pending_credentials_, GetAllMatches(), old_password); form_saver_->Save(pending_credentials_, GetAllMatches(), old_password);
} }
......
...@@ -250,13 +250,6 @@ class NewPasswordFormManager : public PasswordFormManagerInterface, ...@@ -250,13 +250,6 @@ class NewPasswordFormManager : public PasswordFormManagerInterface,
// Sends fill data to the http auth popup. // Sends fill data to the http auth popup.
void FillHttpAuth(); void FillHttpAuth();
// Goes through |not_best_matches_|, updates the password of those which share
// the old password and username with |pending_credentials_| to the new
// password of |pending_credentials_|, and returns copies of all such modified
// credentials.
// TODO(crbug/831123): remove. FormSaver should do the job.
std::vector<autofill::PasswordForm> FindOtherCredentialsToUpdate() const;
// Helper function for calling form parsing and logging results if logging is // Helper function for calling form parsing and logging results if logging is
// active. // active.
std::unique_ptr<autofill::PasswordForm> ParseFormAndMakeLogging( std::unique_ptr<autofill::PasswordForm> ParseFormAndMakeLogging(
...@@ -276,9 +269,8 @@ class NewPasswordFormManager : public PasswordFormManagerInterface, ...@@ -276,9 +269,8 @@ class NewPasswordFormManager : public PasswordFormManagerInterface,
// and |not_best_matches_|). // and |not_best_matches_|).
std::vector<const autofill::PasswordForm*> GetAllMatches() const; std::vector<const autofill::PasswordForm*> GetAllMatches() const;
// Save/update |pending_credentials_| to the password store. If |old_password| // Save/update |pending_credentials_| to the password store.
// is provided, then the corresponding credentials are updated too. void SavePendingToStore(bool update);
void SavePendingToStore(bool update, const base::string16& old_password);
// The client which implements embedder-specific PasswordManager operations. // The client which implements embedder-specific PasswordManager operations.
PasswordManagerClient* client_; PasswordManagerClient* client_;
......
...@@ -243,10 +243,11 @@ void PasswordFormManager::PermanentlyBlacklist() { ...@@ -243,10 +243,11 @@ void PasswordFormManager::PermanentlyBlacklist() {
DCHECK(!client_->IsIncognito()); DCHECK(!client_->IsIncognito());
if (!new_blacklisted_) { if (!new_blacklisted_) {
new_blacklisted_ = std::make_unique<PasswordForm>(observed_form_); new_blacklisted_ = std::make_unique<PasswordForm>();
blacklisted_matches_.push_back(new_blacklisted_.get()); blacklisted_matches_.push_back(new_blacklisted_.get());
} }
form_saver_->PermanentlyBlacklist(new_blacklisted_.get()); *new_blacklisted_ = form_saver_->PermanentlyBlacklist(
PasswordStore::FormDigest(observed_form_));
} }
bool PasswordFormManager::IsNewLogin() const { bool PasswordFormManager::IsNewLogin() const {
...@@ -1035,19 +1036,26 @@ std::vector<PasswordForm> PasswordFormManager::FindOtherCredentialsToUpdate() ...@@ -1035,19 +1036,26 @@ std::vector<PasswordForm> PasswordFormManager::FindOtherCredentialsToUpdate()
} }
void PasswordFormManager::SavePendingToStore(bool update) { void PasswordFormManager::SavePendingToStore(bool update) {
std::vector<const autofill::PasswordForm*> matches;
for (const auto& match : best_matches_)
matches.push_back(match.second);
matches.insert(matches.end(), not_best_matches_.begin(),
not_best_matches_.end());
if (HasGeneratedPassword()) { if (HasGeneratedPassword()) {
generation_state_->CommitGeneratedPassword(pending_credentials_, generation_state_->CommitGeneratedPassword(pending_credentials_, matches,
best_matches_, nullptr); base::string16());
} else if (update) { } else if (update) {
std::vector<PasswordForm> credentials_to_update = base::string16 old_password;
FindOtherCredentialsToUpdate(); if (!pending_credentials_.IsFederatedCredential()) {
form_saver_->Update(pending_credentials_, best_matches_, auto updated_password_it =
&credentials_to_update, nullptr); best_matches_.find(pending_credentials_.username_value);
DCHECK(best_matches_.end() != updated_password_it);
old_password = updated_password_it->second->password_value;
}
form_saver_->Update(pending_credentials_, matches, old_password);
} else { } else {
std::vector<const autofill::PasswordForm*> best_matches; form_saver_->Save(pending_credentials_, matches, base::string16());
for (const auto& match : best_matches_)
best_matches.push_back(match.second);
form_saver_->Save(pending_credentials_, best_matches, base::string16());
} }
} }
......
...@@ -29,9 +29,9 @@ void PasswordGenerationState::PresaveGeneratedPassword(PasswordForm generated) { ...@@ -29,9 +29,9 @@ void PasswordGenerationState::PresaveGeneratedPassword(PasswordForm generated) {
DCHECK(!generated.password_value.empty()); DCHECK(!generated.password_value.empty());
generated.date_created = clock_->Now(); generated.date_created = clock_->Now();
if (presaved_) { if (presaved_) {
form_saver_->Update(generated, {} /* best_matches */, form_saver_->UpdateReplace(generated, {} /* matches */,
nullptr /* credentials_to_update */, base::string16() /* old_password */,
&presaved_.value() /* old_primary_key */); presaved_.value() /* old_primary_key */);
} else { } else {
form_saver_->Save(generated, {} /* matches */, form_saver_->Save(generated, {} /* matches */,
base::string16() /* old_password */); base::string16() /* old_password */);
...@@ -47,13 +47,13 @@ void PasswordGenerationState::PasswordNoLongerGenerated() { ...@@ -47,13 +47,13 @@ void PasswordGenerationState::PasswordNoLongerGenerated() {
void PasswordGenerationState::CommitGeneratedPassword( void PasswordGenerationState::CommitGeneratedPassword(
PasswordForm generated, PasswordForm generated,
const std::map<base::string16, const PasswordForm*>& best_matches, const std::vector<const autofill::PasswordForm*>& matches,
const std::vector<PasswordForm>* credentials_to_update) { const base::string16& old_password) {
DCHECK(presaved_); DCHECK(presaved_);
generated.preferred = true; generated.preferred = true;
generated.date_created = clock_->Now(); generated.date_created = clock_->Now();
form_saver_->Update(generated, best_matches, credentials_to_update, form_saver_->UpdateReplace(generated, matches, old_password,
&presaved_.value() /* old_primary_key */); presaved_.value() /* old_primary_key */);
} }
} // namespace password_manager } // namespace password_manager
...@@ -38,17 +38,12 @@ class PasswordGenerationState { ...@@ -38,17 +38,12 @@ class PasswordGenerationState {
// Signals that the user cancels password generation. // Signals that the user cancels password generation.
void PasswordNoLongerGenerated(); void PasswordNoLongerGenerated();
// Finish the generation flow by saving the final credential |generated| and // Finish the generation flow by saving the final credential |generated|.
// leaving the generation state. // |matches| and |old_password| have the same meaning as in FormSaver.
// |best_matches| constains possible passwords for the current site. They will
// be update according to the new preferred state.
// |credentials_to_update| are credentials for probably related domain that
// should be also updated.
void CommitGeneratedPassword( void CommitGeneratedPassword(
autofill::PasswordForm generated, autofill::PasswordForm generated,
const std::map<base::string16, const autofill::PasswordForm*>& const std::vector<const autofill::PasswordForm*>& matches,
best_matches, const base::string16& old_password);
const std::vector<autofill::PasswordForm>* credentials_to_update);
#if defined(UNIT_TEST) #if defined(UNIT_TEST)
void set_clock(std::unique_ptr<base::Clock> clock) { void set_clock(std::unique_ptr<base::Clock> clock) {
......
...@@ -44,6 +44,7 @@ PasswordForm CreateSavedPSL() { ...@@ -44,6 +44,7 @@ PasswordForm CreateSavedPSL() {
form.action = GURL("https://login.example.org"); form.action = GURL("https://login.example.org");
form.username_value = ASCIIToUTF16("old_username2"); form.username_value = ASCIIToUTF16("old_username2");
form.password_value = ASCIIToUTF16("passw0rd"); form.password_value = ASCIIToUTF16("passw0rd");
form.is_public_suffix_match = true;
return form; return form;
} }
...@@ -157,7 +158,7 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ReplaceTwice) { ...@@ -157,7 +158,7 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ReplaceTwice) {
// credential (as new) results in replacing the presaved password with the // credential (as new) results in replacing the presaved password with the
// pending one. // pending one.
TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenSaveAsNew) { TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenSaveAsNew) {
PasswordForm generated = CreateGenerated(); const PasswordForm generated = CreateGenerated();
EXPECT_CALL(store(), AddLogin(_)); EXPECT_CALL(store(), AddLogin(_));
state().PresaveGeneratedPassword(generated); state().PresaveGeneratedPassword(generated);
...@@ -170,8 +171,8 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenSaveAsNew) { ...@@ -170,8 +171,8 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenSaveAsNew) {
generated_with_date.date_created = base::Time::FromTimeT(kTime); generated_with_date.date_created = base::Time::FromTimeT(kTime);
EXPECT_CALL(store(), UpdateLoginWithPrimaryKey(generated_with_date, EXPECT_CALL(store(), UpdateLoginWithPrimaryKey(generated_with_date,
FormHasUniqueKey(generated))); FormHasUniqueKey(generated)));
state().CommitGeneratedPassword(pending, {} /* best_matches */, state().CommitGeneratedPassword(pending, {} /* matches */,
nullptr /* credentials_to_update */); base::string16() /* old_password */);
EXPECT_TRUE(state().HasGeneratedPassword()); EXPECT_TRUE(state().HasGeneratedPassword());
} }
...@@ -184,26 +185,50 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenUpdate) { ...@@ -184,26 +185,50 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenUpdate) {
EXPECT_CALL(store(), AddLogin(_)); EXPECT_CALL(store(), AddLogin(_));
state().PresaveGeneratedPassword(generated); state().PresaveGeneratedPassword(generated);
PasswordForm pending = generated; PasswordForm related_password = CreateSaved();
pending.username_value = ASCIIToUTF16("edited_username"); related_password.username_value = ASCIIToUTF16("username");
related_password.username_element = ASCIIToUTF16("username_field");
related_password.password_value = ASCIIToUTF16("old password");
PasswordForm old_saved = CreateSaved(); PasswordForm related_psl_password = CreateSavedPSL();
old_saved.preferred = false; related_psl_password.username_value = ASCIIToUTF16("username");
PasswordForm old_psl_saved = CreateSavedPSL(); related_psl_password.password_value = ASCIIToUTF16("old password");
old_psl_saved.password_value = pending.password_value;
std::vector<autofill::PasswordForm> credentials_to_update = {old_psl_saved}; PasswordForm unrelated_password = CreateSaved();
PasswordForm generated_with_date = pending; unrelated_password.preferred = true;
unrelated_password.username_value = ASCIIToUTF16("another username");
unrelated_password.password_value = ASCIIToUTF16("some password");
PasswordForm unrelated_psl_password = CreateSavedPSL();
unrelated_psl_password.preferred = true;
unrelated_psl_password.username_value = ASCIIToUTF16("another username");
unrelated_psl_password.password_value = ASCIIToUTF16("some password");
generated.username_value = ASCIIToUTF16("username");
PasswordForm generated_with_date = generated;
generated_with_date.date_created = base::Time::FromTimeT(kTime); generated_with_date.date_created = base::Time::FromTimeT(kTime);
EXPECT_CALL(store(), UpdateLoginWithPrimaryKey(generated_with_date, EXPECT_CALL(store(),
FormHasUniqueKey(generated))); UpdateLoginWithPrimaryKey(generated_with_date,
EXPECT_CALL(store(), UpdateLogin(old_saved)); FormHasUniqueKey(CreateGenerated())));
EXPECT_CALL(store(), UpdateLogin(old_psl_saved));
PasswordForm related_password_expected = related_password;
related_password_expected.password_value = generated.password_value;
EXPECT_CALL(store(), UpdateLogin(related_password_expected));
PasswordForm related_psl_password_expected = related_psl_password;
related_psl_password_expected.password_value = generated.password_value;
EXPECT_CALL(store(), UpdateLogin(related_psl_password_expected));
PasswordForm unrelated_password_expected = unrelated_password;
unrelated_password_expected.preferred = false;
EXPECT_CALL(store(), UpdateLogin(unrelated_password_expected));
old_saved.preferred = true;
state().CommitGeneratedPassword( state().CommitGeneratedPassword(
pending, {{old_saved.username_value, &old_saved}} /* best_matches */, generated,
&credentials_to_update); {&related_password, &related_psl_password, &unrelated_password,
&unrelated_psl_password} /* matches */,
ASCIIToUTF16("old password"));
EXPECT_TRUE(state().HasGeneratedPassword()); EXPECT_TRUE(state().HasGeneratedPassword());
} }
......
...@@ -6,6 +6,11 @@ ...@@ -6,6 +6,11 @@
namespace password_manager { namespace password_manager {
autofill::PasswordForm StubFormSaver::PermanentlyBlacklist(
PasswordStore::FormDigest digest) {
return autofill::PasswordForm();
}
std::unique_ptr<FormSaver> StubFormSaver::Clone() { std::unique_ptr<FormSaver> StubFormSaver::Clone() {
return nullptr; return nullptr;
} }
......
...@@ -18,15 +18,18 @@ class StubFormSaver : public FormSaver { ...@@ -18,15 +18,18 @@ class StubFormSaver : public FormSaver {
~StubFormSaver() override = default; ~StubFormSaver() override = default;
// FormSaver: // FormSaver:
void PermanentlyBlacklist(autofill::PasswordForm* observed) override {} autofill::PasswordForm PermanentlyBlacklist(
void Save(const autofill::PasswordForm& pending, PasswordStore::FormDigest digest) override;
void Save(autofill::PasswordForm pending,
const std::vector<const autofill::PasswordForm*>& matches, const std::vector<const autofill::PasswordForm*>& matches,
const base::string16& old_password) override {} const base::string16& old_password) override {}
void Update(const autofill::PasswordForm& pending, void Update(autofill::PasswordForm pending,
const std::map<base::string16, const autofill::PasswordForm*>& const std::vector<const autofill::PasswordForm*>& matches,
best_matches, const base::string16& old_password) override {}
const std::vector<autofill::PasswordForm>* credentials_to_update, void UpdateReplace(autofill::PasswordForm pending,
const autofill::PasswordForm* old_primary_key) override {} const std::vector<const autofill::PasswordForm*>& matches,
const base::string16& old_password,
const autofill::PasswordForm& old_unique_key) override {}
void Remove(const autofill::PasswordForm& form) override {} void Remove(const autofill::PasswordForm& form) override {}
std::unique_ptr<FormSaver> Clone() override; std::unique_ptr<FormSaver> Clone() override;
......
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