Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Unified Diff: components/password_manager/core/browser/form_saver_impl_unittest.cc

Issue 2090583003: Introduce password_manager::FormSaver (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/password_manager/core/browser/form_saver_impl_unittest.cc
diff --git a/components/password_manager/core/browser/form_saver_impl_unittest.cc b/components/password_manager/core/browser/form_saver_impl_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..556725c4632a625e7df33f1d2188198e5300f034
--- /dev/null
+++ b/components/password_manager/core/browser/form_saver_impl_unittest.cc
@@ -0,0 +1,504 @@
+// Copyright 2016 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 "components/password_manager/core/browser/form_saver_impl.h"
+
+#include <set>
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/mock_password_store.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using autofill::PasswordForm;
+using autofill::PasswordFormMap;
+using base::ASCIIToUTF16;
+using base::WrapUnique;
+using testing::_;
+using testing::DoAll;
+using testing::SaveArg;
+using testing::StrictMock;
+
+namespace password_manager {
+
+namespace {
+
+// Creates a dummy observed form with some basic arbitrary values.
+PasswordForm CreateObserved() {
+ PasswordForm form;
+ form.origin = GURL("https://example.in");
+ form.signon_realm = form.origin.spec();
+ form.action = GURL("https://login.example.org");
+ return form;
+}
+
+// Creates a dummy pending (for saving) form with some basic arbitrary values
+// and |username| and |password| values as specified.
+PasswordForm CreatePending(const char* username, const char* password) {
+ PasswordForm form = CreateObserved();
+ form.username_value = ASCIIToUTF16(username);
+ form.password_value = ASCIIToUTF16(password);
+ form.preferred = true;
+ return form;
+}
+
+} // namespace
+
+class FormSaverImplTest : public testing::Test {
+ public:
+ FormSaverImplTest()
+ : mock_store_(new StrictMock<MockPasswordStore>()),
+ form_saver_(mock_store_.get()) {}
+
+ ~FormSaverImplTest() override { mock_store_->ShutdownOnUIThread(); }
+
+ protected:
+ base::MessageLoop message_loop_; // For the MockPasswordStore.
+ scoped_refptr<StrictMock<MockPasswordStore>> mock_store_;
+ FormSaverImpl form_saver_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FormSaverImplTest);
+};
+
+// Check that blacklisting an observed form sets the right properties and calls
+// the PasswordStore.
+TEST_F(FormSaverImplTest, PermanentlyBlacklist) {
+ PasswordForm observed = CreateObserved();
+ PasswordForm saved;
+
+ observed.blacklisted_by_user = false;
+ observed.preferred = true;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ form_saver_.PermanentlyBlacklist(&observed);
+ EXPECT_TRUE(saved.blacklisted_by_user);
+ EXPECT_FALSE(saved.preferred);
+}
+
+// Check that saving the pending form as new adds the credential to the store
+// (rather than updating).
+TEST_F(FormSaverImplTest, Save_AsNew) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ form_saver_.Save(pending, PasswordFormMap(), nullptr);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+}
+
+// Check that saving the pending form as not new updates the store with the
+// credential.
+TEST_F(FormSaverImplTest, Save_Update) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ form_saver_.Update(pending, PasswordFormMap(), nullptr, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+}
+
+// Check that passing other credentials to update to the Save call results in
+// the store being updated with those credentials in addition to the pending
+// one.
+TEST_F(FormSaverImplTest, Save_UpdateAlsoOtherCredentials) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm related1 = pending;
+ related1.origin = GURL("https://other.example.ca");
+ related1.signon_realm = related1.origin.spec();
+ PasswordForm related2 = pending;
+ related2.origin = GURL("http://complete.example.net");
+ related2.signon_realm = related2.origin.spec();
+ std::vector<const autofill::PasswordForm*> credentials_to_update = {
+ &related1, &related2};
+ pending.password_value = ASCIIToUTF16("abcd");
+
+ PasswordForm saved[3];
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLogin(_))
+ .WillOnce(SaveArg<0>(&saved[0]))
+ .WillOnce(SaveArg<0>(&saved[1]))
+ .WillOnce(SaveArg<0>(&saved[2]));
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ form_saver_.Update(pending, PasswordFormMap(), &credentials_to_update,
+ nullptr);
+ std::set<GURL> different_origins;
+ for (const PasswordForm& form : saved) {
+ different_origins.insert(form.origin);
+ }
+ EXPECT_THAT(different_origins,
+ testing::UnorderedElementsAre(pending.origin, related1.origin,
+ related2.origin));
+}
+
+// Check that if the old primary key is supplied, the appropriate store method
+// for update is used.
+TEST_F(FormSaverImplTest, Save_UpdateWithPrimaryKey) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm old_key = pending;
+ old_key.username_value = ASCIIToUTF16("old username");
+ PasswordForm saved_new;
+ PasswordForm saved_old;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&saved_new), SaveArg<1>(&saved_old)));
+ form_saver_.Update(pending, PasswordFormMap(), nullptr, &old_key);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved_new.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved_new.password_value);
+ EXPECT_EQ(ASCIIToUTF16("old username"), saved_old.username_value);
+}
+
+// Check that the "preferred" bit of best matches is updated accordingly in the
+// store.
+TEST_F(FormSaverImplTest, Save_AndUpdatePreferredLoginState) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ pending.preferred = true;
+
+ // |best_matches| will contain two forms: one non-PSL matched with a username
+ // different from the pending one, and one PSL-matched with a username same
+ // as the pending one, both marked as "preferred". FormSaver should ignore
+ // the pending and PSL-matched one, but should update the non-PSL matched
+ // form (with different username) to no longer be preferred.
+ PasswordFormMap best_matches;
+ PasswordForm other = pending;
+ other.username_value = ASCIIToUTF16("othername");
+ best_matches[other.username_value] = WrapUnique(new PasswordForm(other));
+ PasswordForm psl_match = pending;
+ psl_match.is_public_suffix_match = true;
+ best_matches[psl_match.username_value] =
+ WrapUnique(new PasswordForm(psl_match));
+
+ PasswordForm saved;
+ PasswordForm updated;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).WillOnce(SaveArg<0>(&updated));
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ form_saver_.Save(pending, best_matches, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+ EXPECT_TRUE(saved.preferred);
+ EXPECT_FALSE(saved.is_public_suffix_match);
+ EXPECT_EQ(ASCIIToUTF16("othername"), updated.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), updated.password_value);
+ EXPECT_FALSE(updated.preferred);
+ EXPECT_FALSE(updated.is_public_suffix_match);
+}
+
+// Check that storing credentials with a non-empty username results in deleting
+// credentials with the same password but no username, if present in best
+// matches.
+TEST_F(FormSaverImplTest, Save_AndDeleteEmptyUsernameCredentials) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+
+ PasswordFormMap best_matches;
+ best_matches[pending.username_value] = WrapUnique(new PasswordForm(pending));
+ PasswordForm no_username = pending;
+ no_username.username_value.clear();
+ no_username.preferred = false;
+ best_matches[no_username.username_value] =
+ WrapUnique(new PasswordForm(no_username));
+
+ PasswordForm saved;
+ PasswordForm removed;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).WillOnce(SaveArg<0>(&removed));
+ form_saver_.Save(pending, best_matches, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+ EXPECT_TRUE(removed.username_value.empty());
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), removed.password_value);
+}
+
+// Check that storing credentials with a non-empty username does not result in
+// deleting credentials with a different password, even if they have no
+// username.
+TEST_F(FormSaverImplTest,
+ Save_AndDoNotDeleteEmptyUsernameCredentialsWithDifferentPassword) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+
+ PasswordFormMap best_matches;
+ best_matches[pending.username_value] = WrapUnique(new PasswordForm(pending));
+ PasswordForm no_username = pending;
+ no_username.username_value.clear();
+ no_username.preferred = false;
+ no_username.password_value = ASCIIToUTF16("abcd");
+ best_matches[no_username.username_value] =
+ WrapUnique(new PasswordForm(no_username));
+
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).Times(0);
+ form_saver_.Save(pending, best_matches, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+}
+
+// Check that if both "abc"/"pwd" and ""/"pwd" are both stored, and "abc"/"pwd"
+// is updated to "abc"/"def", then ""/"pwd" is not deleted.
+TEST_F(FormSaverImplTest,
+ Save_DoNotDeleteUsernamelessOnUpdatingPasswordWithUsername) {
+ PasswordForm pending = CreatePending("abc", "pwd");
+
+ PasswordFormMap best_matches;
+ best_matches[pending.username_value] = WrapUnique(new PasswordForm(pending));
+ PasswordForm no_username = pending;
+ no_username.username_value.clear();
+ no_username.preferred = false;
+ best_matches[no_username.username_value] =
+ WrapUnique(new PasswordForm(no_username));
+
+ pending.password_value = ASCIIToUTF16("def");
+
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).Times(0);
+ form_saver_.Save(pending, best_matches, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("abc"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("def"), saved.password_value);
+}
+
+// Check that if a credential without username is saved, and another credential
+// with the same password (and a non-empty username) is present in best matches,
+// nothing is deleted.
+TEST_F(FormSaverImplTest, Save_EmptyUsernameWillNotCauseDeletion) {
+ PasswordForm pending = CreatePending("", "wordToP4a55");
+
+ PasswordFormMap best_matches;
+ PasswordForm with_username = pending;
+ with_username.username_value = ASCIIToUTF16("nameofuser");
+ with_username.preferred = false;
+ best_matches[with_username.username_value] =
+ WrapUnique(new PasswordForm(with_username));
+
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).Times(0);
+ form_saver_.Save(pending, best_matches, nullptr);
+ EXPECT_TRUE(saved.username_value.empty());
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+}
+
+// Check that PSL-matched credentials in best matches are exempt from deletion,
+// even if they have an empty username and the same password as the pending
+// credential.
+TEST_F(FormSaverImplTest, Save_AndDoNotDeleteEmptyUsernamePSLCredentials) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+
+ PasswordFormMap best_matches;
+ best_matches[pending.username_value] = WrapUnique(new PasswordForm(pending));
+ PasswordForm no_username_psl = pending;
+ no_username_psl.username_value.clear();
+ no_username_psl.is_public_suffix_match = true;
+ best_matches[no_username_psl.username_value] =
+ WrapUnique(new PasswordForm(no_username_psl));
+
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).Times(0);
+ form_saver_.Save(pending, best_matches, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+}
+
+// Check that on storing a credential, other credentials with the same password
+// are not removed, as long as they have a non-empty username.
+TEST_F(FormSaverImplTest, Save_AndDoNotDeleteNonEmptyUsernameCredentials) {
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+
+ PasswordFormMap best_matches;
+ best_matches[pending.username_value] = WrapUnique(new PasswordForm(pending));
+ PasswordForm other_username = pending;
+ other_username.username_value = ASCIIToUTF16("other username");
+ other_username.preferred = false;
+ best_matches[other_username.username_value] =
+ WrapUnique(new PasswordForm(other_username));
+
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).Times(0);
+ form_saver_.Save(pending, best_matches, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+}
+
+// Check that presaving a password for the first time results in adding it.
+TEST_F(FormSaverImplTest, PresaveGeneratedPassword_New) {
+ PasswordForm generated = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm saved;
+
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ form_saver_.PresaveGeneratedPassword(generated);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved.password_value);
+}
+
+// Check that presaving a password for the second time results in updating it.
+TEST_F(FormSaverImplTest, PresaveGeneratedPassword_Replace) {
+ PasswordForm generated = CreatePending("nameofuser", "wordToP4a55");
+
+ EXPECT_CALL(*mock_store_, AddLogin(_));
+ form_saver_.PresaveGeneratedPassword(generated);
+
+ generated.password_value = ASCIIToUTF16("newgenpwd");
+ PasswordForm saved_new;
+ PasswordForm saved_old;
+ EXPECT_CALL(*mock_store_, AddLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&saved_new), SaveArg<1>(&saved_old)));
+ form_saver_.PresaveGeneratedPassword(generated);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved_old.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved_old.password_value);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved_new.username_value);
+ EXPECT_EQ(ASCIIToUTF16("newgenpwd"), saved_new.password_value);
+}
+
+// Check that presaving a password followed by a call to save a pending
+// credential (as new) results in replacing the presaved password with the
+// pending one.
+TEST_F(FormSaverImplTest, PresaveGeneratedPassword_ThenSaveAsNew) {
+ PasswordForm generated = CreatePending("generatedU", "generatedP");
+
+ EXPECT_CALL(*mock_store_, AddLogin(_));
+ form_saver_.PresaveGeneratedPassword(generated);
+
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm saved_new;
+ PasswordForm saved_old;
+ EXPECT_CALL(*mock_store_, AddLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&saved_new), SaveArg<1>(&saved_old)));
+ form_saver_.Save(pending, PasswordFormMap(), nullptr);
+ EXPECT_EQ(ASCIIToUTF16("generatedU"), saved_old.username_value);
+ EXPECT_EQ(ASCIIToUTF16("generatedP"), saved_old.password_value);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved_new.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved_new.password_value);
+}
+
+// Check that presaving a password followed by a call to save a pending
+// credential (as update) results in replacing the presaved password with the
+// pending one.
+TEST_F(FormSaverImplTest, PresaveGeneratedPassword_ThenUpdate) {
+ PasswordForm generated = CreatePending("generatedU", "generatedP");
+
+ EXPECT_CALL(*mock_store_, AddLogin(_));
+ form_saver_.PresaveGeneratedPassword(generated);
+
+ PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm saved_new;
+ PasswordForm saved_old;
+ EXPECT_CALL(*mock_store_, AddLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&saved_new), SaveArg<1>(&saved_old)));
+ form_saver_.Update(pending, PasswordFormMap(), nullptr, nullptr);
+ EXPECT_EQ(ASCIIToUTF16("generatedU"), saved_old.username_value);
+ EXPECT_EQ(ASCIIToUTF16("generatedP"), saved_old.password_value);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved_new.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved_new.password_value);
+}
+
+// Check that presaving a password for the third time results in updating it.
+TEST_F(FormSaverImplTest, PresaveGeneratedPassword_ReplaceTwice) {
+ PasswordForm generated = CreatePending("nameofuser", "wordToP4a55");
+
+ EXPECT_CALL(*mock_store_, AddLogin(_));
+ form_saver_.PresaveGeneratedPassword(generated);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _));
+ form_saver_.PresaveGeneratedPassword(generated);
+
+ generated.password_value = ASCIIToUTF16("newgenpwd");
+ PasswordForm saved_new;
+ PasswordForm saved_old;
+ EXPECT_CALL(*mock_store_, AddLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&saved_new), SaveArg<1>(&saved_old)));
+ form_saver_.PresaveGeneratedPassword(generated);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved_old.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), saved_old.password_value);
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), saved_new.username_value);
+ EXPECT_EQ(ASCIIToUTF16("newgenpwd"), saved_new.password_value);
+}
+
+// Check that removing a presaved password is a no-op if none was presaved.
+TEST_F(FormSaverImplTest, RemovePresavedPassword_NonePresaved) {
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).Times(0);
+ form_saver_.RemovePresavedPassword();
+}
+
+// Check that removing a presaved password removes the presaved password.
+TEST_F(FormSaverImplTest, RemovePresavedPassword) {
+ PasswordForm generated = CreatePending("nameofuser", "wordToP4a55");
+
+ EXPECT_CALL(*mock_store_, AddLogin(_));
+ form_saver_.PresaveGeneratedPassword(generated);
+
+ PasswordForm removed;
+ EXPECT_CALL(*mock_store_, RemoveLogin(_)).WillOnce(SaveArg<0>(&removed));
+ form_saver_.RemovePresavedPassword();
+ EXPECT_EQ(ASCIIToUTF16("nameofuser"), removed.username_value);
+ EXPECT_EQ(ASCIIToUTF16("wordToP4a55"), removed.password_value);
+}
+
+// Check that removing the presaved password and then presaving again results in
+// adding the second presaved password as new.
+TEST_F(FormSaverImplTest, RemovePresavedPassword_AndPresaveAgain) {
+ PasswordForm generated = CreatePending("nameofuser", "wordToP4a55");
+
+ EXPECT_CALL(*mock_store_, AddLogin(_));
+ form_saver_.PresaveGeneratedPassword(generated);
+
+ EXPECT_CALL(*mock_store_, RemoveLogin(_));
+ form_saver_.RemovePresavedPassword();
+
+ PasswordForm saved;
+ generated.username_value = ASCIIToUTF16("newgen");
+ generated.password_value = ASCIIToUTF16("newgenpwd");
+ EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
+ EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
+ EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
+ form_saver_.PresaveGeneratedPassword(generated);
+ EXPECT_EQ(ASCIIToUTF16("newgen"), saved.username_value);
+ EXPECT_EQ(ASCIIToUTF16("newgenpwd"), saved.password_value);
+}
+
+} // namespace password_manager

Powered by Google App Engine
This is Rietveld 408576698