blob: 3295e01ebeebbddaf11dda2537c1273060b82f2c [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/password_update_delegate.h"
#include <memory>
#include <string>
#include <vector>
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/android/password_update_delegate.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/test_password_store.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using testing::ElementsAre;
using testing::Pair;
namespace {
constexpr char kExampleCom[] = "https://example.com/";
constexpr char kExampleOrg[] = "https://example.org/";
constexpr char kNewPass[] = "new pass";
constexpr char kNewUser[] = "new user";
constexpr char kPassword[] = "pass";
constexpr char kPassword2[] = "pass2";
constexpr char kUsername[] = "user";
constexpr char kUsername2[] = "user2";
std::vector<std::pair<std::string, std::string>> GetUsernamesAndPasswords(
const std::vector<autofill::PasswordForm>& forms) {
std::vector<std::pair<std::string, std::string>> result;
result.reserve(forms.size());
for (const auto& form : forms) {
result.emplace_back(base::UTF16ToUTF8(form.username_value),
base::UTF16ToUTF8(form.password_value));
}
return result;
}
autofill::PasswordForm MakeSavedForm(const GURL& origin,
base::StringPiece username,
base::StringPiece password) {
autofill::PasswordForm form;
form.origin = origin;
form.signon_realm = origin.GetOrigin().spec();
form.username_element = base::ASCIIToUTF16("Email");
form.username_value = base::ASCIIToUTF16(username);
form.password_element = base::ASCIIToUTF16("Passwd");
form.password_value = base::ASCIIToUTF16(password);
return form;
}
} // namespace
class PasswordUpdateDelegateTest : public testing::Test {
protected:
PasswordUpdateDelegateTest() {}
~PasswordUpdateDelegateTest() override {
store_->ShutdownOnUIThread();
task_environment_.RunUntilIdle();
}
std::unique_ptr<PasswordUpdateDelegate> CreateTestDelegate(
const GURL& origin,
base::StringPiece username,
base::StringPiece password) {
return std::make_unique<PasswordUpdateDelegate>(
&profile_, MakeSavedForm(origin, username, password));
}
const std::vector<autofill::PasswordForm>& GetStoredPasswordsForRealm(
base::StringPiece signon_realm) {
const auto& stored_passwords =
static_cast<const password_manager::TestPasswordStore&>(*store_)
.stored_passwords();
auto for_realm_it = stored_passwords.find(signon_realm);
return for_realm_it->second;
}
password_manager::PasswordStore* GetStore() { return store_.get(); }
void RunUntilIdle() { task_environment_.RunUntilIdle(); }
private:
content::BrowserTaskEnvironment task_environment_;
TestingProfile profile_;
scoped_refptr<password_manager::PasswordStore> store_ =
base::WrapRefCounted(static_cast<password_manager::PasswordStore*>(
PasswordStoreFactory::GetInstance()
->SetTestingFactoryAndUse(
&profile_,
base::BindRepeating(&password_manager::BuildPasswordStore<
content::BrowserContext,
password_manager::TestPasswordStore>))
.get()));
};
TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_EditPassword) {
GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
RunUntilIdle();
std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kUsername),
base::ASCIIToUTF16(kNewPass));
RunUntilIdle();
EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
ElementsAre(Pair(kUsername, kNewPass)));
}
TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_EditUsername) {
GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
RunUntilIdle();
std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kNewUser),
base::ASCIIToUTF16(kPassword));
RunUntilIdle();
EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
ElementsAre(Pair(kNewUser, kPassword)));
}
TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_EditUsernameAndPassword) {
GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
RunUntilIdle();
std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kNewUser),
base::ASCIIToUTF16(kNewPass));
RunUntilIdle();
EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
ElementsAre(Pair(kNewUser, kNewPass)));
}
TEST_F(PasswordUpdateDelegateTest,
EditSavedPassword_RejectSameUsernameForSameRealm) {
GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
GetStore()->AddLogin(
MakeSavedForm(GURL(kExampleCom), kUsername2, kPassword2));
RunUntilIdle();
std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kUsername2),
base::ASCIIToUTF16(kPassword));
RunUntilIdle();
EXPECT_THAT(
GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
ElementsAre(Pair(kUsername, kPassword), Pair(kUsername2, kPassword2)));
}
TEST_F(PasswordUpdateDelegateTest,
EditSavedPassword_DontRejectSameUsernameForDifferentRealm) {
GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
GetStore()->AddLogin(
MakeSavedForm(GURL(kExampleOrg), kUsername2, kPassword2));
RunUntilIdle();
std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kUsername2),
base::ASCIIToUTF16(kPassword2));
RunUntilIdle();
EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
ElementsAre(Pair(kUsername2, kPassword2)));
EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleOrg)),
ElementsAre(Pair(kUsername2, kPassword2)));
}
TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_UpdateDuplicates) {
GetStore()->AddLogin(MakeSavedForm(GURL(base::StrCat({kExampleCom, "pathA"})),
kUsername, kPassword));
GetStore()->AddLogin(MakeSavedForm(GURL(base::StrCat({kExampleCom, "pathB"})),
kUsername, kPassword));
RunUntilIdle();
std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kNewUser),
base::ASCIIToUTF16(kNewPass));
RunUntilIdle();
EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
ElementsAre(Pair(kNewUser, kNewPass), Pair(kNewUser, kNewPass)));
}