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 |