blob: cc9370971bdb92fd776c95d959a0956d12a5c22a [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill/core/browser/personal_data_manager.h"
#include <stddef.h>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/containers/contains.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/uuid.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
#include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
#include "components/autofill/core/browser/data_model/credit_card_art_image.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/metrics/autofill_metrics.h"
#include "components/autofill/core/browser/personal_data_manager_test_base.h"
#include "components/autofill/core/browser/sync_utils.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/ui/label_formatter_utils.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/autofill/core/browser/ui/suggestion_selection.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
#include "components/signin/public/base/signin_switches.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/sync/base/user_selectable_type.h"
#include "components/sync/test/test_sync_service.h"
#include "components/version_info/version_info.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/image/image_unittest_util.h"
namespace autofill {
namespace {
using testing::ElementsAre;
using testing::Pointee;
using testing::UnorderedElementsAre;
constexpr char kGuid[] = "a21f010a-eac1-41fc-aee9-c06bbedfb292";
constexpr char kPrimaryAccountEmail[] = "syncuser@example.com";
constexpr char16_t kPrimaryAccountEmail16[] = u"syncuser@example.com";
constexpr char kAddressEntryIcon[] = "accountIcon";
enum UserMode { USER_MODE_NORMAL, USER_MODE_INCOGNITO };
const base::Time kArbitraryTime = base::Time::FromDoubleT(25);
const base::Time kSomeLaterTime = base::Time::FromDoubleT(1000);
const base::Time kMuchLaterTime = base::Time::FromDoubleT(5000);
ACTION_P(QuitMessageLoop, loop) {
loop->Quit();
}
class PersonalDataManagerMock : public PersonalDataManager {
public:
explicit PersonalDataManagerMock(const std::string& app_locale,
const std::string& variations_country_code)
: PersonalDataManager(app_locale, variations_country_code) {}
~PersonalDataManagerMock() override = default;
MOCK_METHOD(void,
FetchImagesForURLs,
((base::span<const GURL> updated_urls)),
(const override));
};
template <typename T>
bool CompareElements(T* a, T* b) {
return a->Compare(*b) < 0;
}
template <typename T>
bool ElementsEqual(T* a, T* b) {
return a->Compare(*b) == 0;
}
// Verifies that two vectors have the same elements (according to T::Compare)
// while ignoring order. This is useful because multiple profiles or credit
// cards that are added to the SQLite DB within the same second will be returned
// in GUID (aka random) order.
template <typename T>
void ExpectSameElements(const std::vector<T*>& expectations,
const std::vector<T*>& results) {
ASSERT_EQ(expectations.size(), results.size());
std::vector<T*> expectations_copy = expectations;
std::sort(expectations_copy.begin(), expectations_copy.end(),
CompareElements<T>);
std::vector<T*> results_copy = results;
std::sort(results_copy.begin(), results_copy.end(), CompareElements<T>);
EXPECT_EQ(
base::ranges::mismatch(results_copy, expectations_copy, ElementsEqual<T>)
.first,
results_copy.end());
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
std::vector<std::vector<Suggestion::Text>> ConstructLabelLineMatrix(
const std::vector<std::u16string>& parts) {
return {{Suggestion::Text(ConstructLabelLine(parts))}};
}
#endif
} // anonymous namespace
class PersonalDataManagerHelper : public PersonalDataManagerTestBase {
protected:
PersonalDataManagerHelper() = default;
virtual ~PersonalDataManagerHelper() {
if (personal_data_)
personal_data_->Shutdown();
personal_data_.reset();
}
void ResetPersonalDataManager(UserMode user_mode,
bool use_sync_transport_mode = false) {
if (personal_data_)
personal_data_->Shutdown();
personal_data_ = std::make_unique<PersonalDataManager>("EN", "US");
PersonalDataManagerTestBase::ResetPersonalDataManager(
user_mode == USER_MODE_INCOGNITO, use_sync_transport_mode,
personal_data_.get());
}
void ResetProfiles() {
std::vector<AutofillProfile> empty_profiles;
personal_data_->SetProfilesForAllSources(&empty_profiles);
WaitForOnPersonalDataChanged();
}
bool TurnOnSyncFeature() {
return PersonalDataManagerTestBase::TurnOnSyncFeature(personal_data_.get());
}
void SetUpReferenceProfile(const AutofillProfile& profile) {
ASSERT_EQ(0U, personal_data_->GetProfiles().size());
AddProfileToPersonalDataManager(profile);
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
}
AutofillProfile GetDefaultProfile() {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910",
false);
return profile;
}
// Adds three local cards to the |personal_data_|. The three cards are
// different: two are from different companies and the third doesn't have a
// number. All three have different owners and credit card number. This allows
// to test the suggestions based on name as well as on credit card number.
void SetUpReferenceLocalCreditCards() {
ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
credit_card0.set_use_count(3);
credit_card0.set_use_date(AutofillClock::Now() - base::Days(1));
personal_data_->AddCreditCard(credit_card0);
CreditCard credit_card1("1141084B-72D7-4B73-90CF-3D6AC154673B",
test::kEmptyOrigin);
credit_card1.set_use_count(300);
credit_card1.set_use_date(AutofillClock::Now() - base::Days(10));
test::SetCreditCardInfo(&credit_card1, "John Dillinger",
"4234567890123456" /* Visa */, "01", "2999", "1");
personal_data_->AddCreditCard(credit_card1);
CreditCard credit_card2("002149C1-EE28-4213-A3B9-DA243FFF021B",
test::kEmptyOrigin);
credit_card2.set_use_count(1);
credit_card2.set_use_date(AutofillClock::Now() - base::Days(1));
test::SetCreditCardInfo(&credit_card2, "Bonnie Parker",
"5105105105105100" /* Mastercard */, "12", "2999",
"1");
personal_data_->AddCreditCard(credit_card2);
WaitOnceForOnPersonalDataChanged();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
}
// Add 3 credit cards. One local, one masked, one full. Creates two masked
// cards on Linux, since full server cards are not supported.
void SetUpThreeCardTypes() {
EXPECT_EQ(0U, personal_data_->GetCreditCards().size());
CreditCard masked_server_card;
test::SetCreditCardInfo(&masked_server_card, "Elvis Presley",
"4234567890123456", // Visa
"04", "2999", "1");
masked_server_card.set_guid("00000000-0000-0000-0000-000000000007");
masked_server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
masked_server_card.set_server_id("masked_id");
masked_server_card.set_use_count(15);
personal_data_->AddFullServerCreditCard(masked_server_card);
WaitOnceForOnPersonalDataChanged();
ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
// Cards are automatically remasked on Linux since full server cards are not
// supported.
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
personal_data_->ResetFullServerCard(
personal_data_->GetCreditCards()[0]->guid());
#endif
CreditCard full_server_card;
test::SetCreditCardInfo(&full_server_card, "Buddy Holly",
"5187654321098765", // Mastercard
"10", "2998", "1");
full_server_card.set_guid("00000000-0000-0000-0000-000000000008");
full_server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
full_server_card.set_server_id("full_id");
full_server_card.set_use_count(10);
personal_data_->AddFullServerCreditCard(full_server_card);
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "Freddy Mercury",
"4234567890123463", // Visa
"08", "2999", "1");
local_card.set_guid("00000000-0000-0000-0000-000000000009");
local_card.set_record_type(CreditCard::LOCAL_CARD);
local_card.set_use_count(5);
personal_data_->AddCreditCard(local_card);
WaitOnceForOnPersonalDataChanged();
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
}
// Helper method to create a local card that was expired 400 days ago,
// and has not been used in last 400 days. This card is supposed to be
// deleted during a major version upgrade.
void CreateDeletableExpiredAndDisusedCreditCard() {
CreditCard credit_card1(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card1, "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"1999", "1");
credit_card1.set_use_date(AutofillClock::Now() - base::Days(400));
personal_data_->AddCreditCard(credit_card1);
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
}
// Helper method to create a profile that was last used 400 days ago.
// This profile is supposed to be deleted during a major version upgrade.
void CreateDeletableDisusedProfile() {
AutofillProfile profile0(test::GetFullProfile());
profile0.set_use_date(AutofillClock::Now() - base::Days(400));
AddProfileToPersonalDataManager(profile0);
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
}
AutofillTable* GetServerDataTable() {
return personal_data_->IsSyncFeatureEnabled()
? profile_autofill_table_.get()
: account_autofill_table_.get();
}
void AddProfileToPersonalDataManager(const AutofillProfile& profile) {
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
personal_data_->AddProfile(profile);
run_loop.Run();
}
void UpdateProfileOnPersonalDataManager(const AutofillProfile& profile) {
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
personal_data_->UpdateProfile(profile);
run_loop.Run();
}
void RemoveByGUIDFromPersonalDataManager(const std::string& guid) {
PersonalDataManagerTestBase::RemoveByGUIDFromPersonalDataManager(
guid, personal_data_.get());
}
void SetServerCards(const std::vector<CreditCard>& server_cards) {
test::SetServerCreditCards(GetServerDataTable(), server_cards);
}
void SetServerProfiles(const std::vector<AutofillProfile>& server_profiles) {
GetServerDataTable()->SetServerProfiles(server_profiles);
}
void SaveImportedProfileToPersonalDataManager(
const AutofillProfile& profile) {
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
personal_data_->SaveImportedProfile(profile);
run_loop.Run();
}
void ConvertWalletAddressesAndUpdateWalletCards() {
// Simulate new data is coming from sync which triggers a conversion of
// wallet addresses which in turn triggers a refresh.
personal_data_->AutofillMultipleChangedBySync();
WaitForOnPersonalDataChanged();
}
// Wallet address conversion is deprecated by the CONTACT_INFO type.
// TODO(crbug.com/1423319): Cleanup
bool IsWalletAddressConversionDeprecated() const {
return base::FeatureList::IsEnabled(
features::kAutofillAccountProfilesUnionView);
}
void AddOfferDataForTest(AutofillOfferData offer_data) {
personal_data_->AddOfferDataForTest(
std::make_unique<AutofillOfferData>(offer_data));
}
std::unique_ptr<PersonalDataManager> personal_data_;
};
class PersonalDataManagerTest : public PersonalDataManagerHelper,
public testing::Test {
protected:
void SetUp() override {
SetUpTest();
ResetPersonalDataManager(USER_MODE_NORMAL);
}
void TearDown() override { TearDownTest(); }
};
class PersonalDataManagerSyncTransportModeTest
: public PersonalDataManagerHelper,
public testing::Test {
protected:
void SetUp() override {
SetUpTest();
ResetPersonalDataManager(USER_MODE_NORMAL,
/*use_sync_transport_mode=*/true);
}
void TearDown() override { TearDownTest(); }
};
class PersonalDataManagerMockTest : public PersonalDataManagerTestBase,
public testing::Test {
protected:
void SetUp() override {
SetUpTest();
ResetPersonalDataManager(USER_MODE_NORMAL);
personal_data_->pref_service_->SetInteger(
prefs::kAutofillLastVersionDeduped, 0);
}
void TearDown() override {
if (personal_data_)
personal_data_->Shutdown();
personal_data_.reset();
TearDownTest();
}
void ResetPersonalDataManager(UserMode user_mode) {
if (personal_data_)
personal_data_->Shutdown();
personal_data_ =
std::make_unique<PersonalDataManagerMock>("en", std::string());
PersonalDataManagerTestBase::ResetPersonalDataManager(
user_mode == USER_MODE_INCOGNITO, /*use_sync_transport_mode=*/true,
personal_data_.get());
}
bool TurnOnSyncFeature() {
return PersonalDataManagerTestBase::TurnOnSyncFeature(personal_data_.get());
}
void StopTheDedupeProcess() {
personal_data_->pref_service_->SetInteger(
prefs::kAutofillLastVersionDeduped,
version_info::GetMajorVersionNumberAsInt());
}
void AddProfileToPersonalDataManager(const AutofillProfile& profile) {
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
personal_data_->AddProfile(profile);
run_loop.Run();
}
void UpdateProfileOnPersonalDataManager(const AutofillProfile& profile) {
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
personal_data_->UpdateProfile(profile);
run_loop.Run();
}
void RemoveByGUIDFromPersonalDataManager(const std::string& guid) {
PersonalDataManagerTestBase::RemoveByGUIDFromPersonalDataManager(
guid, personal_data_.get());
}
void AddOfferDataForTest(AutofillOfferData offer_data) {
personal_data_->AddOfferDataForTest(
std::make_unique<AutofillOfferData>(offer_data));
}
// Verifies the credit card art image fetching should begin.
void WaitForFetchImagesForUrls() {
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.Times(testing::AnyNumber());
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
EXPECT_CALL(*personal_data_, FetchImagesForURLs(testing::_))
.Times(1)
.WillOnce(QuitMessageLoop(&run_loop));
run_loop.Run();
}
std::unique_ptr<PersonalDataManagerMock> personal_data_;
};
TEST_F(PersonalDataManagerTest, AddProfile) {
// Add profile0 to the database.
AutofillProfile profile0(test::GetFullProfile());
profile0.SetRawInfo(EMAIL_ADDRESS, u"j@s.com");
AddProfileToPersonalDataManager(profile0);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify the addition.
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, profile0.Compare(*results1[0]));
// Add profile with identical values. Duplicates should not get saved.
AutofillProfile profile0a = profile0;
profile0a.set_guid(base::Uuid::GenerateRandomV4().AsLowercaseString());
AddProfileToPersonalDataManager(profile0a);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify the non-addition.
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, profile0.Compare(*results2[0]));
// New profile with different email.
AutofillProfile profile1 = profile0;
profile1.set_guid(base::Uuid::GenerateRandomV4().AsLowercaseString());
profile1.SetRawInfo(EMAIL_ADDRESS, u"john@smith.com");
// Add the different profile. This should save as a separate profile.
// Note that if this same profile was "merged" it would collapse to one
// profile with a multi-valued entry for email.
AddProfileToPersonalDataManager(profile1);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify the addition.
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
profiles.push_back(&profile1);
ExpectSameElements(profiles, personal_data_->GetProfiles());
}
// Tests that profiles with source `kAccount` and `kLocalOrSyncable` are loaded,
// and accessible via `GetProfiles()` and `GetProfilesFromSource()`.
// If duplicates exist across sources, they should be considered distinct.
TEST_F(PersonalDataManagerTest, GetProfiles) {
base::test::ScopedFeatureList feature;
feature.InitAndEnableFeature(features::kAutofillAccountProfilesUnionView);
AutofillProfile kAccountProfile = test::GetFullProfile();
kAccountProfile.set_source_for_testing(AutofillProfile::Source::kAccount);
AutofillProfile kAccountProfile2 = test::GetFullProfile2();
kAccountProfile2.set_source_for_testing(AutofillProfile::Source::kAccount);
AutofillProfile kLocalProfile = test::GetFullProfile();
AddProfileToPersonalDataManager(kAccountProfile);
AddProfileToPersonalDataManager(kAccountProfile2);
AddProfileToPersonalDataManager(kLocalProfile);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_THAT(
personal_data_->GetProfiles(),
UnorderedElementsAre(Pointee(kAccountProfile), Pointee(kAccountProfile2),
Pointee(kLocalProfile)));
EXPECT_THAT(
personal_data_->GetProfilesFromSource(AutofillProfile::Source::kAccount),
UnorderedElementsAre(Pointee(kAccountProfile),
Pointee(kAccountProfile2)));
EXPECT_THAT(personal_data_->GetProfilesFromSource(
AutofillProfile::Source::kLocalOrSyncable),
ElementsAre(Pointee(kLocalProfile)));
}
// Tests the different orderings in which profiles can be retrieved.
TEST_F(PersonalDataManagerTest, GetProfiles_Order) {
base::Time now = AutofillClock::Now();
AutofillProfile profile1 = test::GetFullProfile();
profile1.set_use_date(now - base::Hours(2));
profile1.set_use_count(1);
AutofillProfile profile2 = test::GetFullProfile2();
profile2.set_use_date(now);
profile2.set_use_count(1);
AutofillProfile profile3 = test::GetFullCanadianProfile();
profile3.set_use_date(now - base::Hours(1));
profile3.set_use_count(1234);
AddProfileToPersonalDataManager(profile1);
AddProfileToPersonalDataManager(profile2);
AddProfileToPersonalDataManager(profile3);
ResetPersonalDataManager(USER_MODE_NORMAL);
// kNone doesn't guarantee any order.
EXPECT_THAT(
personal_data_->GetProfiles(PersonalDataManager::ProfileOrder::kNone),
UnorderedElementsAre(Pointee(profile1), Pointee(profile2),
Pointee(profile3)));
// `profile3` is first, since it has a much higher use count.
// `profile1` and `profile2` have the same use count, so `profile2` with later
// use date is second.
EXPECT_THAT(personal_data_->GetProfiles(
PersonalDataManager::ProfileOrder::kHighestFrecencyDesc),
testing::ElementsAre(Pointee(profile3), Pointee(profile2),
Pointee(profile1)));
std::vector<AutofillProfile*> profiles = personal_data_->GetProfiles(
PersonalDataManager::ProfileOrder::kMostRecentlyUsedFirstDesc);
// Ordered by `use_date()`.
EXPECT_THAT(profiles,
testing::ElementsAre(Pointee(profile2), Pointee(profile3),
Pointee(profile1)));
// TODO(crbug.com/1420547): The modification date cannot be set beforehand,
// since it is overwritten by the database when the profile is initially
// stored. To test the ordering by modification date, update the `profiles`
// modification dates such that the order gets reversed. It is necessary to
// modify the PDM's profiles directly, since any modification involving the
// database will overwrite the modification date.
for (int i = 0; i < 3; i++) {
profiles[i]->set_modification_date(now - base::Hours(2 - i));
}
EXPECT_THAT(personal_data_->GetProfiles(
PersonalDataManager::ProfileOrder::kMostRecentlyModifiedDesc),
testing::ElementsAre(Pointee(profile1), Pointee(profile3),
Pointee(profile2)));
}
// Tests that `GetProfilesForSettings()` orders by descending modification
// dates.
// TODO(crbug.com/1420547): The modification date is set in AutofillTable.
// Setting it on the test profiles directly doesn't suffice.
TEST_F(PersonalDataManagerTest, GetProfilesForSettings) {
// Enable UnionView to test the ordering of profiles from different sources.
base::test::ScopedFeatureList feature;
feature.InitAndEnableFeature(features::kAutofillAccountProfilesUnionView);
TestAutofillClock test_clock;
AutofillProfile kAccountProfile = test::GetFullProfile();
kAccountProfile.set_source_for_testing(AutofillProfile::Source::kAccount);
AddProfileToPersonalDataManager(kAccountProfile);
AutofillProfile kLocalOrSyncableProfile = test::GetFullProfile2();
kLocalOrSyncableProfile.set_source_for_testing(
AutofillProfile::Source::kLocalOrSyncable);
test_clock.Advance(base::Minutes(123));
AddProfileToPersonalDataManager(kLocalOrSyncableProfile);
EXPECT_THAT(
personal_data_->GetProfilesForSettings(),
ElementsAre(Pointee(kLocalOrSyncableProfile), Pointee(kAccountProfile)));
}
// Tests that `SetProfilesForAllSources()` overwrites profiles with the correct
// source.
TEST_F(PersonalDataManagerTest, SetProfiles) {
base::test::ScopedFeatureList feature;
feature.InitAndEnableFeature(features::kAutofillAccountProfilesUnionView);
AutofillProfile kAccountProfile = test::GetFullProfile();
kAccountProfile.set_source_for_testing(AutofillProfile::Source::kAccount);
AutofillProfile kLocalProfile = test::GetFullProfile();
// Set `kAccount` profiles only.
std::vector<AutofillProfile> profiles = {kAccountProfile};
personal_data_->SetProfilesForAllSources(&profiles);
WaitForOnPersonalDataChanged();
EXPECT_THAT(
personal_data_->GetProfilesFromSource(AutofillProfile::Source::kAccount),
ElementsAre(Pointee(kAccountProfile)));
EXPECT_TRUE(
personal_data_
->GetProfilesFromSource(AutofillProfile::Source::kLocalOrSyncable)
.empty());
// Set `kLocalOrSyncable` profiles only. This clear the existing `kAccount`
// profiles
profiles = {kLocalProfile};
personal_data_->SetProfilesForAllSources(&profiles);
WaitForOnPersonalDataChanged();
EXPECT_TRUE(
personal_data_->GetProfilesFromSource(AutofillProfile::Source::kAccount)
.empty());
EXPECT_THAT(personal_data_->GetProfilesFromSource(
AutofillProfile::Source::kLocalOrSyncable),
ElementsAre(Pointee(kLocalProfile)));
// Set profiles of both sources.
profiles = {kAccountProfile, kLocalProfile};
personal_data_->SetProfilesForAllSources(&profiles);
WaitForOnPersonalDataChanged();
EXPECT_THAT(
personal_data_->GetProfilesFromSource(AutofillProfile::Source::kAccount),
ElementsAre(Pointee(kAccountProfile)));
EXPECT_THAT(personal_data_->GetProfilesFromSource(
AutofillProfile::Source::kLocalOrSyncable),
ElementsAre(Pointee(kLocalProfile)));
}
// Adding, updating, removing operations without waiting in between.
TEST_F(PersonalDataManagerTest, AddRemoveUpdateProfileSequence) {
AutofillProfile profile(test::GetFullProfile());
personal_data_->AddProfile(profile);
personal_data_->RemoveByGUID(profile.guid());
personal_data_->UpdateProfile(profile);
WaitForOnPersonalDataChanged();
auto profiles = personal_data_->GetProfiles();
ASSERT_EQ(0U, profiles.size());
personal_data_->AddProfile(profile);
personal_data_->RemoveByGUID(profile.guid());
personal_data_->RemoveByGUID(profile.guid());
WaitForOnPersonalDataChanged();
profiles = personal_data_->GetProfiles();
ASSERT_EQ(0U, profiles.size());
personal_data_->AddProfile(profile);
profile.SetRawInfo(EMAIL_ADDRESS, u"new@email.com");
personal_data_->UpdateProfile(profile);
WaitForOnPersonalDataChanged();
profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
EXPECT_EQ(profiles[0]->GetRawInfo(EMAIL_ADDRESS), u"new@email.com");
profile.SetRawInfo(EMAIL_ADDRESS, u"newer@email.com");
personal_data_->UpdateProfile(profile);
profile.SetRawInfo(EMAIL_ADDRESS, u"newest@email.com");
personal_data_->UpdateProfile(profile);
WaitForOnPersonalDataChanged();
profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
EXPECT_EQ(profiles[0]->GetRawInfo(EMAIL_ADDRESS), u"newest@email.com");
}
// Test that a new profile has its basic information set.
TEST_F(PersonalDataManagerTest, AddProfile_BasicInformation) {
// Create the test clock and set the time to a specific value.
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
// Add a profile to the database.
AutofillProfile profile(test::GetFullProfile());
profile.SetRawInfo(EMAIL_ADDRESS, u"j@s.com");
AddProfileToPersonalDataManager(profile);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify the addition.
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, profile.Compare(*results[0]));
// Make sure the use count and use date were set.
EXPECT_EQ(1U, results[0]->use_count());
EXPECT_EQ(kArbitraryTime, results[0]->use_date());
EXPECT_EQ(kArbitraryTime, results[0]->modification_date());
}
// Test filling profiles with unicode strings and crazy characters.
TEST_F(PersonalDataManagerTest, AddProfile_CrazyCharacters) {
std::vector<AutofillProfile> profiles;
AutofillProfile profile1;
profile1.SetRawInfo(NAME_FIRST,
u"\u0623\u0648\u0628\u0627\u0645\u0627 "
u"\u064a\u0639\u062a\u0630\u0631 "
u"\u0647\u0627\u062a\u0641\u064a\u0627 "
u"\u0644\u0645\u0648\u0638\u0641\u0629 "
u"\u0633\u0648\u062f\u0627\u0621 "
u"\u0627\u0633\u062a\u0642\u0627\u0644\u062a "
u"\u0628\u0633\u0628\u0628 "
u"\u062a\u0635\u0631\u064a\u062d\u0627\u062a "
u"\u0645\u062c\u062a\u0632\u0623\u0629");
profile1.SetRawInfo(NAME_MIDDLE, u"BANK\xcBERF\xc4LLE");
profile1.SetRawInfo(EMAIL_ADDRESS,
u"\uacbd\uc81c \ub274\uc2a4 "
u"\ub354\ubcf4\uae30@google.com");
profile1.SetRawInfo(ADDRESS_HOME_LINE1,
u"\uad6d\uc815\uc6d0\xb7\uac80\ucc30, "
u"\ub178\ubb34\ud604\uc815\ubd80 "
u"\ub300\ubd81\uc811\ucd09 \ub2f4\ub2f9 "
u"\uc778\uc0ac\ub4e4 \uc870\uc0ac");
profile1.SetRawInfo(ADDRESS_HOME_CITY,
u"\u653f\u5e9c\u4e0d\u6392\u9664\u7acb\u6cd5"
u"\u898f\u7ba1\u5c0e\u904a");
profile1.SetRawInfo(ADDRESS_HOME_ZIP, u"YOHO_54676");
profile1.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"861088828000");
profile1.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), u"India", "en-US");
profile1.FinalizeAfterImport();
profiles.push_back(profile1);
AutofillProfile profile2;
profile2.SetRawInfo(NAME_FIRST,
u"\u4e0a\u6d77\u5e02\u91d1\u5c71\u533a "
u"\u677e\u9690\u9547\u4ead\u67ab\u516c"
u"\u8def1915\u53f7");
profile2.SetRawInfo(NAME_LAST, u"aguantó");
profile2.SetRawInfo(ADDRESS_HOME_ZIP, u"HOME 94043");
profile2.FinalizeAfterImport();
profiles.push_back(profile2);
AutofillProfile profile3;
profile3.SetRawInfo(EMAIL_ADDRESS, u"sue@example.com");
profile3.SetRawInfo(COMPANY_NAME, u"Company X");
profile3.FinalizeAfterImport();
profiles.push_back(profile3);
AutofillProfile profile4;
profile4.SetRawInfo(NAME_FIRST, u"Joe 3254");
profile4.SetRawInfo(NAME_LAST, u"\u8bb0\u8d262\u5e74\u591a");
profile4.SetRawInfo(ADDRESS_HOME_ZIP,
u"\uff08\u90ae\u7f16\uff1a201504\uff09");
profile4.SetRawInfo(EMAIL_ADDRESS, u"télévision@example.com");
profile4.SetRawInfo(COMPANY_NAME,
u"\u0907\u0932\u0947\u0915\u093f\u091f\u094d"
u"\u0930\u0928\u093f\u0915\u094d\u0938, "
u"\u0905\u092a\u094b\u0932\u094b "
u"\u091f\u093e\u092f\u0930\u094d\u0938 "
u"\u0906\u0926\u093f");
profile4.FinalizeAfterImport();
profiles.push_back(profile4);
AutofillProfile profile5;
profile5.SetRawInfo(NAME_FIRST, u"Larry");
profile5.SetRawInfo(NAME_LAST,
u"\u0938\u094d\u091f\u093e\u0902\u092a "
u"\u0921\u094d\u092f\u0942\u091f\u0940");
profile5.SetRawInfo(ADDRESS_HOME_ZIP, u"111111111111110000GOOGLE");
profile5.SetRawInfo(EMAIL_ADDRESS, u"page@000000.com");
profile5.SetRawInfo(COMPANY_NAME, u"Google");
profile5.FinalizeAfterImport();
profiles.push_back(profile5);
AutofillProfile profile6;
profile6.SetRawInfo(NAME_FIRST,
u"\u4e0a\u6d77\u5e02\u91d1\u5c71\u533a "
u"\u677e\u9690\u9547\u4ead\u67ab\u516c"
u"\u8def1915\u53f7");
profile6.SetRawInfo(NAME_LAST,
u"\u0646\u062c\u0627\u0645\u064a\u0646\u0627 "
u"\u062f\u0639\u0645\u0647\u0627 "
u"\u0644\u0644\u0631\u0626\u064a\u0633 "
u"\u0627\u0644\u0633\u0648\u062f\u0627\u0646"
u"\u064a \u0639\u0645\u0631 "
u"\u0627\u0644\u0628\u0634\u064a\u0631");
profile6.SetRawInfo(ADDRESS_HOME_ZIP, u"HOME 94043");
profile6.FinalizeAfterImport();
profiles.push_back(profile6);
AutofillProfile profile7;
profile7.SetRawInfo(NAME_FIRST, u"&$%$$$ TESTO *&*&^&^& MOKO");
profile7.SetRawInfo(NAME_MIDDLE, u"WOHOOOO$$$$$$$$****");
profile7.SetRawInfo(EMAIL_ADDRESS, u"yuvu@example.com");
profile7.SetRawInfo(ADDRESS_HOME_LINE1, u"34544, anderson ST.(120230)");
profile7.SetRawInfo(ADDRESS_HOME_CITY, u"Sunnyvale");
profile7.SetRawInfo(ADDRESS_HOME_STATE, u"CA");
profile7.SetRawInfo(ADDRESS_HOME_ZIP, u"94086");
profile7.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"15466784565");
profile7.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), u"United States",
"en-US");
profile7.FinalizeAfterImport();
profiles.push_back(profile7);
personal_data_->SetProfilesForAllSources(&profiles);
WaitForOnPersonalDataChanged();
ASSERT_EQ(profiles.size(), personal_data_->GetProfiles().size());
for (size_t i = 0; i < profiles.size(); ++i) {
EXPECT_TRUE(base::Contains(profiles, *personal_data_->GetProfiles()[i]));
}
}
// Test filling in invalid values for profiles are saved as-is. Phone
// information entered into the settings UI is not validated or rejected except
// for duplicates.
TEST_F(PersonalDataManagerTest, AddProfile_Invalid) {
// First try profiles with invalid ZIP input.
AutofillProfile without_invalid;
without_invalid.SetRawInfo(NAME_FIRST, u"Will");
without_invalid.SetRawInfo(ADDRESS_HOME_CITY, u"Sunnyvale");
without_invalid.SetRawInfo(ADDRESS_HOME_STATE, u"CA");
without_invalid.SetRawInfo(ADDRESS_HOME_ZIP, u"my_zip");
without_invalid.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), u"United States",
"en-US");
AutofillProfile with_invalid = without_invalid;
with_invalid.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"Invalid_Phone_Number");
std::vector<AutofillProfile> profiles;
profiles.push_back(with_invalid);
personal_data_->SetProfilesForAllSources(&profiles);
WaitForOnPersonalDataChanged();
ASSERT_EQ(1u, personal_data_->GetProfiles().size());
AutofillProfile profile = *personal_data_->GetProfiles()[0];
ASSERT_NE(without_invalid.GetRawInfo(PHONE_HOME_WHOLE_NUMBER),
profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
}
// Tests that SaveImportedProfile sets the modification date on new profiles.
TEST_F(PersonalDataManagerTest, SaveImportedProfileSetModificationDate) {
AutofillProfile profile(test::GetFullProfile());
EXPECT_NE(base::Time(), profile.modification_date());
SaveImportedProfileToPersonalDataManager(profile);
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
EXPECT_GT(base::Milliseconds(2000),
AutofillClock::Now() - profiles[0]->modification_date());
}
TEST_F(PersonalDataManagerTest, AddUpdateRemoveProfiles) {
AutofillProfile profile0;
test::SetProfileInfo(&profile0, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", nullptr,
"Orlando", "FL", "32801", "US", "19482937549");
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
// Add two test profiles to the database.
AddProfileToPersonalDataManager(profile0);
AddProfileToPersonalDataManager(profile1);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
profiles.push_back(&profile1);
ExpectSameElements(profiles, personal_data_->GetProfiles());
// Update, remove, and add.
profile0.SetRawInfo(NAME_FIRST, u"John");
UpdateProfileOnPersonalDataManager(profile0);
RemoveByGUIDFromPersonalDataManager(profile1.guid());
AddProfileToPersonalDataManager(profile2);
profiles.clear();
profiles.push_back(&profile0);
profiles.push_back(&profile2);
ExpectSameElements(profiles, personal_data_->GetProfiles());
// Reset the PersonalDataManager. This tests that the personal data was saved
// to the web database, and that we can load the profiles from the web
// database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that we've loaded the profiles from the web database.
ExpectSameElements(profiles, personal_data_->GetProfiles());
}
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
// Test that setting the `kAutofillEnablePaymentsMandatoryReauth` pref works
// correctly.
TEST_F(PersonalDataManagerTest, AutofillPaymentMethodsMandatoryReauthEnabled) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
features::kAutofillEnablePaymentsMandatoryReauth);
EXPECT_FALSE(personal_data_->IsPaymentMethodsMandatoryReauthEnabled());
personal_data_->SetPaymentMethodsMandatoryReauthEnabled(true);
EXPECT_TRUE(personal_data_->IsPaymentMethodsMandatoryReauthEnabled());
personal_data_->SetPaymentMethodsMandatoryReauthEnabled(false);
EXPECT_FALSE(personal_data_->IsPaymentMethodsMandatoryReauthEnabled());
}
// Test that setting the `kAutofillEnablePaymentsMandatoryReauth` does not
// enable the feature when the flag is off.
TEST_F(PersonalDataManagerTest,
AutofillPaymentMethodsMandatoryReauthEnabled_FlagOff) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
features::kAutofillEnablePaymentsMandatoryReauth);
EXPECT_FALSE(personal_data_->IsPaymentMethodsMandatoryReauthEnabled());
personal_data_->SetPaymentMethodsMandatoryReauthEnabled(true);
EXPECT_FALSE(personal_data_->IsPaymentMethodsMandatoryReauthEnabled());
}
// Test that
// `PersonalDataManager::ShouldShowPaymentMethodsMandatoryReauthPromo()`
// only returns that we should show the promo when we are below the max counter
// limit for showing the promo.
TEST_F(
PersonalDataManagerTest,
ShouldShowPaymentMethodsMandatoryReauthPromo_MaxValueForPromoShownCounterReached) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
features::kAutofillEnablePaymentsMandatoryReauth);
for (int i = 0; i < prefs::kMaxValueForMandatoryReauthPromoShownCounter;
i++) {
EXPECT_TRUE(personal_data_->ShouldShowPaymentMethodsMandatoryReauthPromo());
personal_data_->IncrementPaymentMethodsMandatoryReauthPromoShownCounter();
}
EXPECT_FALSE(personal_data_->ShouldShowPaymentMethodsMandatoryReauthPromo());
}
// Test that
// `PersonalDataManager::ShouldShowPaymentMethodsMandatoryReauthPromo()`
// returns that we should not show the promo if the user has already made a
// decision.
TEST_F(
PersonalDataManagerTest,
ShouldShowPaymentMethodsMandatoryReauthPromo_UserHasMadeADecisionAlready) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
features::kAutofillEnablePaymentsMandatoryReauth);
personal_data_->SetPaymentMethodsMandatoryReauthEnabled(true);
EXPECT_FALSE(personal_data_->ShouldShowPaymentMethodsMandatoryReauthPromo());
}
// Test that
// `PersonalDataManager::ShouldShowPaymentMethodsMandatoryReauthPromo()`
// returns that we should not show the promo if the flag is off.
TEST_F(PersonalDataManagerTest,
ShouldShowPaymentMethodsMandatoryReauthPromo_FlagOff) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
features::kAutofillEnablePaymentsMandatoryReauth);
EXPECT_FALSE(personal_data_->ShouldShowPaymentMethodsMandatoryReauthPromo());
}
#endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
TEST_F(PersonalDataManagerTest, NoIBANsAddedIfDisabled) {
prefs::SetAutofillIBANEnabled(prefs_.get(), false);
personal_data_->AddIBAN(autofill::test::GetIBAN());
personal_data_->AddIBAN(autofill::test::GetIBAN2());
EXPECT_EQ(0U, personal_data_->GetLocalIBANs().size());
}
TEST_F(PersonalDataManagerTest, AddingIbanUpdatesPref) {
prefs::SetAutofillIBANEnabled(prefs_.get(), true);
// The pref should always start disabled.
ASSERT_FALSE(personal_data_->IsAutofillHasSeenIbanPrefEnabled());
IBAN iban = test::GetIBAN();
personal_data_->AddIBAN(iban);
WaitForOnPersonalDataChanged();
// Adding an IBAN permanently enables the pref.
EXPECT_TRUE(personal_data_->IsAutofillHasSeenIbanPrefEnabled());
}
TEST_F(PersonalDataManagerTest, AddUpdateRemoveIBANs) {
prefs::SetAutofillIBANEnabled(prefs_.get(), true);
IBAN iban0 = autofill::test::GetIBAN();
IBAN iban1 = autofill::test::GetIBAN2();
iban1.set_nickname(u"Nickname 1");
IBAN iban1_1 = iban1;
iban1_1.set_nickname(u"Nickname 1_1");
IBAN iban2 = autofill::test::GetIBANWithoutNickname();
iban2.set_nickname(u"Nickname 2");
// Add two test IBANs to the database. `iban1_1` has the same value
// as `iban1` but with a different nickname. Verify that only `iban1` is
// added.
personal_data_->AddIBAN(iban0);
WaitForOnPersonalDataChanged();
personal_data_->AddIBAN(iban1);
WaitForOnPersonalDataChanged();
personal_data_->AddIBAN(iban1_1);
std::vector<IBAN*> ibans;
ibans.push_back(&iban0);
ibans.push_back(&iban1);
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
// `iban1_2` has the same fields as `iban1_1`, verify that `iban1_2` is
// not added.
IBAN iban1_2 = iban1_1;
personal_data_->AddIBAN(iban1_1);
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
// Update IBAN0, remove IBAN1, and add IBAN2.
iban0.set_nickname(u"Nickname new 0");
iban0.SetRawInfo(IBAN_VALUE, u"GB98 MIDL 0700 9312 3456 78");
personal_data_->UpdateIBAN(iban0);
RemoveByGUIDFromPersonalDataManager(iban1.guid());
personal_data_->AddIBAN(iban2);
WaitForOnPersonalDataChanged();
ibans.clear();
ibans.push_back(&iban0);
ibans.push_back(&iban2);
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
// Verify that a duplicate IBAN should not be added.
IBAN iban0_dup = iban0;
personal_data_->AddIBAN(iban0_dup);
ibans.clear();
ibans.push_back(&iban0);
ibans.push_back(&iban2);
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
// Reset the PersonalDataManager. This tests that the personal data was saved
// to the web database, and that we can load the IBANs from the web database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that we've reloaded the IBANs from the web database.
ibans.clear();
ibans.push_back(&iban0);
ibans.push_back(&iban2);
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
}
// Ensure that new IBANs can be updated and saved via
// `OnAcceptedLocalIBANSave()`.
TEST_F(PersonalDataManagerTest, OnAcceptedLocalIBANSave) {
prefs::SetAutofillIBANEnabled(prefs_.get(), true);
// Start with a new IBAN.
IBAN iban0 = autofill::test::GetIBAN();
// Add the IBAN to the database.
personal_data_->OnAcceptedLocalIBANSave(iban0);
// Make sure everything is set up correctly.
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetLocalIBANs().size());
// Creates a new IBAN and call `OnAcceptedLocalIBANSave()` and verify that
// the new IBAN is saved.
IBAN iban1 = autofill::test::GetIBAN2();
personal_data_->OnAcceptedLocalIBANSave(iban1);
WaitForOnPersonalDataChanged();
// Expect that the new IBAN is added.
ASSERT_EQ(2U, personal_data_->GetLocalIBANs().size());
std::vector<IBAN*> ibans;
ibans.push_back(&iban0);
ibans.push_back(&iban1);
// Verify that we've loaded the IBAN from the web database.
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
// Creates a new `iban2` which has the same value as `iban0` but with
// different nickname and call `OnAcceptedLocalIBANSave()`.
IBAN iban2 = iban0;
iban2.set_nickname(u"Nickname 2");
personal_data_->OnAcceptedLocalIBANSave(iban2);
WaitForOnPersonalDataChanged();
// Updates the nickname for `iban1` and call `OnAcceptedLocalIBANSave()`.
iban1.set_nickname(u"Nickname 1 updated");
personal_data_->OnAcceptedLocalIBANSave(iban1);
WaitForOnPersonalDataChanged();
ibans.clear();
ibans.push_back(&iban1);
ibans.push_back(&iban2);
// Expect that the existing IBANs are updated.
ASSERT_EQ(2U, personal_data_->GetLocalIBANs().size());
// Verify that we've loaded the IBANs from the web database.
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
// Call `OnAcceptedLocalIBANSave()` with the same iban1, verify that nothing
// changes.
personal_data_->OnAcceptedLocalIBANSave(iban1);
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
// Reset the PersonalDataManager. This tests that the IBANs are persisted
// in the local web database even if the browser is re-loaded, ensuring that
// the user can load the IBANs from the local web database on browser startup.
ResetPersonalDataManager(USER_MODE_NORMAL);
ExpectSameElements(ibans, personal_data_->GetLocalIBANs());
}
// Ensure that new IBAN cannot be updated nor saved via
// `OnAcceptedLocalIBANSave()` if `is_off_the_record_` is true.
TEST_F(PersonalDataManagerTest, OnAcceptedLocalIBANSave_IsOffTheRecordTrue) {
personal_data_->set_is_off_the_record_for_testing(true);
prefs::SetAutofillIBANEnabled(prefs_.get(), true);
// Start with a new IBAN and add the IBAN to the database.
personal_data_->AddIBAN(autofill::test::GetIBAN());
// Verify the new IBAN is not saved.
EXPECT_TRUE(personal_data_->GetLocalIBANs().empty());
// Creates a new IBAN and call `OnAcceptedLocalIBANSave()` and verify that
// the new IBAN is not saved.
IBAN iban1 = autofill::test::GetIBAN2();
personal_data_->OnAcceptedLocalIBANSave(iban1);
EXPECT_TRUE(personal_data_->GetLocalIBANs().empty());
// Updates the nickname for `iban1` and call `OnAcceptedLocalIBANSave()`,
// verify that nothing happens.
iban1.set_nickname(u"Nickname 0 updated");
personal_data_->OnAcceptedLocalIBANSave(iban1);
EXPECT_TRUE(personal_data_->GetLocalIBANs().empty());
}
TEST_F(PersonalDataManagerTest, AddUpdateRemoveCreditCards) {
CreditCard credit_card0(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card0, "John Dillinger",
"4234567890123456" /* Visa */, "01", "2999", "1");
credit_card0.SetNickname(u"card zero");
CreditCard credit_card1(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card1, "Bonnie Parker",
"5105105105105100" /* Mastercard */, "12", "2999",
"1");
CreditCard credit_card2(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card2, "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
credit_card2.SetNickname(u"card two");
// Add two test credit cards to the database.
personal_data_->AddCreditCard(credit_card0);
personal_data_->AddCreditCard(credit_card1);
WaitForOnPersonalDataChanged();
std::vector<CreditCard*> cards;
cards.push_back(&credit_card0);
cards.push_back(&credit_card1);
ExpectSameElements(cards, personal_data_->GetCreditCards());
// Update, remove, and add.
credit_card0.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Joe");
credit_card0.SetNickname(u"new card zero");
personal_data_->UpdateCreditCard(credit_card0);
RemoveByGUIDFromPersonalDataManager(credit_card1.guid());
personal_data_->AddCreditCard(credit_card2);
WaitForOnPersonalDataChanged();
cards.clear();
cards.push_back(&credit_card0);
cards.push_back(&credit_card2);
ExpectSameElements(cards, personal_data_->GetCreditCards());
// Reset the PersonalDataManager. This tests that the personal data was saved
// to the web database, and that we can load the credit cards from the web
// database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that we've loaded the credit cards from the web database.
cards.clear();
cards.push_back(&credit_card0);
cards.push_back(&credit_card2);
ExpectSameElements(cards, personal_data_->GetCreditCards());
// Add a full server card.
CreditCard credit_card3(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card3, "Jane Doe",
"4111111111111111" /* Visa */, "04", "2999", "1");
credit_card3.set_record_type(CreditCard::FULL_SERVER_CARD);
credit_card3.set_server_id("server_id");
personal_data_->AddFullServerCreditCard(credit_card3);
WaitForOnPersonalDataChanged();
cards.push_back(&credit_card3);
ExpectSameElements(cards, personal_data_->GetCreditCards());
// Must not add a duplicate server card with same GUID.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(0);
personal_data_->AddFullServerCreditCard(credit_card3);
ExpectSameElements(cards, personal_data_->GetCreditCards());
// Must not add a duplicate card with same contents as another server card.
CreditCard duplicate_server_card(credit_card3);
duplicate_server_card.set_guid(
base::Uuid::GenerateRandomV4().AsLowercaseString());
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(0);
personal_data_->AddFullServerCreditCard(duplicate_server_card);
ExpectSameElements(cards, personal_data_->GetCreditCards());
}
// Test that a new credit card has its basic information set.
TEST_F(PersonalDataManagerTest, AddCreditCard_BasicInformation) {
// Create the test clock and set the time to a specific value.
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
// Add a credit card to the database.
CreditCard credit_card(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card, "John Dillinger",
"4234567890123456" /* Visa */, "01", "2999", "1");
personal_data_->AddCreditCard(credit_card);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify the addition.
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, credit_card.Compare(*results[0]));
// Make sure the use count and use date were set.
EXPECT_EQ(1U, results[0]->use_count());
EXPECT_EQ(kArbitraryTime, results[0]->use_date());
EXPECT_EQ(kArbitraryTime, results[0]->modification_date());
}
// Test filling credit cards with unicode strings and crazy characters.
TEST_F(PersonalDataManagerTest, AddCreditCard_CrazyCharacters) {
std::vector<CreditCard> cards;
CreditCard card1;
card1.SetRawInfo(CREDIT_CARD_NAME_FULL,
u"\u751f\u6d3b\u5f88\u6709\u89c4\u5f8b "
u"\u4ee5\u73a9\u4e3a\u4e3b");
card1.SetRawInfo(CREDIT_CARD_NUMBER, u"6011111111111117");
card1.SetRawInfo(CREDIT_CARD_EXP_MONTH, u"12");
card1.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2011");
cards.push_back(card1);
CreditCard card2;
card2.SetRawInfo(CREDIT_CARD_NAME_FULL, u"John Williams");
card2.SetRawInfo(CREDIT_CARD_NUMBER, u"WokoAwesome12345");
card2.SetRawInfo(CREDIT_CARD_EXP_MONTH, u"10");
card2.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2015");
cards.push_back(card2);
CreditCard card3;
card3.SetRawInfo(CREDIT_CARD_NAME_FULL,
u"\u0623\u062d\u0645\u062f\u064a "
u"\u0646\u062c\u0627\u062f "
u"\u0644\u0645\u062d\u0627\u0648\u0644\u0647 "
u"\u0627\u063a\u062a\u064a\u0627\u0644 "
u"\u0641\u064a \u0645\u062f\u064a\u0646\u0629 "
u"\u0647\u0645\u062f\u0627\u0646 ");
card3.SetRawInfo(CREDIT_CARD_NUMBER,
u"\u092a\u0941\u0928\u0930\u094d\u091c\u0940"
u"\u0935\u093f\u0924 \u0939\u094b\u0917\u093e "
u"\u0928\u093e\u0932\u0902\u0926\u093e");
card3.SetRawInfo(CREDIT_CARD_EXP_MONTH, u"10");
card3.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2015");
cards.push_back(card3);
CreditCard card4;
card4.SetRawInfo(CREDIT_CARD_NAME_FULL,
u"\u039d\u03ad\u03b5\u03c2 "
u"\u03c3\u03c5\u03b3\u03c7\u03c9\u03bd\u03b5"
u"\u03cd\u03c3\u03b5\u03b9\u03c2 "
u"\u03ba\u03b1\u03b9 "
u"\u03ba\u03b1\u03c4\u03b1\u03c1\u03b3\u03ae"
u"\u03c3\u03b5\u03b9\u03c2");
card4.SetRawInfo(CREDIT_CARD_NUMBER, u"00000000000000000000000");
card4.SetRawInfo(CREDIT_CARD_EXP_MONTH, u"01");
card4.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2016");
cards.push_back(card4);
personal_data_->SetCreditCards(&cards);
WaitForOnPersonalDataChanged();
ASSERT_EQ(cards.size(), personal_data_->GetCreditCards().size());
for (size_t i = 0; i < cards.size(); ++i) {
EXPECT_TRUE(base::Contains(cards, *personal_data_->GetCreditCards()[i]));
}
}
// Test invalid credit card numbers typed in settings UI should be saved as-is.
TEST_F(PersonalDataManagerTest, AddCreditCard_Invalid) {
CreditCard card;
card.SetRawInfo(CREDIT_CARD_NUMBER, u"Not_0123-5Checked");
std::vector<CreditCard> cards;
cards.push_back(card);
personal_data_->SetCreditCards(&cards);
ASSERT_EQ(1u, personal_data_->GetCreditCards().size());
ASSERT_EQ(card, *personal_data_->GetCreditCards()[0]);
}
TEST_F(PersonalDataManagerTest, GetCreditCardByServerId) {
CreditCard card = test::GetFullServerCard();
card.set_server_id("server id");
personal_data_->AddFullServerCreditCard(card);
WaitForOnPersonalDataChanged();
ASSERT_EQ(1u, personal_data_->GetCreditCards().size());
EXPECT_TRUE(personal_data_->GetCreditCardByServerId("server id"));
EXPECT_FALSE(personal_data_->GetCreditCardByServerId("non-existing id"));
}
#if !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, AddAndGetCreditCardArtImage) {
gfx::Image expected_image = gfx::test::CreateImage(32, 20);
std::unique_ptr<CreditCardArtImage> credit_card_art_image =
std::make_unique<CreditCardArtImage>(GURL("https://www.example.com"),
expected_image);
std::vector<std::unique_ptr<CreditCardArtImage>> images;
images.push_back(std::move(credit_card_art_image));
personal_data_->OnCardArtImagesFetched(std::move(images));
gfx::Image* actual_image = personal_data_->GetCreditCardArtImageForUrl(
GURL("https://www.example.com"));
ASSERT_TRUE(actual_image);
EXPECT_TRUE(gfx::test::AreImagesEqual(expected_image, *actual_image));
// TODO(crbug.com/1284788): Look into integrating with PersonalDataManagerMock
// and checking that PersonalDataManager::FetchImagesForUrls() does not get
// triggered when PersonalDataManager::GetCachedCardArtImageForUrl() is
// called.
gfx::Image* cached_image = personal_data_->GetCachedCardArtImageForUrl(
GURL("https://www.example.com"));
ASSERT_TRUE(cached_image);
EXPECT_TRUE(gfx::test::AreImagesEqual(expected_image, *cached_image));
}
TEST_F(PersonalDataManagerMockTest, ProcessCardArtUrlChanges) {
CreditCard card = test::GetFullServerCard();
card.set_server_id("card_server_id");
personal_data_->AddFullServerCreditCard(card);
WaitForOnPersonalDataChanged();
card.set_server_id("card_server_id");
card.set_card_art_url(GURL("https://www.example.com/card1"));
std::vector<GURL> updated_urls;
updated_urls.emplace_back(GURL("https://www.example.com/card1"));
personal_data_->AddFullServerCreditCard(card);
WaitForFetchImagesForUrls();
card.set_card_art_url(GURL("https://www.example.com/card2"));
updated_urls.clear();
updated_urls.emplace_back(GURL("https://www.example.com/card2"));
personal_data_->AddFullServerCreditCard(card);
WaitForFetchImagesForUrls();
}
#endif
TEST_F(PersonalDataManagerTest, UpdateUnverifiedCreditCards) {
// Start with unverified data.
CreditCard credit_card = test::GetCreditCard();
EXPECT_FALSE(credit_card.IsVerified());
// Add the data to the database.
personal_data_->AddCreditCard(credit_card);
WaitForOnPersonalDataChanged();
EXPECT_THAT(personal_data_->GetCreditCards(),
testing::UnorderedElementsAre(Pointee(credit_card)));
// Try to update with just the origin changed.
CreditCard original_credit_card(credit_card);
credit_card.set_origin(kSettingsOrigin);
EXPECT_TRUE(credit_card.IsVerified());
personal_data_->UpdateCreditCard(credit_card);
// Credit Card origin should not be overwritten.
EXPECT_THAT(personal_data_->GetCreditCards(),
testing::UnorderedElementsAre(Pointee(original_credit_card)));
// Try to update with data changed as well.
credit_card.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Joe");
personal_data_->UpdateCreditCard(credit_card);
WaitForOnPersonalDataChanged();
EXPECT_THAT(personal_data_->GetCreditCards(),
testing::UnorderedElementsAre(Pointee(credit_card)));
}
// Test that ensure local data is not lost on sign-in.
// Clearing/changing the primary account is not supported on CrOS.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PersonalDataManagerTest, KeepExistingLocalDataOnSignIn) {
// Sign out.
identity_test_env_.ClearPrimaryAccount();
sync_service_.SetAccountInfo(CoreAccountInfo());
EXPECT_EQ(AutofillSyncSigninState::kSignedOut,
personal_data_->GetSyncSigninState());
EXPECT_EQ(0U, personal_data_->GetCreditCards().size());
// Add local card.
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "Freddy Mercury",
"4234567890123463", // Visa
"08", "2999", "1");
local_card.set_guid("00000000-0000-0000-0000-000000000009");
local_card.set_record_type(CreditCard::LOCAL_CARD);
local_card.set_use_count(5);
personal_data_->AddCreditCard(local_card);
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
// Sign in.
identity_test_env_.MakePrimaryAccountAvailable("test@gmail.com",
signin::ConsentLevel::kSync);
sync_service_.SetAccountInfo(
identity_test_env_.identity_manager()->GetPrimaryAccountInfo(
signin::ConsentLevel::kSync));
sync_service_.SetHasSyncConsent(true);
sync_service_.GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false,
/*types=*/{syncer::UserSelectableType::kAutofill});
EXPECT_EQ(AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled,
personal_data_->GetSyncSigninState());
ASSERT_TRUE(TurnOnSyncFeature());
// Check saved local card should be not lost.
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
EXPECT_EQ(0, local_card.Compare(*personal_data_->GetCreditCards()[0]));
}
#endif
TEST_F(PersonalDataManagerTest, AddProfilesAndCreditCards) {
AutofillProfile profile0;
test::SetProfileInfo(&profile0, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", nullptr,
"Orlando", "FL", "32801", "US", "19482937549");
CreditCard credit_card0(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card0, "John Dillinger",
"4234567890123456" /* Visa */, "01", "2999", "1");
CreditCard credit_card1(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card1, "Bonnie Parker",
"5105105105105100" /* Mastercard */, "12", "2999",
"1");
// Add two test profiles to the database.
AddProfileToPersonalDataManager(profile0);
AddProfileToPersonalDataManager(profile1);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
profiles.push_back(&profile1);
ExpectSameElements(profiles, personal_data_->GetProfiles());
// Add two test credit cards to the database.
personal_data_->AddCreditCard(credit_card0);
personal_data_->AddCreditCard(credit_card1);
WaitForOnPersonalDataChanged();
std::vector<CreditCard*> cards;
cards.push_back(&credit_card0);
cards.push_back(&credit_card1);
ExpectSameElements(cards, personal_data_->GetCreditCards());
// Determine uniqueness by inserting all of the GUIDs into a set and verifying
// the size of the set matches the number of GUIDs.
std::set<std::string> guids;
guids.insert(profile0.guid());
guids.insert(profile1.guid());
guids.insert(credit_card0.guid());
guids.insert(credit_card1.guid());
EXPECT_EQ(4U, guids.size());
}
// Test for http://crbug.com/50047. Makes sure that guids are populated
// correctly on load.
TEST_F(PersonalDataManagerTest, PopulateUniqueIDsOnLoad) {
AutofillProfile profile0;
test::SetProfileInfo(&profile0, "y", "", "", "", "", "", "", "", "", "", "",
"");
// Add the profile0 to the db.
AddProfileToPersonalDataManager(profile0);
// Verify that we've loaded the profiles from the web database.
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, profile0.Compare(*results2[0]));
// Add a new profile.
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "z", "", "", "", "", "", "", "", "", "", "",
"");
AddProfileToPersonalDataManager(profile1);
// Make sure the two profiles have different GUIDs, both valid.
const std::vector<AutofillProfile*>& results3 = personal_data_->GetProfiles();
ASSERT_EQ(2U, results3.size());
EXPECT_NE(results3[0]->guid(), results3[1]->guid());
EXPECT_TRUE(base::Uuid::ParseCaseInsensitive(results3[0]->guid()).is_valid());
EXPECT_TRUE(base::Uuid::ParseCaseInsensitive(results3[1]->guid()).is_valid());
}
TEST_F(PersonalDataManagerTest, SetUniqueCreditCardLabels) {
CreditCard credit_card0(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
credit_card0.SetRawInfo(CREDIT_CARD_NAME_FULL, u"John");
CreditCard credit_card1(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
credit_card1.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Paul");
CreditCard credit_card2(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
credit_card2.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Ringo");
CreditCard credit_card3(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
credit_card3.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Other");
CreditCard credit_card4(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
credit_card4.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Ozzy");
CreditCard credit_card5(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
credit_card5.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Dio");
// Add the test credit cards to the database.
personal_data_->AddCreditCard(credit_card0);
personal_data_->AddCreditCard(credit_card1);
personal_data_->AddCreditCard(credit_card2);
personal_data_->AddCreditCard(credit_card3);
personal_data_->AddCreditCard(credit_card4);
personal_data_->AddCreditCard(credit_card5);
// Reset the PersonalDataManager. This tests that the personal data was saved
// to the web database, and that we can load the credit cards from the web
// database.
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<CreditCard*> cards;
cards.push_back(&credit_card0);
cards.push_back(&credit_card1);
cards.push_back(&credit_card2);
cards.push_back(&credit_card3);
cards.push_back(&credit_card4);
cards.push_back(&credit_card5);
ExpectSameElements(cards, personal_data_->GetCreditCards());
}
TEST_F(PersonalDataManagerTest, SetEmptyProfile) {
AutofillProfile profile0;
test::SetProfileInfo(&profile0, "", "", "", "", "", "", "", "", "", "", "",
"");
// Add the empty profile to the database.
AddProfileToPersonalDataManager(profile0);
// Reset the PersonalDataManager. This tests that the personal data was saved
// to the web database, and that we can load the profiles from the web
// database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that we've loaded the profiles from the web database.
ASSERT_EQ(0U, personal_data_->GetProfiles().size());
}
TEST_F(PersonalDataManagerTest, SetEmptyCreditCard) {
CreditCard credit_card0(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card0, "", "", "", "", "");
// Add the empty credit card to the database.
personal_data_->AddCreditCard(credit_card0);
// Note: no refresh here.
// Reset the PersonalDataManager. This tests that the personal data was saved
// to the web database, and that we can load the credit cards from the web
// database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that we've loaded the credit cards from the web database.
ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
}
TEST_F(PersonalDataManagerTest, Refresh) {
AutofillProfile profile0;
test::SetProfileInfo(&profile0, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", nullptr,
"Orlando", "FL", "32801", "US", "19482937549");
// Add the test profiles to the database.
AddProfileToPersonalDataManager(profile0);
AddProfileToPersonalDataManager(profile1);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
profiles.push_back(&profile1);
ExpectSameElements(profiles, personal_data_->GetProfiles());
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
profile_database_service_->AddAutofillProfile(profile2);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
profiles.clear();
profiles.push_back(&profile0);
profiles.push_back(&profile1);
profiles.push_back(&profile2);
ExpectSameElements(profiles, personal_data_->GetProfiles());
profile_database_service_->RemoveAutofillProfile(
profile1.guid(), AutofillProfile::Source::kLocalOrSyncable);
profile_database_service_->RemoveAutofillProfile(
profile2.guid(), AutofillProfile::Source::kLocalOrSyncable);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
auto results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(profile0, *results[0]);
profile0.SetRawInfo(NAME_FIRST, u"Mar");
profile_database_service_->UpdateAutofillProfile(profile0);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(profile0, *results[0]);
}
// Ensure that verified credit cards can be saved via
// OnAcceptedLocalCreditCardSave.
TEST_F(PersonalDataManagerTest, OnAcceptedLocalCreditCardSaveWithVerifiedData) {
// Start with a verified credit card.
CreditCard credit_card(base::Uuid::GenerateRandomV4().AsLowercaseString(),
kSettingsOrigin);
test::SetCreditCardInfo(&credit_card, "Biggie Smalls",
"4111 1111 1111 1111" /* Visa */, "01", "2999", "");
EXPECT_TRUE(credit_card.IsVerified());
// Add the credit card to the database.
personal_data_->AddCreditCard(credit_card);
// Make sure everything is set up correctly.
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
CreditCard new_verified_card = credit_card;
new_verified_card.set_guid(
base::Uuid::GenerateRandomV4().AsLowercaseString());
new_verified_card.SetRawInfo(CREDIT_CARD_NAME_FULL, u"B. Small");
EXPECT_TRUE(new_verified_card.IsVerified());
personal_data_->OnAcceptedLocalCreditCardSave(new_verified_card);
WaitForOnPersonalDataChanged();
// Expect that the saved credit card is updated.
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(u"B. Small", results[0]->GetRawInfo(CREDIT_CARD_NAME_FULL));
}
TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
// Check that there are no available types with no profiles stored.
ServerFieldTypeSet non_empty_types;
personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_EQ(0U, non_empty_types.size());
// Test with one profile stored.
AutofillProfile profile0;
test::SetProfileInfo(&profile0, "Marion", nullptr, "Morrison",
"johnwayne@me.xyz", nullptr, "123 Zoo St.", nullptr,
"Hollywood", "CA", "91601", "US", "14155678910");
AddProfileToPersonalDataManager(profile0);
// Make sure everything is set up correctly.
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
std::vector<ServerFieldType> expected_types{
NAME_FIRST,
NAME_LAST,
NAME_FULL,
EMAIL_ADDRESS,
ADDRESS_HOME_ADDRESS,
ADDRESS_HOME_STREET_AND_DEPENDENT_STREET_NAME,
ADDRESS_HOME_LINE1,
ADDRESS_HOME_STREET_ADDRESS,
ADDRESS_HOME_CITY,
ADDRESS_HOME_STATE,
ADDRESS_HOME_ZIP,
ADDRESS_HOME_COUNTRY,
PHONE_HOME_NUMBER,
PHONE_HOME_NUMBER_PREFIX,
PHONE_HOME_NUMBER_SUFFIX,
PHONE_HOME_COUNTRY_CODE,
PHONE_HOME_CITY_CODE,
PHONE_HOME_CITY_AND_NUMBER,
PHONE_HOME_WHOLE_NUMBER};
// For structured names and addresses, there are more non-empty types.
expected_types.push_back(NAME_LAST_SECOND);
expected_types.insert(expected_types.end(),
{ADDRESS_HOME_STREET_NAME, ADDRESS_HOME_HOUSE_NUMBER});
personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_THAT(non_empty_types,
testing::UnorderedElementsAreArray(expected_types));
// Test with multiple profiles stored.
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", nullptr,
"Orlando", "FL", "32801", "US", "16502937549");
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "16502937549");
AddProfileToPersonalDataManager(profile1);
AddProfileToPersonalDataManager(profile2);
EXPECT_EQ(3U, personal_data_->GetProfiles().size());
expected_types.insert(
expected_types.end(),
{NAME_MIDDLE, NAME_MIDDLE_INITIAL, ADDRESS_HOME_LINE2, COMPANY_NAME});
personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_THAT(non_empty_types,
testing::UnorderedElementsAreArray(expected_types));
// Test with credit card information also stored.
CreditCard credit_card(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card, "John Dillinger",
"4234567890123456" /* Visa */, "01", "2999", "");
personal_data_->AddCreditCard(credit_card);
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
expected_types.insert(
expected_types.end(),
{CREDIT_CARD_NAME_FULL, CREDIT_CARD_NAME_FIRST, CREDIT_CARD_NAME_LAST,
CREDIT_CARD_NUMBER, CREDIT_CARD_TYPE, CREDIT_CARD_EXP_MONTH,
CREDIT_CARD_EXP_2_DIGIT_YEAR, CREDIT_CARD_EXP_4_DIGIT_YEAR,
CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR});
personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_THAT(non_empty_types,
testing::UnorderedElementsAreArray(expected_types));
}
TEST_F(PersonalDataManagerTest, IncognitoReadOnly) {
ASSERT_TRUE(personal_data_->GetProfiles().empty());
ASSERT_TRUE(personal_data_->GetCreditCards().empty());
AutofillProfile steve_jobs;
test::SetProfileInfo(&steve_jobs, "Steven", "Paul", "Jobs", "sjobs@apple.com",
"Apple Computer, Inc.", "1 Infinite Loop", "",
"Cupertino", "CA", "95014", "US", "(800) 275-2273");
AddProfileToPersonalDataManager(steve_jobs);
CreditCard bill_gates(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&bill_gates, "William H. Gates", "5555555555554444",
"1", "2020", "1");
personal_data_->AddCreditCard(bill_gates);
// The personal data manager should be able to read existing profiles in an
// off-the-record context.
ResetPersonalDataManager(USER_MODE_INCOGNITO);
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
// No adds, saves, or updates should take effect.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(0);
// Add profiles or credit card shouldn't work.
personal_data_->AddProfile(test::GetFullProfile());
CreditCard larry_page(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&larry_page, "Lawrence Page", "4111111111111111",
"10", "2025", "1");
personal_data_->AddCreditCard(larry_page);
ResetPersonalDataManager(USER_MODE_INCOGNITO);
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
// Saving or creating profiles from imported profiles shouldn't work.
steve_jobs.SetRawInfo(NAME_FIRST, u"Steve");
personal_data_->SaveImportedProfile(steve_jobs);
bill_gates.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Bill Gates");
personal_data_->OnAcceptedLocalCreditCardSave(bill_gates);
ResetPersonalDataManager(USER_MODE_INCOGNITO);
EXPECT_EQ(u"Steven",
personal_data_->GetProfiles()[0]->GetRawInfo(NAME_FIRST));
EXPECT_EQ(
u"William H. Gates",
personal_data_->GetCreditCards()[0]->GetRawInfo(CREDIT_CARD_NAME_FULL));
// Updating existing profiles shouldn't work.
steve_jobs.SetRawInfo(NAME_FIRST, u"Steve");
personal_data_->UpdateProfile(steve_jobs);
bill_gates.SetRawInfo(CREDIT_CARD_NAME_FULL, u"Bill Gates");
personal_data_->UpdateCreditCard(bill_gates);
ResetPersonalDataManager(USER_MODE_INCOGNITO);
EXPECT_EQ(u"Steven",
personal_data_->GetProfiles()[0]->GetRawInfo(NAME_FIRST));
EXPECT_EQ(
u"William H. Gates",
personal_data_->GetCreditCards()[0]->GetRawInfo(CREDIT_CARD_NAME_FULL));
// Removing shouldn't work.
personal_data_->RemoveByGUID(steve_jobs.guid());
personal_data_->RemoveByGUID(bill_gates.guid());
ResetPersonalDataManager(USER_MODE_INCOGNITO);
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
}
// Tests that GetAutofillOffers returns all available offers.
TEST_F(PersonalDataManagerTest, GetAutofillOffers) {
// Add two card-linked offers and one promo code offer.
AddOfferDataForTest(test::GetCardLinkedOfferData1());
AddOfferDataForTest(test::GetCardLinkedOfferData2());
AddOfferDataForTest(test::GetPromoCodeOfferData());
// Should return all three.
EXPECT_EQ(3U, personal_data_->GetAutofillOffers().size());
}
// Tests that GetAutofillOffers does not return any offers if
// |IsAutofillWalletImportEnabled()| returns |false|.
TEST_F(PersonalDataManagerMockTest, GetAutofillOffers_WalletImportDisabled) {
// Add a card-linked offer and a promo code offer.
AddOfferDataForTest(test::GetCardLinkedOfferData1());
AddOfferDataForTest(test::GetPromoCodeOfferData());
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
prefs::SetPaymentsIntegrationEnabled(prefs_.get(), false);
// Should return neither of them as the wallet import pref is disabled.
EXPECT_EQ(0U, personal_data_->GetAutofillOffers().size());
}
// Tests that GetAutofillOffers does not return any offers if
// |IsAutofillCreditCardEnabled()| returns |false|.
TEST_F(PersonalDataManagerMockTest,
GetAutofillOffers_AutofillCreditCardDisabled) {
// Add a card-linked offer and a promo code offer.
AddOfferDataForTest(test::GetCardLinkedOfferData1());
AddOfferDataForTest(test::GetPromoCodeOfferData());
prefs::SetAutofillCreditCardEnabled(prefs_.get(), false);
// Should return neither of the offers as the autofill credit card import pref
// is disabled.
EXPECT_EQ(0U, personal_data_->GetAutofillOffers().size());
}
// Tests that GetActiveAutofillPromoCodeOffersForOrigin returns only active and
// site-relevant promo code offers.
TEST_F(PersonalDataManagerTest, GetActiveAutofillPromoCodeOffersForOrigin) {
// Card-linked offers should not be returned.
AddOfferDataForTest(test::GetCardLinkedOfferData1());
// Expired promo code offers should not be returned.
AddOfferDataForTest(test::GetPromoCodeOfferData(
/*origin=*/GURL("http://www.example.com"), /*is_expired=*/true));
// Active promo code offers should be returned.
AddOfferDataForTest(test::GetPromoCodeOfferData(
/*origin=*/GURL("http://www.example.com"), /*is_expired=*/false));
// Active promo code offers for a different site should not be returned.
AddOfferDataForTest(test::GetPromoCodeOfferData(
/*origin=*/GURL("http://www.some-other-merchant.com"),
/*is_expired=*/false));
// Only the active offer for example.com should be returned.
EXPECT_EQ(1U, personal_data_
->GetActiveAutofillPromoCodeOffersForOrigin(
GURL("http://www.example.com"))
.size());
}
// Tests that GetActiveAutofillPromoCodeOffersForOrigin does not return any
// promo code offers if |IsAutofillWalletImportEnabled()| returns |false|.
TEST_F(PersonalDataManagerMockTest,
GetActiveAutofillPromoCodeOffersForOrigin_WalletImportDisabled) {
// Add an active promo code offer.
AddOfferDataForTest(test::GetPromoCodeOfferData(
/*origin=*/GURL("http://www.example.com")));
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&run_loop));
prefs::SetPaymentsIntegrationEnabled(prefs_.get(), false);
// Should not return the offer as the wallet import pref is disabled.
EXPECT_EQ(0U, personal_data_
->GetActiveAutofillPromoCodeOffersForOrigin(
GURL("http://www.example.com"))
.size());
}
// Tests that GetActiveAutofillPromoCodeOffersForOrigin does not return any
// promo code offers if |IsAutofillCreditCardEnabled()| returns |false|.
TEST_F(PersonalDataManagerMockTest,
GetActiveAutofillPromoCodeOffersForOrigin_AutofillCreditCardDisabled) {
// Add an active promo code offer.
AddOfferDataForTest(test::GetPromoCodeOfferData(
/*origin=*/GURL("http://www.example.com")));
prefs::SetAutofillCreditCardEnabled(prefs_.get(), false);
// Should not return the offer as the autofill credit card pref is disabled.
EXPECT_EQ(0U, personal_data_
->GetActiveAutofillPromoCodeOffersForOrigin(
GURL("http://www.example.com"))
.size());
}
TEST_F(PersonalDataManagerTest, DefaultCountryCodeIsCached) {
// The return value should always be some country code, no matter what.
std::string default_country =
personal_data_->GetDefaultCountryCodeForNewAddress();
EXPECT_EQ(2U, default_country.size());
AutofillProfile profile = test::GetFullProfile();
AddProfileToPersonalDataManager(profile);
// The value is cached and doesn't change even after adding an address.
EXPECT_EQ(default_country,
personal_data_->GetDefaultCountryCodeForNewAddress());
// Disabling Autofill blows away this cache and shouldn't account for Autofill
// profiles.
prefs::SetAutofillProfileEnabled(prefs_.get(), false);
prefs::SetAutofillCreditCardEnabled(prefs_.get(), false);
prefs::SetAutofillIBANEnabled(prefs_.get(), false);
WaitForOnPersonalDataChanged();
EXPECT_EQ(default_country,
personal_data_->GetDefaultCountryCodeForNewAddress());
// Enabling Autofill blows away the cached value and should reflect the new
// value (accounting for profiles).
prefs::SetAutofillProfileEnabled(prefs_.get(), true);
EXPECT_EQ(base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)),
personal_data_->GetDefaultCountryCodeForNewAddress());
}
TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromProfiles) {
AutofillProfile canadian_profile = test::GetFullCanadianProfile();
ASSERT_EQ(canadian_profile.GetRawInfo(ADDRESS_HOME_COUNTRY), u"CA");
AddProfileToPersonalDataManager(canadian_profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("CA", personal_data_->GetDefaultCountryCodeForNewAddress());
// Multiple profiles cast votes.
AutofillProfile us_profile1 = test::GetFullProfile();
AutofillProfile us_profile2 = test::GetFullProfile2();
ASSERT_EQ(us_profile1.GetRawInfo(ADDRESS_HOME_COUNTRY), u"US");
ASSERT_EQ(us_profile2.GetRawInfo(ADDRESS_HOME_COUNTRY), u"US");
AddProfileToPersonalDataManager(us_profile1);
AddProfileToPersonalDataManager(us_profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("US", personal_data_->GetDefaultCountryCodeForNewAddress());
}
TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromVariations) {
const std::string expected_country_code = "DE";
const std::string unexpected_country_code = "FR";
// Normally, the variation country code is passed to the constructor.
personal_data_->set_variations_country_code_for_testing(
expected_country_code);
// Since there are no profiles set, the country code supplied buy variations
// should be used get get a default country code.
ASSERT_EQ(0u, personal_data_->GetProfiles().size());
std::string actual_country_code =
personal_data_->GetDefaultCountryCodeForNewAddress();
EXPECT_EQ(expected_country_code, actual_country_code);
// Set a new country code.
// The default country code retrieved before should have been cached.
personal_data_->set_variations_country_code_for_testing(
unexpected_country_code);
actual_country_code = personal_data_->GetDefaultCountryCodeForNewAddress();
EXPECT_EQ(expected_country_code, actual_country_code);
// Now a profile is set and the correct caching of the country code is
// verified once more.
AddProfileToPersonalDataManager(test::GetFullProfile());
actual_country_code = personal_data_->GetDefaultCountryCodeForNewAddress();
EXPECT_EQ(actual_country_code, expected_country_code);
}
TEST_F(PersonalDataManagerTest, UpdateLanguageCodeInProfile) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile);
// Make sure everything is set up correctly.
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
profile.set_language_code("en");
UpdateProfileOnPersonalDataManager(profile);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, profile.Compare(*results[0]));
EXPECT_EQ("en", results[0]->language_code());
}
TEST_F(PersonalDataManagerTest, GetProfileSuggestions) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), u"123", false,
std::vector<ServerFieldType>());
ASSERT_FALSE(suggestions.empty());
EXPECT_EQ(u"123 Zoo St., Second Line, Third line, unit 5",
suggestions[0].main_text.value);
}
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_PhoneSubstring_NoImprovedDisambiguation) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndDisableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(PHONE_HOME_WHOLE_NUMBER), u"234", false,
std::vector<ServerFieldType>());
ASSERT_FALSE(suggestions.empty());
EXPECT_EQ(u"12345678910", suggestions[0].main_text.value);
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_PhoneSubstring_ImprovedDisambiguation) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(PHONE_HOME_WHOLE_NUMBER), u"234", false,
std::vector<ServerFieldType>());
ASSERT_FALSE(suggestions.empty());
EXPECT_EQ(u"(234) 567-8910", suggestions[0].main_text.value);
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_HideSubsets) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
// Dupe profile, except different in email address (irrelevant for this form).
AutofillProfile profile1 = profile;
profile1.set_guid(base::Uuid::GenerateRandomV4().AsLowercaseString());
profile1.SetRawInfo(EMAIL_ADDRESS, u"spam_me@example.com");
// Dupe profile, except different in address state.
AutofillProfile profile2 = profile;
profile2.set_guid(base::Uuid::GenerateRandomV4().AsLowercaseString());
profile2.SetRawInfo(ADDRESS_HOME_STATE, u"TX");
// Subset profile.
AutofillProfile profile3 = profile;
profile3.set_guid(base::Uuid::GenerateRandomV4().AsLowercaseString());
profile3.SetRawInfo(ADDRESS_HOME_STATE, std::u16string());
// For easier results verification, make sure |profile| is suggested first.
profile.set_use_count(5);
AddProfileToPersonalDataManager(profile);
AddProfileToPersonalDataManager(profile1);
AddProfileToPersonalDataManager(profile2);
AddProfileToPersonalDataManager(profile3);
ResetPersonalDataManager(USER_MODE_NORMAL);
// Simulate a form with street address, city and state.
std::vector<ServerFieldType> types;
types.push_back(ADDRESS_HOME_CITY);
types.push_back(ADDRESS_HOME_STATE);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), u"123", false, types);
ASSERT_EQ(2U, suggestions.size());
ASSERT_EQ(1U, suggestions[0].labels.size());
ASSERT_EQ(1U, suggestions[0].labels[0].size());
EXPECT_EQ(u"Hollywood, CA", suggestions[0].labels[0][0].value);
ASSERT_EQ(1U, suggestions[1].labels.size());
ASSERT_EQ(1U, suggestions[1].labels.size());
EXPECT_EQ(u"Hollywood, TX", suggestions[1].labels[0][0].value);
}
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_SuggestionsLimit) {
// Drawing takes noticeable time when there are more than 10 profiles.
// Therefore, we keep only the 10 first suggested profiles.
std::vector<AutofillProfile> profiles;
for (size_t i = 0; i < 2 * suggestion_selection::kMaxUniqueSuggestionsCount;
i++) {
AutofillProfile profile;
test::SetProfileInfo(&profile, base::StringPrintf("Marion%zu", i).c_str(),
"Mitchell", "Morrison", "johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile);
profiles.push_back(profile);
}
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), u"Ma", false, std::vector<ServerFieldType>());
ASSERT_EQ(2 * suggestion_selection::kMaxUniqueSuggestionsCount,
personal_data_->GetProfiles().size());
ASSERT_EQ(suggestion_selection::kMaxUniqueSuggestionsCount,
suggestions.size());
}
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfilesLimit) {
// Deduping takes noticeable time when there are more than 50 profiles.
// Therefore, keep only the 50 first pre-dedupe matching profiles.
std::vector<AutofillProfile> profiles;
for (size_t i = 0; i < suggestion_selection::kMaxSuggestedProfilesCount;
i++) {
AutofillProfile profile;
test::SetProfileInfo(
&profile, "Marion", "Mitchell", "Morrison", "johnwayne@me.xyz", "Fox",
base::StringPrintf("%zu123 Zoo St.\nSecond Line\nThird line", i)
.c_str(),
"unit 5", "Hollywood", "CA", "91601", "US", "12345678910");
// Set ranking score such that they appear before the "last" profile (added
// next).
profile.set_use_count(12);
profile.set_use_date(AutofillClock::Now() - base::Days(1));
AddProfileToPersonalDataManager(profile);
profiles.push_back(profile);
}
// Add another profile that matches, but that will get stripped out.
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marie", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"000 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile.set_use_count(1);
profile.set_use_date(AutofillClock::Now() - base::Days(7));
AddProfileToPersonalDataManager(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), u"Ma", false, std::vector<ServerFieldType>());
ASSERT_EQ(suggestion_selection::kMaxSuggestedProfilesCount + 1,
personal_data_->GetProfiles().size());
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ(u"Marion", suggestions[0].main_text.value);
}
// Tests that GetProfileSuggestions orders its suggestions based on the ranking
// formula.
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Ranking) {
// Set up the profiles. They are named with number suffixes X so the X is the
// order in which they should be ordered by the ranking formula.
AutofillProfile profile3;
test::SetProfileInfo(&profile3, "Marion3", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile3.set_use_date(AutofillClock::Now() - base::Days(1));
profile3.set_use_count(5);
AddProfileToPersonalDataManager(profile3);
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile1.set_use_date(AutofillClock::Now() - base::Days(1));
profile1.set_use_count(10);
AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile2.set_use_date(AutofillClock::Now() - base::Days(15));
profile2.set_use_count(300);
AddProfileToPersonalDataManager(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), u"Ma", false, std::vector<ServerFieldType>());
ASSERT_EQ(3U, suggestions.size());
EXPECT_EQ(suggestions[0].main_text.value, u"Marion1");
EXPECT_EQ(suggestions[1].main_text.value, u"Marion2");
EXPECT_EQ(suggestions[2].main_text.value, u"Marion3");
}
// Tests that GetProfileSuggestions returns all profiles suggestions.
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_NumberOfSuggestions) {
// Set up 3 different profiles.
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile2);
AutofillProfile profile3;
test::SetProfileInfo(&profile3, "Marion3", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile3);
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that all the profiles are suggested.
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), std::u16string(), false,
std::vector<ServerFieldType>());
EXPECT_EQ(3U, suggestions.size());
}
// Tests that disused profiles are suppressed when supression is enabled and
// the input field is empty.
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_SuppressDisusedProfilesOnEmptyField) {
// Set up 2 different profiles.
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile1.set_use_date(AutofillClock::Now() - base::Days(200));
AddProfileToPersonalDataManager(profile1);
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"456 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
profile2.set_use_date(AutofillClock::Now() - base::Days(20));
AddProfileToPersonalDataManager(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
// Query with empty string only returns profile2.
{
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), std::u16string(), false,
std::vector<ServerFieldType>());
EXPECT_EQ(1U, suggestions.size());
}
// Query with non-alpha-numeric string only returns profile2.
{
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), u"--", false,
std::vector<ServerFieldType>());
EXPECT_EQ(1U, suggestions.size());
}
// Query with prefix for profile1 returns profile1.
{
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), u"123", false,
std::vector<ServerFieldType>());
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ(u"123 Zoo St., Second Line, Third line, unit 5",
suggestions[0].main_text.value);
}
// Query with prefix for profile2 returns profile2.
{
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), u"456", false,
std::vector<ServerFieldType>());
EXPECT_EQ(1U, suggestions.size());
EXPECT_EQ(u"456 Zoo St., Second Line, Third line, unit 5",
suggestions[0].main_text.value);
}
}
// Test that local and server profiles are not shown if
// |kAutofillProfileEnabled| is set to |false|.
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfileAutofillDisabled) {
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
const std::string kServerAddressId("server_address1");
ASSERT_TRUE(TurnOnSyncFeature());
// Add two different profiles, a local and a server one.
AutofillProfile local_profile;
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
AddProfileToPersonalDataManager(local_profile);
if (!IsWalletAddressConversionDeprecated()) {
std::vector<AutofillProfile> server_profiles;
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
"ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
"77401", "US", "");
// Wallet only provides a full name, so the above first and last names
// will be ignored when the profile is written to the DB.
server_profiles.back().SetRawInfo(NAME_FULL, u"John Doe");
SetServerProfiles(server_profiles);
}
// Disable Profile autofill.
prefs::SetAutofillProfileEnabled(personal_data_->pref_service_, false);
WaitForOnPersonalDataChanged();
ConvertWalletAddressesAndUpdateWalletCards();
// Check that profiles were saved.
const size_t expected_profiles = 1 + !IsWalletAddressConversionDeprecated();
EXPECT_EQ(expected_profiles, personal_data_->GetProfiles().size());
// Expect no autofilled values or suggestions.
EXPECT_EQ(0U, personal_data_->GetProfilesToSuggest().size());
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), u"123", false,
std::vector<ServerFieldType>());
ASSERT_EQ(0U, suggestions.size());
}
// Test that local and server profiles are not loaded into memory on start-up if
// |kAutofillProfileEnabled| is set to |false|.
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_NoProfilesLoadedIfDisabled) {
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
const std::string kServerAddressId("server_address1");
ASSERT_TRUE(TurnOnSyncFeature());
// Add two different profiles, a local and a server one.
AutofillProfile local_profile;
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
AddProfileToPersonalDataManager(local_profile);
if (!IsWalletAddressConversionDeprecated()) {
std::vector<AutofillProfile> server_profiles;
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
"ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
"77401", "US", "");
// Wallet only provides a full name, so the above first and last names
// will be ignored when the profile is written to the DB.
server_profiles.back().SetRawInfo(NAME_FULL, u"John Doe");
SetServerProfiles(server_profiles);
}
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
ConvertWalletAddressesAndUpdateWalletCards();
// Expect that all profiles are suggested.
const size_t expected_profiles = 1 + !IsWalletAddressConversionDeprecated();
EXPECT_EQ(expected_profiles, personal_data_->GetProfiles().size());
EXPECT_EQ(expected_profiles, personal_data_->GetProfilesToSuggest().size());
// Disable Profile autofill.
prefs::SetAutofillProfileEnabled(personal_data_->pref_service_, false);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Expect no profile values or suggestions were loaded.
EXPECT_EQ(0U, personal_data_->GetProfilesToSuggest().size());
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), u"123", false,
std::vector<ServerFieldType>());
ASSERT_EQ(0U, suggestions.size());
}
// Test that local profiles are not added if |kAutofillProfileEnabled| is set to
// |false|.
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_NoProfilesAddedIfDisabled) {
// Disable Profile autofill.
prefs::SetAutofillProfileEnabled(personal_data_->pref_service_, false);
// Add a local profile.
AutofillProfile local_profile;
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
AddProfileToPersonalDataManager(local_profile);
// Expect no profile values or suggestions were added.
EXPECT_EQ(0U, personal_data_->GetProfiles().size());
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_LogProfileSuggestionsMadeWithFormatter) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AddProfileToPersonalDataManager(profile);
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
base::HistogramTester histogram_tester;
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FIRST, NAME_LAST, EMAIL_ADDRESS,
PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(testing::Field(
&Suggestion::main_text,
Suggestion::Text(u"Hoa", Suggestion::Text::IsPrimary(true)))));
histogram_tester.ExpectUniqueSample(
"Autofill.ProfileSuggestionsMadeWithFormatter", true, 1);
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ForContactForm) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AddProfileToPersonalDataManager(profile);
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FIRST, NAME_LAST, EMAIL_ADDRESS,
PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(AllOf(
testing::Field(&Suggestion::labels,
ConstructLabelLineMatrix(
{u"(978) 674-4120", u"hoa.pham@comcast.net"})),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_AddressForm) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AddProfileToPersonalDataManager(profile);
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
EXPECT_THAT(personal_data_->GetProfileSuggestions(
AutofillType(NAME_FULL), std::u16string(), false,
std::vector<ServerFieldType>{
NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY,
ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP}),
ElementsAre(AllOf(
testing::Field(&Suggestion::labels,
ConstructLabelLineMatrix(
{u"401 Merrimack St, Lowell, MA 01852"})),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_AddressPhoneForm) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AddProfileToPersonalDataManager(profile);
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(NAME_FULL), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(
AllOf(testing::Field(&Suggestion::labels,
ConstructLabelLineMatrix(
{u"(978) 674-4120", u"401 Merrimack St"})),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_AddressEmailForm) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AddProfileToPersonalDataManager(profile);
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(NAME_FULL), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
EMAIL_ADDRESS}),
ElementsAre(AllOf(
testing::Field(&Suggestion::labels,
ConstructLabelLineMatrix(
{u"401 Merrimack St", u"hoa.pham@comcast.net"})),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_FormWithOneProfile) {
AutofillProfile profile;
test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AddProfileToPersonalDataManager(profile);
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kAutofillUseImprovedLabelDisambiguation);
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(NAME_FULL), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(
AllOf(testing::Field(&Suggestion::labels,
ConstructLabelLineMatrix({u"401 Merrimack St"})),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_AddressContactFormWithProfiles) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitWithFeatures(
/*enabled_features=*/{features::
kAutofillEnableRankingFormulaAddressProfiles,
features::kAutofillUseImprovedLabelDisambiguation},
/*disabled_features=*/{});
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Hoa", "", "Pham", "hp@aol.com", "",
"216 Broadway St", "", "Lowell", "MA", "01854", "US",
"19784523366");
// The profiles' use dates and counts are set make this test deterministic.
// The suggestion created with data from profile1 should be ranked higher
// than profile2's associated suggestion. This ensures that profile1's
// suggestion is the first element in the collection returned by
// GetProfileSuggestions.
profile1.set_use_date(AutofillClock::Now());
profile1.set_use_count(10);
profile2.set_use_date(AutofillClock::Now() - base::Days(10));
profile2.set_use_count(1);
EXPECT_TRUE(profile1.HasGreaterRankingThan(&profile2, AutofillClock::Now()));
AddProfileToPersonalDataManager(profile1);
AddProfileToPersonalDataManager(profile2);
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(NAME_FULL), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(
AllOf(testing::Field(&Suggestion::labels,
ConstructLabelLineMatrix(
{u"401 Merrimack St", u"(978) 674-4120",
u"hoa.pham@comcast.net"})),
testing::Field(&Suggestion::icon, kAddressEntryIcon)),
AllOf(testing::Field(&Suggestion::labels,
ConstructLabelLineMatrix({u"216 Broadway St",
u"(978) 452-3366",
u"hp@aol.com"})),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_MobileShowOne) {
std::map<std::string, std::string> parameters;
parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] =
features::kAutofillUseMobileLabelDisambiguationParameterShowOne;
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeatureWithParameters(
features::kAutofillUseMobileLabelDisambiguation, parameters);
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "María", "", "Lòpez", "maria@aol.com", "",
"11 Elkins St", "", "Boston", "MA", "02127", "US",
"6172686862");
// The profiles' use dates and counts are set make this test deterministic.
// The suggestion created with data from profile1 should be ranked higher
// than profile2's associated suggestion. This ensures that profile1's
// suggestion is the first element in the collection returned by
// GetProfileSuggestions.
profile1.set_use_date(AutofillClock::Now());
profile1.set_use_count(10);
profile2.set_use_date(AutofillClock::Now() - base::Days(10));
profile2.set_use_count(1);
AddProfileToPersonalDataManager(profile1);
AddProfileToPersonalDataManager(profile2);
// Tests a form with name, email address, and phone number fields.
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(EMAIL_ADDRESS), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FIRST, NAME_LAST, EMAIL_ADDRESS,
PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(
AllOf(testing::Field(&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(u"(978) 674-4120")}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon)),
AllOf(testing::Field(&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(u"(617) 268-6862")}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
// Tests a form with name, address, phone number, and email address fields.
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(EMAIL_ADDRESS), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
ADDRESS_HOME_CITY, EMAIL_ADDRESS,
PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(
AllOf(testing::Field(&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(u"401 Merrimack St")}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon)),
AllOf(testing::Field(&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(u"11 Elkins St")}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_MobileShowAll) {
std::map<std::string, std::string> parameters;
parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] =
features::kAutofillUseMobileLabelDisambiguationParameterShowAll;
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeatureWithParameters(
features::kAutofillUseMobileLabelDisambiguation, parameters);
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Hoa", "", "Pham", "hoa.pham@comcast.net", "",
"401 Merrimack St", "", "Lowell", "MA", "01852", "US",
"19786744120");
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "María", "", "Lòpez", "maria@aol.com", "",
"11 Elkins St", "", "Boston", "MA", "02127", "US",
"6172686862");
// The profiles' use dates and counts are set make this test deterministic.
// The suggestion created with data from profile1 should be ranked higher
// than profile2's associated suggestion. This ensures that profile1's
// suggestion is the first element in the collection returned by
// GetProfileSuggestions.
profile1.set_use_date(AutofillClock::Now());
profile1.set_use_count(10);
profile2.set_use_date(AutofillClock::Now() - base::Days(10));
profile2.set_use_count(1);
AddProfileToPersonalDataManager(profile1);
AddProfileToPersonalDataManager(profile2);
// Tests a form with name, email address, and phone number fields.
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(EMAIL_ADDRESS), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FIRST, NAME_LAST, EMAIL_ADDRESS,
PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(
AllOf(testing::Field(&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(ConstructMobileLabelLine(
{u"Hoa", u"(978) 674-4120"}))}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon)),
AllOf(testing::Field(&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(ConstructMobileLabelLine(
{u"María", u"(617) 268-6862"}))}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
// Tests a form with name, address, phone number, and email address fields.
EXPECT_THAT(
personal_data_->GetProfileSuggestions(
AutofillType(EMAIL_ADDRESS), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
ADDRESS_HOME_CITY, EMAIL_ADDRESS,
PHONE_HOME_WHOLE_NUMBER}),
ElementsAre(
AllOf(
testing::Field(
&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(ConstructMobileLabelLine(
{u"Hoa", u"401 Merrimack St", u"(978) 674-4120"}))}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon)),
AllOf(testing::Field(
&Suggestion::labels,
std::vector<std::vector<Suggestion::Text>>{
{Suggestion::Text(ConstructMobileLabelLine(
{u"María", u"11 Elkins St", u"(617) 268-6862"}))}}),
testing::Field(&Suggestion::icon, kAddressEntryIcon))));
}
#endif // if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesMaskedServerCard) {
// Add a masked server card.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"2110" /* last 4 digits */, "12", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
CreditCard cardToCompare;
cardToCompare.SetNumber(u"4234 5678 9012 2110" /* Visa */);
ASSERT_TRUE(personal_data_->IsKnownCard(cardToCompare));
}
TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesFullServerCard) {
// Add a full server card.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"4234567890122110" /* Visa */, "12", "2999", "1");
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
CreditCard cardToCompare;
cardToCompare.SetNumber(u"4234 5678 9012 2110" /* Visa */);
ASSERT_TRUE(personal_data_->IsKnownCard(cardToCompare));
}
TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesLocalCard) {
// Add a local card.
CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
"4234 5678 9012 2110" /* Visa */, "04", "2999", "1");
personal_data_->AddCreditCard(credit_card0);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
CreditCard cardToCompare;
cardToCompare.SetNumber(u"4234567890122110" /* Visa */);
ASSERT_TRUE(personal_data_->IsKnownCard(cardToCompare));
}
TEST_F(PersonalDataManagerTest, IsKnownCard_TypeDoesNotMatch) {
// Add a local card.
CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
"4234 5678 9012 2110" /* Visa */, "04", "2999", "1");
personal_data_->AddCreditCard(credit_card0);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
CreditCard cardToCompare;
cardToCompare.SetNumber(u"5105 1051 0510 2110" /* American Express */);
ASSERT_FALSE(personal_data_->IsKnownCard(cardToCompare));
}
TEST_F(PersonalDataManagerTest, IsKnownCard_LastFourDoesNotMatch) {
// Add a local card.
CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
"4234 5678 9012 2110" /* Visa */, "04", "2999", "1");
personal_data_->AddCreditCard(credit_card0);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
CreditCard cardToCompare;
cardToCompare.SetNumber(u"4234 5678 9012 0000" /* Visa */);
ASSERT_FALSE(personal_data_->IsKnownCard(cardToCompare));
}
TEST_F(PersonalDataManagerTest, IsServerCard_DuplicateOfFullServerCard) {
// Add a full server card.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"4234567890122110" /* Visa */, "12", "2999", "1");
SetServerCards(server_cards);
// Add a dupe local card of a full server card.
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Emmet Dalton",
"4234 5678 9012 2110" /* Visa */, "12", "2999", "1");
personal_data_->AddCreditCard(local_card);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
CreditCard cardToCompare;
cardToCompare.SetNumber(u"4234 5678 9012 2110" /* Visa */);
ASSERT_TRUE(personal_data_->IsServerCard(&cardToCompare));
ASSERT_TRUE(personal_data_->IsServerCard(&local_card));
}
TEST_F(PersonalDataManagerTest, IsServerCard_DuplicateOfMaskedServerCard) {
// Add a masked server card.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"2110" /* last 4 digits */, "12", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
SetServerCards(server_cards);
// Add a dupe local card of a full server card.
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Emmet Dalton",
"4234 5678 9012 2110" /* Visa */, "12", "2999", "1");
personal_data_->AddCreditCard(local_card);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
CreditCard cardToCompare;
cardToCompare.SetNumber(u"4234 5678 9012 2110" /* Visa */);
ASSERT_TRUE(personal_data_->IsServerCard(&cardToCompare));
ASSERT_TRUE(personal_data_->IsServerCard(&local_card));
}
TEST_F(PersonalDataManagerTest, IsServerCard_AlreadyServerCard) {
std::vector<CreditCard> server_cards;
// Create a full server card.
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&full_server_card, "Homer Simpson",
"4234567890123456" /* Visa */, "01", "2999", "1");
server_cards.push_back(full_server_card);
// Create a masked server card.
CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&masked_card, "Homer Simpson", "2110" /* Visa */,
"01", "2999", "1");
masked_card.SetNetworkForMaskedCard(kVisaCard);
server_cards.push_back(masked_card);
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
ASSERT_TRUE(personal_data_->IsServerCard(&full_server_card));
ASSERT_TRUE(personal_data_->IsServerCard(&masked_card));
}
TEST_F(PersonalDataManagerTest, IsServerCard_UniqueLocalCard) {
// Add a unique local card.
CreditCard local_card("1141084B-72D7-4B73-90CF-3D6AC154673B",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"4234567890123456" /* Visa */, "01", "2999", "1");
personal_data_->AddCreditCard(local_card);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
ASSERT_FALSE(personal_data_->IsServerCard(&local_card));
}
// Test that local credit cards are ordered as expected.
TEST_F(PersonalDataManagerTest, GetCreditCardsToSuggest_LocalCardsRanking) {
SetUpReferenceLocalCreditCards();
// Sublabel is card number when filling name (exact format depends on
// the platform, but the last 4 digits should appear).
std::vector<CreditCard*> card_to_suggest =
personal_data_->GetCreditCardsToSuggest();
ASSERT_EQ(3U, card_to_suggest.size());
// Ordered as expected.
EXPECT_EQ(u"John Dillinger",
card_to_suggest[0]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"Clyde Barrow",
card_to_suggest[1]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"Bonnie Parker",
card_to_suggest[2]->GetRawInfo(CREDIT_CARD_NAME_FULL));
}
// Test that local and server cards are ordered as expected.
TEST_F(PersonalDataManagerTest,
GetCreditCardsToSuggest_LocalAndServerCardsRanking) {
SetUpReferenceLocalCreditCards();
// Add some server cards.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"2999", "1");
server_cards.back().set_use_count(2);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(1));
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b460");
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"2999", "1");
server_cards.back().set_use_count(6);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(1));
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(5U, personal_data_->GetCreditCards().size());
std::vector<CreditCard*> card_to_suggest =
personal_data_->GetCreditCardsToSuggest();
ASSERT_EQ(5U, card_to_suggest.size());
// All cards should be ordered as expected.
EXPECT_EQ(u"Jesse James",
card_to_suggest[0]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"John Dillinger",
card_to_suggest[1]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"Clyde Barrow",
card_to_suggest[2]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"Emmet Dalton",
card_to_suggest[3]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"Bonnie Parker",
card_to_suggest[4]->GetRawInfo(CREDIT_CARD_NAME_FULL));
}
// Test that local and server cards are not shown if
// |kAutofillCreditCardEnabled| is set to |false|.
TEST_F(PersonalDataManagerTest,
GetCreditCardsToSuggest_CreditCardAutofillDisabled) {
SetUpReferenceLocalCreditCards();
// Add some server cards.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"2999", "1");
server_cards.back().set_use_count(2);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(1));
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b460");
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"2999", "1");
server_cards.back().set_use_count(6);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(1));
SetServerCards(server_cards);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
// Disable Credit card autofill.
prefs::SetAutofillCreditCardEnabled(personal_data_->pref_service_, false);
WaitForOnPersonalDataChanged();
// Check that profiles were saved.
EXPECT_EQ(5U, personal_data_->GetCreditCards().size());
// Expect no autofilled values or suggestions.
EXPECT_EQ(0U, personal_data_->GetCreditCardsToSuggest().size());
std::vector<CreditCard*> card_to_suggest =
personal_data_->GetCreditCardsToSuggest();
ASSERT_EQ(0U, card_to_suggest.size());
}
// Test that local and server cards are not loaded into memory on start-up if
// |kAutofillCreditCardEnabled| is set to |false|.
TEST_F(PersonalDataManagerTest,
GetCreditCardsToSuggest_NoCardsLoadedIfDisabled) {
SetUpReferenceLocalCreditCards();
// Add some server cards.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"2999", "1");
server_cards.back().set_use_count(2);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(1));
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b460");
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"2999", "1");
server_cards.back().set_use_count(6);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(1));
SetServerCards(server_cards);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
// Expect 5 autofilled values or suggestions.
EXPECT_EQ(5U, personal_data_->GetCreditCards().size());
// Disable Credit card autofill.
prefs::SetAutofillCreditCardEnabled(personal_data_->pref_service_, false);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Expect no credit card values or suggestions were loaded.
EXPECT_EQ(0U, personal_data_->GetCreditCardsToSuggest().size());
std::vector<CreditCard*> card_to_suggest =
personal_data_->GetCreditCardsToSuggest();
ASSERT_EQ(0U, card_to_suggest.size());
}
// Test that local credit cards are not added if |kAutofillCreditCardEnabled| is
// set to |false|.
TEST_F(PersonalDataManagerTest,
GetCreditCardsToSuggest_NoCreditCardsAddedIfDisabled) {
// Disable Profile autofill.
prefs::SetAutofillCreditCardEnabled(personal_data_->pref_service_, false);
// Add a local credit card.
CreditCard credit_card("002149C1-EE28-4213-A3B9-DA243FFF021B",
"https://www.example.com");
test::SetCreditCardInfo(&credit_card, "Bonnie Parker",
"5105105105105100" /* Mastercard */, "04", "2999",
"1");
personal_data_->AddCreditCard(credit_card);
// Expect no credit card values or suggestions were added.
EXPECT_EQ(0U, personal_data_->GetCreditCards().size());
}
// Tests the suggestions of duplicate local and server credit cards.
TEST_F(PersonalDataManagerTest, GetCreditCardsToSuggest_ServerDuplicates) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
features::kAutofillSuggestServerCardInsteadOfLocalCard);
SetUpReferenceLocalCreditCards();
// Add some server cards. If there are local dupes, the locals should be
// hidden.
std::vector<CreditCard> server_cards;
// This server card matches a local card, except the local card is missing the
// number. This should count as a dupe and thus not be shown in the
// suggestions since the locally saved card takes precedence.
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"3456" /* Visa */, "01", "2999", "1");
server_cards.back().set_use_count(2);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(15));
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
// This unmasked server card is an exact dupe of a local card. Therefore only
// this card should appear in the suggestions as full server cards have
// precedence over local cards.
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
server_cards.back().set_use_count(1);
server_cards.back().set_use_date(AutofillClock::Now() - base::Days(15));
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(5U, personal_data_->GetCreditCards().size());
std::vector<CreditCard*> card_to_suggest =
personal_data_->GetCreditCardsToSuggest();
ASSERT_EQ(3U, card_to_suggest.size());
EXPECT_EQ(u"John Dillinger",
card_to_suggest[0]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"Clyde Barrow",
card_to_suggest[1]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(u"Bonnie Parker",
card_to_suggest[2]->GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(CreditCard::LOCAL_CARD, card_to_suggest[0]->record_type());
EXPECT_EQ(CreditCard::FULL_SERVER_CARD, card_to_suggest[1]->record_type());
EXPECT_EQ(CreditCard::LOCAL_CARD, card_to_suggest[2]->record_type());
}
// Tests that a full server card can be a dupe of more than one local card.
TEST_F(PersonalDataManagerTest,
GetCreditCardsToSuggest_ServerCardDuplicateOfMultipleLocalCards) {
SetUpReferenceLocalCreditCards();
// Add a duplicate server card.
std::vector<CreditCard> server_cards;
// This unmasked server card is an exact dupe of a local card. Therefore only
// the local card should appear in the suggestions.
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(4U, personal_data_->GetCreditCards().size());
std::vector<CreditCard*> card_to_suggest =
personal_data_->GetCreditCardsToSuggest();
ASSERT_EQ(3U, card_to_suggest.size());
// Add a second dupe local card to make sure a full server card can be a dupe
// of more than one local card.
CreditCard credit_card3("4141084B-72D7-4B73-90CF-3D6AC154673B",
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card3, "Clyde Barrow", "", "04", "", "");
personal_data_->AddCreditCard(credit_card3);
WaitForOnPersonalDataChanged();
card_to_suggest = personal_data_->GetCreditCardsToSuggest();
ASSERT_EQ(3U, card_to_suggest.size());
}
// Tests that only the full server card is kept when deduping with a local
// duplicate of it.
TEST_F(PersonalDataManagerTest,
DedupeCreditCardToSuggest_FullServerShadowsLocal) {
std::list<CreditCard*> credit_cards;
// Create 3 different local credit cards.
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"4234567890123456" /* Visa */, "01", "2999", "1");
local_card.set_use_count(3);
local_card.set_use_date(AutofillClock::Now() - base::Days(1));
credit_cards.push_back(&local_card);
// Create a full server card that is a duplicate of one of the local cards.
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&full_server_card, "Homer Simpson",
"4234567890123456" /* Visa */, "01", "2999", "1");
full_server_card.set_use_count(1);
full_server_card.set_use_date(AutofillClock::Now() - base::Days(15));
credit_cards.push_back(&full_server_card);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
ASSERT_EQ(1U, credit_cards.size());
const CreditCard* deduped_card = credit_cards.front();
EXPECT_TRUE(*deduped_card == full_server_card);
}
// Tests that only the local card is kept when deduping with a masked server
// duplicate of it or vice-versa. This is checked based on the value assigned
// during the for loop.
TEST_F(PersonalDataManagerTest,
DedupeCreditCardToSuggest_BothLocalAndServerShadowsMaskedInTurns) {
for (bool is_dedupe_experiment_active : {true, false}) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatureState(
features::kAutofillSuggestServerCardInsteadOfLocalCard,
is_dedupe_experiment_active);
std::list<CreditCard*> credit_cards;
CreditCard local_card("1141084B-72D7-4B73-90CF-3D6AC154673B",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"4234567890123456" /* Visa */, "01", "2999", "1");
credit_cards.push_back(&local_card);
// Create a masked server card that is a duplicate of a local card.
CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&masked_card, "Homer Simpson", "3456" /* Visa */,
"01", "2999", "1");
masked_card.SetNetworkForMaskedCard(kVisaCard);
credit_cards.push_back(&masked_card);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
ASSERT_EQ(1U, credit_cards.size());
const CreditCard* deduped_card = credit_cards.front();
if (is_dedupe_experiment_active) {
EXPECT_EQ(*deduped_card, masked_card);
} else {
EXPECT_EQ(*deduped_card, local_card);
}
}
}
// Tests that identical full server and masked credit cards are not deduped.
TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_FullServerAndMasked) {
std::list<CreditCard*> credit_cards;
// Create a full server card that is a duplicate of one of the local cards.
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&full_server_card, "Homer Simpson",
"4234567890123456" /* Visa */, "01", "2999", "1");
full_server_card.set_use_count(1);
full_server_card.set_use_date(AutofillClock::Now() - base::Days(15));
credit_cards.push_back(&full_server_card);
// Create a masked server card that is a duplicate of a local card.
CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&masked_card, "Homer Simpson", "3456" /* Visa */,
"01", "2999", "1");
masked_card.set_use_count(2);
masked_card.set_use_date(AutofillClock::Now() - base::Days(15));
masked_card.SetNetworkForMaskedCard(kVisaCard);
credit_cards.push_back(&masked_card);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
EXPECT_EQ(2U, credit_cards.size());
}
// Tests that different local, masked, and full server credit cards are not
// deduped.
TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) {
std::list<CreditCard*> credit_cards;
CreditCard local_card("002149C1-EE28-4213-A3B9-DA243FFF021B",
test::kEmptyOrigin);
local_card.set_use_count(1);
local_card.set_use_date(AutofillClock::Now() - base::Days(1));
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"5105105105105100" /* Mastercard */, "", "", "");
credit_cards.push_back(&local_card);
// Create a masked server card that is different from the local card.
CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "b456");
test::SetCreditCardInfo(&masked_card, "Homer Simpson", "0005", "12", "2999",
"1");
masked_card.set_use_count(3);
masked_card.set_use_date(AutofillClock::Now() - base::Days(15));
// credit_card4.SetNetworkForMaskedCard(kVisaCard);
credit_cards.push_back(&masked_card);
// Create a full server card that is slightly different of the two other
// cards.
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&full_server_card, "Homer Simpson",
"378282246310005" /* American Express */, "04",
"2999", "1");
full_server_card.set_use_count(1);
full_server_card.set_use_date(AutofillClock::Now() - base::Days(15));
credit_cards.push_back(&full_server_card);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
EXPECT_EQ(3U, credit_cards.size());
}
TEST_F(PersonalDataManagerTest, RecordUseOf) {
// Create the test clock and set the time to a specific value.
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
auto Check = [](const AutofillDataModel& data_model, size_t use_count,
base::Time use_date, base::Time modification_date) {
EXPECT_EQ(use_count, data_model.use_count());
EXPECT_EQ(use_date, data_model.use_date());
EXPECT_EQ(modification_date, data_model.modification_date());
};
AutofillProfile profile(test::GetFullProfile());
Check(profile, 1u, kArbitraryTime, kArbitraryTime);
AddProfileToPersonalDataManager(profile);
CreditCard credit_card(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card, "John Dillinger",
"4234567890123456" /* Visa */, "01", "2999", "1");
Check(credit_card, 1u, kArbitraryTime, kArbitraryTime);
personal_data_->AddCreditCard(credit_card);
// Make sure everything is set up correctly.
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
// Set the current time to another value.
test_clock.SetNow(kSomeLaterTime);
// Notify the PDM that the profile and credit card were used.
AutofillProfile* added_profile =
personal_data_->GetProfileByGUID(profile.guid());
ASSERT_TRUE(added_profile);
EXPECT_EQ(*added_profile, profile);
Check(*added_profile, 1u, kArbitraryTime, kArbitraryTime);
CreditCard* added_card =
personal_data_->GetCreditCardByGUID(credit_card.guid());
ASSERT_TRUE(added_card);
EXPECT_EQ(*added_card, credit_card);
Check(*added_card, 1u, kArbitraryTime, kArbitraryTime);
// Use |profile|, then verify usage stats.
base::RunLoop profile_run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&profile_run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
personal_data_->RecordUseOf(&profile);
profile_run_loop.Run();
added_profile = personal_data_->GetProfileByGUID(profile.guid());
added_card = personal_data_->GetCreditCardByGUID(credit_card.guid());
ASSERT_TRUE(added_profile);
ASSERT_TRUE(added_card);
Check(*added_profile, 2u, kSomeLaterTime, kArbitraryTime);
Check(*added_card, 1u, kArbitraryTime, kArbitraryTime);
// Use |credit_card|, then verify usage stats.
base::RunLoop credit_card_run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillOnce(QuitMessageLoop(&credit_card_run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
personal_data_->RecordUseOf(&credit_card);
credit_card_run_loop.Run();
added_profile = personal_data_->GetProfileByGUID(profile.guid());
added_card = personal_data_->GetCreditCardByGUID(credit_card.guid());
ASSERT_TRUE(added_profile);
ASSERT_TRUE(added_card);
Check(*added_profile, 2u, kSomeLaterTime, kArbitraryTime);
Check(*added_card, 2u, kSomeLaterTime, kArbitraryTime);
}
TEST_F(PersonalDataManagerTest, ClearAllServerData) {
// Add a server card.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"3456" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
SetServerCards(server_cards);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
// The card and profile should be there.
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_FALSE(personal_data_->GetCreditCards().empty());
personal_data_->ClearAllServerData();
// Reload the database, everything should be gone.
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_TRUE(personal_data_->GetCreditCards().empty());
}
TEST_F(PersonalDataManagerTest, ClearAllLocalData) {
// Add some local data.
AddProfileToPersonalDataManager(test::GetFullProfile());
personal_data_->AddCreditCard(test::GetCreditCard());
personal_data_->Refresh();
// The card and profile should be there.
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_FALSE(personal_data_->GetCreditCards().empty());
EXPECT_FALSE(personal_data_->GetProfiles().empty());
personal_data_->ClearAllLocalData();
// Reload the database, everything should be gone.
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_TRUE(personal_data_->GetCreditCards().empty());
EXPECT_TRUE(personal_data_->GetProfiles().empty());
}
// Tests the SaveImportedProfile method with different profiles to make sure the
// merge logic works correctly.
typedef struct {
autofill::ServerFieldType field_type;
std::u16string field_value;
} ProfileField;
typedef std::vector<ProfileField> ProfileFields;
typedef struct {
// Each test starts with a default pre-existing profile and applies these
// changes to it.
ProfileFields changes_to_original;
// Each test saves a second profile. Applies these changes to the default
// values before saving.
ProfileFields changes_to_new;
// For tests with profile merging, makes sure that these fields' values are
// the ones we expect (depending on the test).
ProfileFields changed_field_values;
} SaveImportedProfileTestCase;
class SaveImportedProfileTest
: public PersonalDataManagerHelper,
public testing::TestWithParam<SaveImportedProfileTestCase> {
public:
SaveImportedProfileTest() = default;
~SaveImportedProfileTest() override = default;
void SetUp() override {
SetUpTest();
ResetPersonalDataManager(USER_MODE_NORMAL);
}
void TearDown() override { TearDownTest(); }
};
TEST_P(SaveImportedProfileTest, SaveImportedProfile) {
// Create the test clock.
TestAutofillClock test_clock;
auto test_case = GetParam();
// Set the time to a specific value.
test_clock.SetNow(kArbitraryTime);
AutofillProfile original_profile = GetDefaultProfile();
// Apply changes to the original profile (if applicable).
for (ProfileField change : test_case.changes_to_original) {
original_profile.SetRawInfoWithVerificationStatus(
change.field_type, change.field_value, VerificationStatus::kObserved);
}
// Initialize PersonalDataManager with the original profile.
original_profile.FinalizeAfterImport();
SetUpReferenceProfile(original_profile);
// Set the time to a bigger value.
test_clock.SetNow(kSomeLaterTime);
AutofillProfile profile2(GetDefaultProfile());
// Apply changes to the second profile (if applicable).
for (ProfileField change : test_case.changes_to_new) {
profile2.SetRawInfoWithVerificationStatus(
change.field_type, change.field_value, VerificationStatus::kObserved);
}
profile2.FinalizeAfterImport();
SaveImportedProfileToPersonalDataManager(profile2);
const std::vector<AutofillProfile*>& saved_profiles =
personal_data_->GetProfiles();
// Get the set of profiles persisted in the db.
std::vector<std::unique_ptr<AutofillProfile>> db_profiles;
profile_autofill_table_->GetAutofillProfiles(
AutofillProfile::Source::kLocalOrSyncable, &db_profiles);
// Expect the profiles held in-memory by PersonalDataManager and the db
// profiles to be the same.
EXPECT_EQ(db_profiles.size(), saved_profiles.size());
for (const auto& it : db_profiles) {
AutofillProfile* inmemory_profile =
personal_data_->GetProfileByGUID(it->guid());
ASSERT_TRUE(inmemory_profile != nullptr);
EXPECT_TRUE(it->EqualsIncludingUsageStatsForTesting(*inmemory_profile));
}
// If there are no merge changes to verify, make sure that two profiles were
// saved.
if (test_case.changed_field_values.empty()) {
EXPECT_EQ(2U, saved_profiles.size());
} else {
EXPECT_EQ(1U, saved_profiles.size());
// Make sure the new information was merged correctly.
for (ProfileField changed_field : test_case.changed_field_values) {
EXPECT_EQ(changed_field.field_value,
saved_profiles.front()->GetRawInfo(changed_field.field_type));
}
// Verify that the merged profile's use count, use date and modification
// date were properly updated.
EXPECT_EQ(1U, saved_profiles.front()->use_count());
EXPECT_EQ(kSomeLaterTime, saved_profiles.front()->use_date());
// The modification date is only updated when the profile actually changes.
EXPECT_EQ(*saved_profiles.front() == original_profile ? kArbitraryTime
: kSomeLaterTime,
saved_profiles.front()->modification_date());
}
// Erase the profiles for the next test.
ResetProfiles();
}
INSTANTIATE_TEST_SUITE_P(
PersonalDataManagerTest,
SaveImportedProfileTest,
testing::Values(
// Test that saving an identical profile except for the name results
// in two profiles being saved.
SaveImportedProfileTestCase{ProfileFields(),
{{NAME_FIRST, u"Marionette"}}},
// Test that saving an identical profile except with the middle name
// initial instead of the full middle name results in the profiles
// getting merged and the full middle name being kept.
SaveImportedProfileTestCase{ProfileFields(),
{{NAME_MIDDLE, u"M"}},
{{NAME_MIDDLE, u"Mitchell"},
{NAME_FULL, u"Marion Mitchell Morrison"}}},
// Test that saving an identical profile except with the full middle
// name instead of the middle name initial results in the profiles
// getting merged and the full middle name replacing the initial.
SaveImportedProfileTestCase{{{NAME_MIDDLE, u"M"}},
{{NAME_MIDDLE, u"Mitchell"}},
{{NAME_MIDDLE, u"Mitchell"}}},
// Test that saving an identical profile except with no middle name
// results in the profiles getting merged and the full middle name
// being kept.
SaveImportedProfileTestCase{ProfileFields(),
{{NAME_MIDDLE, u""}},
{{NAME_MIDDLE, u"Mitchell"}}},
// Test that saving an identical profile except with a middle name
// initial results in the profiles getting merged and the middle
// name initial being saved.
SaveImportedProfileTestCase{{{NAME_MIDDLE, u""}},
{{NAME_MIDDLE, u"M"}},
{{NAME_MIDDLE, u"M"}}},
// Test that saving an identical profile except with a middle name
// results in the profiles getting merged and the full middle name
// being saved.
SaveImportedProfileTestCase{{{NAME_MIDDLE, u""}},
{{NAME_MIDDLE, u"Mitchell"}},
{{NAME_MIDDLE, u"Mitchell"}}},
// Test that saving an identical profile except with the full name
// set instead of the name parts results in the two profiles being
// merged and all the name parts kept and the full name being added.
SaveImportedProfileTestCase{
{
{NAME_FIRST, u"Marion"},
{NAME_MIDDLE, u"Mitchell"},
{NAME_LAST, u"Morrison"},
{NAME_FULL, u""},
},
{
{NAME_FIRST, u""},
{NAME_MIDDLE, u""},
{NAME_LAST, u""},
{NAME_FULL, u"Marion Mitchell Morrison"},
},
{
{NAME_FIRST, u"Marion"},
{NAME_MIDDLE, u"Mitchell"},
{NAME_LAST, u"Morrison"},
{NAME_FULL, u"Marion Mitchell Morrison"},
},
},
// Test that saving a identical profile except with the name parts
// set instead of the full name results in the two profiles being
// merged and the full name being kept and all the name parts being
// added.
SaveImportedProfileTestCase{
{
{NAME_FIRST, u""},
{NAME_MIDDLE, u""},
{NAME_LAST, u""},
{NAME_FULL, u"Marion Mitchell Morrison"},
},
{
{NAME_FIRST, u"Marion"},
{NAME_MIDDLE, u"Mitchell"},
{NAME_LAST, u"Morrison"},
{NAME_FULL, u""},
},
{
{NAME_FIRST, u"Marion"},
{NAME_MIDDLE, u"Mitchell"},
{NAME_LAST, u"Morrison"},
{NAME_FULL, u"Marion Mitchell Morrison"},
},
},
// Test that saving a profile that has only a full name set does not
// get merged with a profile with only the name parts set if the
// names are different.
SaveImportedProfileTestCase{
{
{NAME_FIRST, u"Marion"},
{NAME_MIDDLE, u"Mitchell"},
{NAME_LAST, u"Morrison"},
{NAME_FULL, u""},
},
{
{NAME_FIRST, u""},
{NAME_MIDDLE, u""},
{NAME_LAST, u""},
{NAME_FULL, u"John Thompson Smith"},
},
},
// Test that saving a profile that has only the name parts set does
// not get merged with a profile with only the full name set if the
// names are different.
SaveImportedProfileTestCase{
{
{NAME_FIRST, u""},
{NAME_MIDDLE, u""},
{NAME_LAST, u""},
{NAME_FULL, u"John Thompson Smith"},
},
{
{NAME_FIRST, u"Marion"},
{NAME_MIDDLE, u"Mitchell"},
{NAME_LAST, u"Morrison"},
{NAME_FULL, u""},
},
},
// Test that saving an identical profile except for the first
// address line results in two profiles being saved.
SaveImportedProfileTestCase{
ProfileFields(),
{{ADDRESS_HOME_LINE1, u"123 Aquarium St."}}},
// Test that saving an identical profile except for the second
// address line results in two profiles being saved.
SaveImportedProfileTestCase{ProfileFields(),
{{ADDRESS_HOME_LINE2, u"unit 7"}}},
// Tests that saving an identical profile that has a new piece of
// information (company name) results in a merge and that the
// original empty value gets overwritten by the new information.
SaveImportedProfileTestCase{{{COMPANY_NAME, u""}},
ProfileFields(),
{{COMPANY_NAME, u"Fox"}}},
// Tests that saving an identical profile except a loss of
// information results in a merge but the original value is not
// overwritten (no information loss).
SaveImportedProfileTestCase{ProfileFields(),
{{COMPANY_NAME, u""}},
{{COMPANY_NAME, u"Fox"}}},
// Tests that saving an identical profile except a slightly
// different postal code results in a merge with the new value kept.
SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, u"R2C 0A1"}},
{{ADDRESS_HOME_ZIP, u"R2C0A1"}},
{{ADDRESS_HOME_ZIP, u"R2C0A1"}}},
SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, u"R2C0A1"}},
{{ADDRESS_HOME_ZIP, u"R2C 0A1"}},
{{ADDRESS_HOME_ZIP, u"R2C 0A1"}}},
SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, u"r2c 0a1"}},
{{ADDRESS_HOME_ZIP, u"R2C0A1"}},
{{ADDRESS_HOME_ZIP, u"R2C0A1"}}},
// Tests that saving an identical profile plus a new piece of
// information on the address line 2 results in a merge and that the
// original empty value gets overwritten by the new information.
SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE2, u""}},
ProfileFields(),
{{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except a loss of
// information on the address line 2 results in a merge but that the
// original value gets not overwritten (no information loss).
SaveImportedProfileTestCase{ProfileFields(),
{{ADDRESS_HOME_LINE2, u""}},
{{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical except with more punctuation in
// the fist address line, while the second is empty, results in a
// merge and that the original address gets overwritten.
SaveImportedProfileTestCase{
{{ADDRESS_HOME_LINE2, u""}},
{{ADDRESS_HOME_LINE2, u""}, {ADDRESS_HOME_LINE1, u"123, Zoo St."}},
{{ADDRESS_HOME_LINE1, u"123, Zoo St."}}},
// Tests that saving an identical profile except with less
// punctuation in the fist address line, while the second is empty,
// results in a merge and that the longer address is retained.
SaveImportedProfileTestCase{
{{ADDRESS_HOME_LINE2, u""}, {ADDRESS_HOME_LINE1, u"123, Zoo St."}},
{{ADDRESS_HOME_LINE2, u""}},
{{ADDRESS_HOME_LINE1, u"123 Zoo St"}}},
// Tests that saving an identical profile except additional
// punctuation in the two address lines results in a merge and that
// the newer address is retained.
SaveImportedProfileTestCase{ProfileFields(),
{{ADDRESS_HOME_LINE1, u"123, Zoo St."},
{ADDRESS_HOME_LINE2, u"unit. 5"}},
{{ADDRESS_HOME_LINE1, u"123, Zoo St."},
{ADDRESS_HOME_LINE2, u"unit. 5"}}},
// Tests that saving an identical profile except less punctuation in
// the two address lines results in a merge and that the newer
// address is retained.
SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE1, u"123, Zoo St."},
{ADDRESS_HOME_LINE2, u"unit. 5"}},
ProfileFields(),
{{ADDRESS_HOME_LINE1, u"123 Zoo St"},
{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile with accented characters
// in the two address lines results in a merge and that the newer
// address is retained.
SaveImportedProfileTestCase{ProfileFields(),
{{ADDRESS_HOME_LINE1, u"123 Zôö St"},
{ADDRESS_HOME_LINE2, u"üñìt 5"}},
{{ADDRESS_HOME_LINE1, u"123 Zôö St"},
{ADDRESS_HOME_LINE2, u"üñìt 5"}}},
// Tests that saving an identical profile without accented
// characters in the two address lines results in a merge and that
// the newer address is retained.
SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE1, u"123 Zôö St"},
{ADDRESS_HOME_LINE2, u"üñìt 5"}},
ProfileFields(),
{{ADDRESS_HOME_LINE1, u"123 Zoo St"},
{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except that the address
// line 1 is in the address line 2 results in a merge and that the
// multi-lne address is retained.
SaveImportedProfileTestCase{
ProfileFields(),
{{ADDRESS_HOME_LINE1, u"123 Zoo St, unit 5"},
{ADDRESS_HOME_LINE2, u""}},
{{ADDRESS_HOME_LINE1, u"123 Zoo St"},
{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except that the address
// line 2 contains part of the old address line 1 results in a merge
// and that the original address lines of the reference profile get
// overwritten.
SaveImportedProfileTestCase{
{{ADDRESS_HOME_LINE1, u"123 Zoo St, unit 5"},
{ADDRESS_HOME_LINE2, u""}},
ProfileFields(),
{{ADDRESS_HOME_LINE1, u"123 Zoo St"},
{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except that the state is
// the abbreviation instead of the full form results in a merge and
// that the original state gets overwritten.
SaveImportedProfileTestCase{{{ADDRESS_HOME_STATE, u"California"}},
ProfileFields(),
{{ADDRESS_HOME_STATE, u"CA"}}},
// Tests that saving an identical profile except that the state is
// the full form instead of the abbreviation results in a merge and
// that the abbreviated state is retained.
SaveImportedProfileTestCase{ProfileFields(),
{{ADDRESS_HOME_STATE, u"California"}},
{{ADDRESS_HOME_STATE, u"CA"}}},
// Tests that saving and identical profile except that the company
// name has different punctuation and case results in a merge and
// that the syntax of the new profile replaces the old one.
SaveImportedProfileTestCase{{{COMPANY_NAME, u"Stark inc"}},
{{COMPANY_NAME, u"Stark Inc."}},
{{COMPANY_NAME, u"Stark Inc."}}}));
// Tests that MergeProfile tries to merge the imported profile into the
// existing profile in decreasing order of ranking score.
TEST_F(PersonalDataManagerTest, MergeProfile_Ranking) {
// Create two very similar profiles except with different company names.
std::unique_ptr<AutofillProfile> profile1 =
std::make_unique<AutofillProfile>();
test::SetProfileInfo(profile1.get(), "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
AutofillProfile* profile2 = new AutofillProfile();
test::SetProfileInfo(profile2, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
// Give the "Fox" profile a larger ranking score.
profile2->set_use_count(15);
// Create the |existing_profiles| vector.
std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
existing_profiles.push_back(std::move(profile1));
existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile2));
// Create a new imported profile with no company name.
AutofillProfile imported_profile;
test::SetProfileInfo(&imported_profile, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "US", "12345678910");
// Merge the imported profile into the existing profiles.
std::vector<AutofillProfile> profiles;
std::string guid = AutofillProfileComparator::MergeProfile(
imported_profile, existing_profiles, "US-EN", &profiles);
// The new profile should be merged into the "fox" profile.
EXPECT_EQ(profile2->guid(), guid);
}
// Tests that MergeProfile produces a merged profile with the expected usage
// statistics.
// Flaky on TSan, see crbug.com/686226.
#if defined(THREAD_SANITIZER)
#define MAYBE_MergeProfile_UsageStats DISABLED_MergeProfile_UsageStats
#else
#define MAYBE_MergeProfile_UsageStats MergeProfile_UsageStats
#endif
TEST_F(PersonalDataManagerTest, MAYBE_MergeProfile_UsageStats) {
// Create the test clock and set the time to a specific value.
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
// Create an initial profile with a use count of 10, an old use date and an
// old modification date of 4 days ago.
AutofillProfile* profile = new AutofillProfile();
test::SetProfileInfo(profile, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
profile->set_use_count(4U);
EXPECT_EQ(kArbitraryTime, profile->use_date());
EXPECT_EQ(kArbitraryTime, profile->modification_date());
// Create the |existing_profiles| vector.
std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile));
// Change the current date.
test_clock.SetNow(kSomeLaterTime);
// Create a new imported profile that will get merged with the existing one.
AutofillProfile imported_profile;
test::SetProfileInfo(&imported_profile, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "US", "12345678910");
// Change the current date.
test_clock.SetNow(kMuchLaterTime);
// Merge the imported profile into the existing profiles.
std::vector<AutofillProfile> profiles;
std::string guid = AutofillProfileComparator::MergeProfile(
imported_profile, existing_profiles, "US-EN", &profiles);
// The new profile should be merged into the existing profile.
EXPECT_EQ(profile->guid(), guid);
EXPECT_EQ(1U, profiles.size());
// The use count should have be max(4, 1) => 4.
EXPECT_EQ(4U, profiles[0].use_count());
// The use date should be the one of the most recent profile, which is
// kSecondArbitraryTime.
EXPECT_EQ(kSomeLaterTime, profiles[0].use_date());
// Since the merge is considered a modification, the modification_date should
// be set to kMuchLaterTime.
EXPECT_EQ(kMuchLaterTime, profiles[0].modification_date());
}
TEST_F(PersonalDataManagerTest, DeleteLocalCreditCards) {
CreditCard credit_card1(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card1, "Alice",
"378282246310005" /* American Express */, "04",
"2020", "1");
CreditCard credit_card2(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card2, "Ben",
"378282246310006" /* American Express */, "04",
"2021", "1");
CreditCard credit_card3(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&credit_card3, "Clyde",
"5105105105105100" /* Mastercard */, "04", "2022",
"1");
std::vector<CreditCard> cards;
cards.push_back(credit_card1);
cards.push_back(credit_card2);
personal_data_->AddCreditCard(credit_card1);
personal_data_->AddCreditCard(credit_card2);
personal_data_->AddCreditCard(credit_card3);
personal_data_->DeleteLocalCreditCards(cards);
// Wait for the data to be refreshed.
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
std::unordered_set<std::u16string> expectedToRemain = {u"Clyde"};
for (auto* card : personal_data_->GetCreditCards()) {
EXPECT_NE(expectedToRemain.end(),
expectedToRemain.find(card->GetRawInfo(CREDIT_CARD_NAME_FULL)));
}
}
// Tests that a new local profile is created if no existing one is a duplicate
// of the server address. Also tests that the billing address relationship was
// transferred to the converted address.
TEST_F(PersonalDataManagerTest,
ConvertWalletAddressesAndUpdateWalletCards_NewProfile) {
if (IsWalletAddressConversionDeprecated()) {
return;
}
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
ASSERT_TRUE(TurnOnSyncFeature());
base::HistogramTester histogram_tester;
const std::string kServerAddressId("server_address1");
// Add two different profiles, a local and a server one. Set the use stats so
// the server profile has a higher ranking, to have a predictable ordering to
// validate results.
AutofillProfile local_profile;
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
local_profile.set_use_count(1);
AddProfileToPersonalDataManager(local_profile);
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
server_profiles.push_back(
AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
"ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
"77401", "US", "");
EXPECT_EQ(server_profiles.back().GetRawInfo(NAME_FULL), u"John Doe");
server_profiles.back().set_use_count(100);
SetServerProfiles(server_profiles);
// Add a server and a local card that have the server address as billing
// address.
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
local_card.set_billing_address_id(kServerAddressId);
personal_data_->AddCreditCard(local_card);
std::vector<CreditCard> server_cards;
server_cards.push_back(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.back().set_billing_address_id(kServerAddressId);
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
ASSERT_EQ(1U, personal_data_->GetServerProfiles().size());
ASSERT_EQ(2U, personal_data_->GetCreditCards().size());
ConvertWalletAddressesAndUpdateWalletCards();
// The Wallet address should have been added as a new local profile.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
histogram_tester.ExpectUniqueSample("Autofill.WalletAddressConversionType",
AutofillMetrics::CONVERTED_ADDRESS_ADDED,
1);
// The conversion should be recorded in the Wallet address.
EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
// Get the profiles, sorted by ranking to have a deterministic order.
std::vector<AutofillProfile*> profiles =
personal_data_->GetProfilesToSuggest();
// Make sure that the two profiles have not merged.
ASSERT_EQ(2U, profiles.size());
EXPECT_EQ(u"John", profiles[0]->GetRawInfo(NAME_FIRST));
EXPECT_EQ(local_profile, *profiles[1]);
// Make sure that the billing address id of the two cards now point to the
// converted profile.
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[0]->billing_address_id());
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[1]->billing_address_id());
// Make sure that the added address has the email address of the currently
// signed-in user.
EXPECT_EQ(kPrimaryAccountEmail16, profiles[0]->GetRawInfo(EMAIL_ADDRESS));
}
// Tests that the converted wallet address is merged into an existing local
// profile if they are considered equivalent. Also tests that the billing
// address relationship was transferred to the converted address.
TEST_F(PersonalDataManagerTest,
ConvertWalletAddressesAndUpdateWalletCards_MergedProfile) {
if (IsWalletAddressConversionDeprecated()) {
return;
}
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
ASSERT_TRUE(TurnOnSyncFeature());
base::HistogramTester histogram_tester;
const std::string kServerAddressId("server_address1");
// Add two similar profile, a local and a server one. Set the use stats so
// the server card has a higher ranking, to have a predictable ordering to
// validate results.
// Add a local profile.
AutofillProfile local_profile;
test::SetProfileInfo(&local_profile, "John", "", "Doe", "john@doe.com", "",
"1212 Center.", "Bld. 5", "Orlando", "FL", "32801", "US",
"19482937549");
local_profile.set_use_count(1);
AddProfileToPersonalDataManager(local_profile);
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "Fox",
"1212 Center", "Bld. 5", "Orlando", "FL", "", "US", "");
// Wallet only provides a full name, so the above first and last names
// will be ignored when the profile is written to the DB.
server_profiles.back().SetRawInfo(NAME_FULL, u"John Doe");
server_profiles.back().set_use_count(100);
SetServerProfiles(server_profiles);
// Add a server and a local card that have the server address as billing
// address.
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
local_card.set_billing_address_id(kServerAddressId);
personal_data_->AddCreditCard(local_card);
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card1");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.back().set_billing_address_id(kServerAddressId);
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
ConvertWalletAddressesAndUpdateWalletCards();
// The Wallet address should have been merged with the existing local profile.
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
histogram_tester.ExpectUniqueSample("Autofill.WalletAddressConversionType",
AutofillMetrics::CONVERTED_ADDRESS_MERGED,
1);
// The conversion should be recorded in the Wallet address.
EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
// Get the profiles, sorted by frequency to have a deterministic order.
std::vector<AutofillProfile*> profiles =
personal_data_->GetProfilesToSuggest();
// Make sure that the two profiles have merged.
ASSERT_EQ(1U, profiles.size());
// Check that the values were merged.
EXPECT_EQ(u"john@doe.com", profiles[0]->GetRawInfo(EMAIL_ADDRESS));
EXPECT_EQ(u"Fox", profiles[0]->GetRawInfo(COMPANY_NAME));
EXPECT_EQ(u"32801", profiles[0]->GetRawInfo(ADDRESS_HOME_ZIP));
// Make sure that the billing address id of the two cards now point to the
// converted profile.
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[0]->billing_address_id());
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[1]->billing_address_id());
}
// Tests that a Wallet address that has already converted does not get converted
// a second time.
TEST_F(PersonalDataManagerTest,
ConvertWalletAddressesAndUpdateWalletCards_AlreadyConverted) {
if (IsWalletAddressConversionDeprecated()) {
return;
}
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
ASSERT_TRUE(TurnOnSyncFeature());
base::HistogramTester histogram_tester;
const std::string kServerAddressId("server_address1");
// Add a server profile that has already been converted.
std::vector<AutofillProfile> server_profiles;
server_profiles.push_back(
AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
test::SetProfileInfo(&server_profiles.back(), "John", "Ray", "Doe",
"john@doe.com", "Fox", "1212 Center", "Bld. 5",
"Orlando", "FL", "32801", "US", "");
server_profiles.back().set_has_converted(true);
// Wallet only provides a full name, so the above first and last names
// will be ignored when the profile is written to the DB.
SetServerProfiles(server_profiles);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(0U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
///////////////////////////////////////////////////////////////////////
// Tested method.
///////////////////////////////////////////////////////////////////////
ConvertWalletAddressesAndUpdateWalletCards();
// There should be no local profiles added.
EXPECT_EQ(0U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
}
// Tests that when the user has multiple similar Wallet addresses, they get
// merged into a single local profile, and that the billing address relationship
// is merged too.
TEST_F(
PersonalDataManagerTest,
ConvertWalletAddressesAndUpdateWalletCards_MultipleSimilarWalletAddresses) {
if (IsWalletAddressConversionDeprecated()) {
return;
}
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
ASSERT_TRUE(TurnOnSyncFeature());
base::HistogramTester histogram_tester;
const std::string kServerAddressId("server_address1");
const std::string kServerAddressId2("server_address2");
// Add a unique local profile and two similar server profiles. Set the use
// stats to have a predictable ordering to validate results.
// Add a local profile.
AutofillProfile local_profile;
test::SetProfileInfo(&local_profile, "Bob", "", "Doe", "", "Fox",
"1212 Center.", "Bld. 5", "Orlando", "FL", "32801", "US",
"19482937549");
local_profile.set_use_count(1);
AddProfileToPersonalDataManager(local_profile);
// Add a server profile.
std::vector<AutofillProfile> server_profiles;
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "",
"1212 Center", "Bld. 5", "Orlando", "FL", "32801", "US",
"");
EXPECT_EQ(server_profiles.back().GetRawInfo(NAME_FULL), u"John Doe");
server_profiles.back().set_use_count(100);
// Add a similar server profile.
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
kServerAddressId2);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe",
"john@doe.com", "Fox", "1212 Center", "Bld. 5",
"Orlando", "FL", "", "US", "");
// Wallet only provides a full name, so the above first and last names
// will be ignored when the profile is written to the DB.
server_profiles.back().SetRawInfo(NAME_FULL, u"John Doe");
server_profiles.back().set_use_count(200);
SetServerProfiles(server_profiles);
// Add a server and a local card that have the first and second Wallet address
// as a billing address.
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card, "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
local_card.set_billing_address_id(kServerAddressId);
personal_data_->AddCreditCard(local_card);
WaitForOnPersonalDataChanged();
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card1");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.back().set_billing_address_id(kServerAddressId2);
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
ConvertWalletAddressesAndUpdateWalletCards();
// The first Wallet address should have been added as a new local profile and
// the second one should have merged with the first.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetServerProfiles().size());
histogram_tester.ExpectBucketCount("Autofill.WalletAddressConversionType",
AutofillMetrics::CONVERTED_ADDRESS_ADDED,
1);
histogram_tester.ExpectBucketCount("Autofill.WalletAddressConversionType",
AutofillMetrics::CONVERTED_ADDRESS_MERGED,
1);
// The conversion should be recorded in the Wallet addresses.
EXPECT_TRUE(personal_data_->GetServerProfiles()[0]->has_converted());
EXPECT_TRUE(personal_data_->GetServerProfiles()[1]->has_converted());
// Get the profiles, sorted by ranking to have a deterministic order.
std::vector<AutofillProfile*> profiles =
personal_data_->GetProfilesToSuggest();
// Make sure that the two Wallet addresses merged together and were added as
// a new local profile.
ASSERT_EQ(2U, profiles.size());
EXPECT_EQ(u"John", profiles[0]->GetRawInfo(NAME_FIRST));
EXPECT_EQ(local_profile, *profiles[1]);
// Check that the values were merged.
EXPECT_EQ(u"Fox", profiles[0]->GetRawInfo(COMPANY_NAME));
EXPECT_EQ(u"32801", profiles[0]->GetRawInfo(ADDRESS_HOME_ZIP));
// Make sure that the billing address id of the two cards now point to the
// converted profile.
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[0]->billing_address_id());
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[1]->billing_address_id());
}
// Tests a new server card's billing address is updated propely even if the
// address was already converted in the past.
TEST_F(
PersonalDataManagerTest,
ConvertWalletAddressesAndUpdateWalletCards_NewCrd_AddressAlreadyConverted) {
if (IsWalletAddressConversionDeprecated()) {
return;
}
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
// Go through the conversion process for a server address and card. Then add
// a new server card that refers to the already converted server address as
// its billing address.
ASSERT_TRUE(TurnOnSyncFeature());
base::HistogramTester histogram_tester;
const std::string kServerAddressId("server_address1");
// Add a server profile.
std::vector<AutofillProfile> server_profiles;
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "Fox",
"1212 Center", "Bld. 5", "Orlando", "FL", "", "US", "");
// Wallet only provides a full name, so the above first and last names
// will be ignored when the profile is written to the DB.
server_profiles.back().SetRawInfo(NAME_FULL, u"John Doe");
server_profiles.back().set_use_count(100);
SetServerProfiles(server_profiles);
// Add a server card that have the server address as billing address.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card1");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.back().set_billing_address_id(kServerAddressId);
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
ConvertWalletAddressesAndUpdateWalletCards();
// The Wallet address should have been converted to a new local profile.
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
// The conversion should be recorded in the Wallet address.
EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
// Make sure that the billing address id of the card now point to the
// converted profile.
std::vector<AutofillProfile*> profiles =
personal_data_->GetProfilesToSuggest();
ASSERT_EQ(1U, profiles.size());
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[0]->billing_address_id());
// Add a new server card that has the same billing address as the old one.
server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card2");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1112" /* Visa */, "01", "2888", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
server_cards.back().set_billing_address_id(kServerAddressId);
SetServerCards(server_cards);
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
ConvertWalletAddressesAndUpdateWalletCards();
// The conversion should still be recorded in the Wallet address.
EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
// Get the profiles, sorted by ranking score to have a deterministic order.
profiles = personal_data_->GetProfilesToSuggest();
// Make sure that there is still only one profile.
ASSERT_EQ(1U, profiles.size());
// Make sure that the billing address id of the first server card still refers
// to the converted address.
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[0]->billing_address_id());
// Make sure that the billing address id of the new server card still refers
// to the converted address.
EXPECT_EQ(profiles[0]->guid(),
personal_data_->GetCreditCards()[1]->billing_address_id());
}
// Tests that Wallet addresses do NOT get converted if they're stored in
// ephemeral storage.
TEST_F(PersonalDataManagerSyncTransportModeTest,
DoNotConvertWalletAddressesInEphemeralStorage) {
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
ASSERT_FALSE(personal_data_->IsSyncFeatureEnabled());
// Add a local profile.
AutofillProfile local_profile;
test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz", "",
"Fox", "1212 Center.", "Bld. 5", "", "", "", "", "");
AddProfileToPersonalDataManager(local_profile);
// Add two server profiles: The first is unique, the second is similar to the
// local one but has some additional info.
std::vector<AutofillProfile> server_profiles;
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
"server_address1");
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "",
"1212 Center", "Bld. 5", "Orlando", "FL", "32801", "US",
"");
server_profiles.back().SetRawInfo(NAME_FULL, u"John Doe");
server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
"server_address2");
test::SetProfileInfo(&server_profiles.back(), "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
server_profiles.back().SetRawInfo(NAME_FULL, u"Josephine Alicia Saenz");
SetServerProfiles(server_profiles);
ASSERT_TRUE(AutofillProfileComparator(personal_data_->app_locale())
.AreMergeable(local_profile, server_profiles.back()));
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
ASSERT_EQ(2U, personal_data_->GetServerProfiles().size());
///////////////////////////////////////////////////////////////////////
// Tested method.
///////////////////////////////////////////////////////////////////////
// Since the wallet addresses are in ephemeral storage, they should *not* get
// converted to local addresses.
ConvertWalletAddressesAndUpdateWalletCards();
///////////////////////////////////////////////////////////////////////
// Validation.
///////////////////////////////////////////////////////////////////////
// There should be no changes to the local profiles: No new one added, and no
// changes to the existing one (even though the second server profile contains
// additional information and is mergeable in principle).
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(local_profile, *personal_data_->GetProfiles()[0]);
}
TEST_F(PersonalDataManagerTest, RemoveByGUID_ResetsBillingAddress) {
///////////////////////////////////////////////////////////////////////
// Setup.
///////////////////////////////////////////////////////////////////////
std::vector<CreditCard> server_cards;
// Add two different profiles
AutofillProfile profile0;
test::SetProfileInfo(&profile0, "Bob", "", "Doe", "", "Fox", "1212 Center.",
"Bld. 5", "Orlando", "FL", "32801", "US", "19482937549");
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Seb", "", "Doe", "", "ACME",
"1234 Evergreen Terrace", "Bld. 5", "Springfield", "IL",
"32801", "US", "15151231234");
// Add a local and a server card that have profile0 as their billing address.
CreditCard local_card0(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card0, "John Dillinger",
"4111111111111111" /* Visa */, "01", "2999",
profile0.guid());
CreditCard server_card0(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_card0, "John Barrow",
"378282246310005" /* American Express */, "04",
"2999", profile0.guid());
server_cards.push_back(server_card0);
// Do the same but for profile1.
CreditCard local_card1(base::Uuid::GenerateRandomV4().AsLowercaseString(),
test::kEmptyOrigin);
test::SetCreditCardInfo(&local_card1, "Seb Dillinger",
"4111111111111111" /* Visa */, "01", "2999",
profile1.guid());
CreditCard server_card1(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_card1, "John Barrow",
"378282246310005" /* American Express */, "04",
"2999", profile1.guid());
server_cards.push_back(server_card1);
// Add the data to the database.
AddProfileToPersonalDataManager(profile0);
AddProfileToPersonalDataManager(profile1);
personal_data_->AddCreditCard(local_card0);
personal_data_->AddCreditCard(local_card1);
SetServerCards(server_cards);
// Verify that the web database has been updated and the notification sent.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
// Make sure everything was saved properly.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
EXPECT_EQ(4U, personal_data_->GetCreditCards().size());
///////////////////////////////////////////////////////////////////////
// Tested method.
///////////////////////////////////////////////////////////////////////
RemoveByGUIDFromPersonalDataManager(profile0.guid());
///////////////////////////////////////////////////////////////////////
// Validation.
///////////////////////////////////////////////////////////////////////
// Wait for the data to be refreshed.
// WaitForOnPersonalDataChanged();
// Make sure only profile0 was deleted.
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(profile1.guid(), personal_data_->GetProfiles()[0]->guid());
EXPECT_EQ(4U, personal_data_->GetCreditCards().size());
for (CreditCard* card : personal_data_->GetCreditCards()) {
if (card->guid() == local_card0.guid() ||
card->guid() == server_card0.guid()) {
// The billing address id of local_card0 and server_card0 should have been
// reset.
EXPECT_EQ("", card->billing_address_id());
} else {
// The billing address of local_card1 and server_card1 should still refer
// to profile1.
EXPECT_EQ(profile1.guid(), card->billing_address_id());
}
}
}
TEST_F(PersonalDataManagerTest, LogStoredCreditCardMetrics) {
ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
// Helper timestamps for setting up the test data.
base::Time now = AutofillClock::Now();
base::Time one_month_ago = now - base::Days(30);
base::Time::Exploded now_exploded;
base::Time::Exploded one_month_ago_exploded;
now.LocalExplode(&now_exploded);
one_month_ago.LocalExplode(&one_month_ago_exploded);
std::vector<CreditCard> server_cards;
server_cards.reserve(10);
// Create in-use and in-disuse cards of each record type.
const std::vector<CreditCard::RecordType> record_types{
CreditCard::LOCAL_CARD, CreditCard::MASKED_SERVER_CARD,
CreditCard::FULL_SERVER_CARD};
for (auto record_type : record_types) {
// Create a card that's still in active use.
CreditCard card_in_use = test::GetRandomCreditCard(record_type);
card_in_use.set_use_date(now - base::Days(30));
card_in_use.set_use_count(10);
// Create a card that's not in active use.
CreditCard card_in_disuse = test::GetRandomCreditCard(record_type);
card_in_disuse.SetExpirationYear(one_month_ago_exploded.year);
card_in_disuse.SetExpirationMonth(one_month_ago_exploded.month);
card_in_disuse.set_use_date(now - base::Days(200));
card_in_disuse.set_use_count(10);
// Add the cards to the personal data manager in the appropriate way.
if (record_type == CreditCard::LOCAL_CARD) {
personal_data_->AddCreditCard(card_in_use);
personal_data_->AddCreditCard(card_in_disuse);
} else {
server_cards.push_back(std::move(card_in_use));
server_cards.push_back(std::move(card_in_disuse));
}
}
// Sets the virtual card enrollment state for the first three server cards.
server_cards[0].set_virtual_card_enrollment_state(
CreditCard::VirtualCardEnrollmentState::ENROLLED);
server_cards[0].set_card_art_url(GURL("https://www.example.com/image1"));
server_cards[1].set_virtual_card_enrollment_state(
CreditCard::VirtualCardEnrollmentState::ENROLLED);
server_cards[1].set_card_art_url(GURL("https://www.example.com/image1"));
server_cards[2].set_virtual_card_enrollment_state(
CreditCard::VirtualCardEnrollmentState::ENROLLED);
server_cards[2].set_card_art_url(GURL("https://www.example.com/image2"));
SetServerCards(server_cards);
// SetServerCards modifies the metadata (use_count and use_date)
// of unmasked cards. Reset the server card metadata to match the data set
// up above.
for (const auto& card : server_cards)
account_autofill_table_->UpdateServerCardMetadata(card);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
ASSERT_EQ(6U, personal_data_->GetCreditCards().size());
// Reload the database, which will log the stored profile counts.
base::HistogramTester histogram_tester;
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ(personal_data_->GetServerCardWithArtImageCount(), 3U);
ASSERT_EQ(6U, personal_data_->GetCreditCards().size());
// Validate the basic count metrics for both local and server cards. Deep
// validation of the metrics is done in:
// AutofillMetricsTest::LogStoredCreditCardMetrics
histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount", 1);
histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Local", 1);
histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Server", 1);
histogram_tester.ExpectTotalCount(
"Autofill.StoredCreditCardCount.Server.Masked", 1);
histogram_tester.ExpectTotalCount(
"Autofill.StoredCreditCardCount.Server.Unmasked", 1);
histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount", 6, 1);
histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Local", 2,
1);
histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Server", 4,
1);
histogram_tester.ExpectBucketCount(
"Autofill.StoredCreditCardCount.Server.Masked", 2, 1);
histogram_tester.ExpectBucketCount(
"Autofill.StoredCreditCardCount.Server.Unmasked", 2, 1);
histogram_tester.ExpectTotalCount(
"Autofill.StoredCreditCardCount.Server.WithVirtualCardMetadata", 1);
histogram_tester.ExpectBucketCount(
"Autofill.StoredCreditCardCount.Server.WithCardArtImage", 3, 1);
}
// These tests are not applicable on Linux since it does not support full server
// cards.
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
// Test that setting a null sync service remasks full server cards.
TEST_F(PersonalDataManagerTest, OnSyncServiceInitialized_NoSyncService) {
base::HistogramTester histogram_tester;
SetUpThreeCardTypes();
// Set no sync service.
personal_data_->SetSyncServiceForTest(nullptr);
WaitForOnPersonalDataChanged();
// Check that cards were masked and other were untouched.
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
std::vector<CreditCard*> server_cards =
personal_data_->GetServerCreditCards();
EXPECT_EQ(2U, server_cards.size());
for (CreditCard* card : server_cards)
EXPECT_TRUE(card->record_type() == CreditCard::MASKED_SERVER_CARD);
}
// Test that setting a sync service in auth error remasks full server cards.
TEST_F(PersonalDataManagerTest, OnSyncServiceInitialized_NotActiveSyncService) {
base::HistogramTester histogram_tester;
SetUpThreeCardTypes();
// Set a sync service in auth error.
syncer::TestSyncService sync_service;
sync_service.SetPersistentAuthError();
personal_data_->SetSyncServiceForTest(&sync_service);
WaitForOnPersonalDataChanged();
// Remove the auth error to be able to get the server cards.
sync_service.ClearAuthError();
// Check that cards were masked and other were untouched.
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
std::vector<CreditCard*> server_cards =
personal_data_->GetServerCreditCards();
EXPECT_EQ(2U, server_cards.size());
for (CreditCard* card : server_cards)
EXPECT_TRUE(card->record_type() == CreditCard::MASKED_SERVER_CARD);
// Call OnSyncShutdown to ensure removing observer added by
// SetSyncServiceForTest.
personal_data_->OnSyncShutdown(&sync_service);
}
#endif // !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
// Sync Transport mode is only for Win, Mac, and Linux.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_CHROMEOS)
TEST_F(PersonalDataManagerSyncTransportModeTest,
ServerCardsShowInTransportMode) {
SetUpThreeCardTypes();
CoreAccountInfo active_info =
identity_test_env_.identity_manager()->GetPrimaryAccountInfo(
signin::ConsentLevel::kSignin);
// Opt-in to seeing server card in sync transport mode.
::autofill::prefs::SetUserOptedInWalletSyncTransport(
prefs_.get(), active_info.account_id, true);
// Check that the server cards are available for suggestion.
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(3U, personal_data_->GetCreditCardsToSuggest().size());
EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
// Stop Wallet sync.
sync_service_.GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false,
/*types=*/syncer::UserSelectableTypeSet());
// Check that server cards are unavailable.
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(1U, personal_data_->GetCreditCardsToSuggest().size());
EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
}
// Make sure that the opt in is necessary to show server cards if the
// appropriate feature is disabled.
TEST_F(PersonalDataManagerSyncTransportModeTest,
ServerCardsShowInTransportMode_NeedOptIn) {
SetUpThreeCardTypes();
CoreAccountInfo active_info =
identity_test_env_.identity_manager()->GetPrimaryAccountInfo(
signin::ConsentLevel::kSignin);
// The server cards should not be available at first. The user needs to
// accept the opt-in offer.
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(1U, personal_data_->GetCreditCardsToSuggest().size());
EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
// Opt-in to seeing server card in sync transport mode.
::autofill::prefs::SetUserOptedInWalletSyncTransport(
prefs_.get(), active_info.account_id, true);
// Check that the server cards are available for suggestion.
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(3U, personal_data_->GetCreditCardsToSuggest().size());
EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
}
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) ||
// BUILDFLAG(IS_CHROMEOS)
// Tests that all the non settings origins of autofill credit cards are cleared
// even if sync is disabled.
TEST_F(
PersonalDataManagerTest,
SyncServiceInitializedWithAutofillDisabled_ClearCreditCardNonSettingsOrigins) {
// Create a card with a non-settings, non-empty origin.
CreditCard credit_card(base::Uuid::GenerateRandomV4().AsLowercaseString(),
"https://www.example.com");
test::SetCreditCardInfo(&credit_card, "Bob0",
"5105105105105100" /* Mastercard */, "04", "1999",
"1");
personal_data_->AddCreditCard(credit_card);
WaitForOnPersonalDataChanged();
// Turn off autofill profile sync.
syncer::UserSelectableTypeSet user_selectable_type_set =
sync_service_.GetUserSettings()->GetSelectedTypes();
user_selectable_type_set.Remove(syncer::UserSelectableType::kAutofill);
sync_service_.GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false,
/*types=*/user_selectable_type_set);
// The credit card should still exist.
ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
// Reload the personal data manager.
ResetPersonalDataManager(USER_MODE_NORMAL);
// The credit card should still exist.
ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
// The card's origin should be cleared
EXPECT_TRUE(personal_data_->GetCreditCards()[0]->origin().empty());
}
// Sanity check that the mode where we use the regular, persistent storage for
// cards still works.
TEST_F(PersonalDataManagerTest, UsePersistentServerStorage) {
ASSERT_TRUE(identity_test_env_.identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSync));
ASSERT_TRUE(sync_service_.HasSyncConsent());
SetUpThreeCardTypes();
EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(3U, personal_data_->GetCreditCardsToSuggest().size());
EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
}
// Verify that PDM can switch at runtime between the different storages.
TEST_F(PersonalDataManagerSyncTransportModeTest, SwitchServerStorages) {
// Start with account storage.
SetUpThreeCardTypes();
// Check that we do have 2 server cards, as expected.
ASSERT_EQ(2U, personal_data_->GetServerCreditCards().size());
// Switch to persistent storage.
sync_service_.SetHasSyncConsent(true);
personal_data_->OnStateChanged(&sync_service_);
WaitForOnPersonalDataChanged();
EXPECT_EQ(0U, personal_data_->GetServerCreditCards().size());
CreditCard server_card;
test::SetCreditCardInfo(&server_card, "Server Card",
"4234567890123456", // Visa
"04", "2999", "1");
server_card.set_guid("00000000-0000-0000-0000-000000000007");
server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
server_card.set_server_id("server_id");
personal_data_->AddFullServerCreditCard(server_card);
WaitForOnPersonalDataChanged();
EXPECT_EQ(1U, personal_data_->GetServerCreditCards().size());
// Switch back to the account storage.
sync_service_.SetHasSyncConsent(false);
personal_data_->OnStateChanged(&sync_service_);
WaitForOnPersonalDataChanged();
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
}
// Sanity check that the mode where we use the regular, persistent storage for
// cards still works.
TEST_F(PersonalDataManagerSyncTransportModeTest,
UseCorrectStorageForDifferentCards) {
// Add a server card.
CreditCard server_card;
test::SetCreditCardInfo(&server_card, "Server Card",
"4234567890123456", // Visa
"04", "2999", "1");
server_card.set_guid("00000000-0000-0000-0000-000000000007");
server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
server_card.set_server_id("server_id");
personal_data_->AddFullServerCreditCard(server_card);
// Set server card metadata.
server_card.set_use_count(15);
personal_data_->UpdateServerCardsMetadata({server_card});
WaitForOnPersonalDataChanged();
// Expect that the server card is stored in the account autofill table.
std::vector<std::unique_ptr<CreditCard>> cards;
account_autofill_table_->GetServerCreditCards(&cards);
EXPECT_EQ(1U, cards.size());
EXPECT_EQ(server_card.LastFourDigits(), cards[0]->LastFourDigits());
// Add a local card.
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "Freddy Mercury",
"4234567890123463", // Visa
"08", "2999", "1");
local_card.set_guid("00000000-0000-0000-0000-000000000009");
local_card.set_record_type(CreditCard::LOCAL_CARD);
local_card.set_use_date(AutofillClock::Now() - base::Days(5));
personal_data_->AddCreditCard(local_card);
WaitForOnPersonalDataChanged();
// Expect that the local card is stored in the profile autofill table.
profile_autofill_table_->GetCreditCards(&cards);
EXPECT_EQ(1U, cards.size());
EXPECT_EQ(local_card.LastFourDigits(), cards[0]->LastFourDigits());
// Add a local profile
AutofillProfile profile;
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
AddProfileToPersonalDataManager(profile);
std::vector<std::unique_ptr<AutofillProfile>> profiles;
// Expect that a profile is stored in the profile autofill table.
profile_autofill_table_->GetAutofillProfiles(
AutofillProfile::Source::kLocalOrSyncable, &profiles);
EXPECT_EQ(1U, profiles.size());
EXPECT_EQ(profile, *profiles[0]);
}
// Tests that the least recently used profile of two existing profiles is
// deleted, when an update of one of the profiles makes it a duplicate of the
// other, already existing profile. Here, the less recently used profile is
// edited to become a duplicate of the more recently used profile.
TEST_F(PersonalDataManagerTest, CreateDuplicateWithAnUpdate) {
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
AutofillProfile more_recently_used_profile(test::GetFullProfile());
AutofillProfile less_recently_used_profile(test::GetFullProfile2());
base::Time older_use_date = AutofillClock::Now();
less_recently_used_profile.set_use_date(older_use_date);
test_clock.Advance(base::Days(1));
// Set more recently used profile to have a use date that is newer than
// `older_use_date`.
base::Time newer_use_data = AutofillClock::Now();
more_recently_used_profile.set_use_date(newer_use_data);
AddProfileToPersonalDataManager(more_recently_used_profile);
AddProfileToPersonalDataManager(less_recently_used_profile);
EXPECT_EQ(personal_data_->GetProfiles().size(), 2U);
// Now make an update to less recently used profile that makes it a duplicate
// of the more recently used profile.
AutofillProfile updated_less_recently_used_profile =
more_recently_used_profile;
updated_less_recently_used_profile.set_guid(
less_recently_used_profile.guid());
// Set the updated profile to have a older use date than it's duplicate.
updated_less_recently_used_profile.set_use_date(older_use_date);
UpdateProfileOnPersonalDataManager(updated_less_recently_used_profile);
// Verify that the less recently used profile was removed.
ASSERT_EQ(personal_data_->GetProfiles().size(), 1U);
EXPECT_EQ(*personal_data_->GetProfiles()[0], more_recently_used_profile);
EXPECT_EQ(personal_data_->GetProfiles()[0]->use_date(), newer_use_data);
}
// Tests that the least recently used profile of two existing profiles is
// deleted, when an update of one of the profiles makes it a duplicate of the
// other, already existing profile. Here, the more recently used profile is
// edited to become a duplicate of the less recently used profile.
TEST_F(PersonalDataManagerTest,
CreateDuplicateWithAnUpdate_UpdatedProfileWasMoreRecentlyUsed) {
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
AutofillProfile less_recently_used_profile(test::GetFullProfile());
AutofillProfile more_recently_used_profile(test::GetFullProfile2());
less_recently_used_profile.set_use_date(AutofillClock::Now());
more_recently_used_profile.set_use_date(AutofillClock::Now());
AddProfileToPersonalDataManager(less_recently_used_profile);
AddProfileToPersonalDataManager(more_recently_used_profile);
EXPECT_EQ(personal_data_->GetProfiles().size(), 2U);
// Now make an update to profile2 that makes it a duplicate of profile1,
// but set the last use time to be more recent than the one of profile1.
AutofillProfile updated_more_recently_used_profile =
less_recently_used_profile;
updated_more_recently_used_profile.set_guid(
more_recently_used_profile.guid());
// Set the updated profile to have a newer use date than it's duplicate.
test_clock.Advance(base::Days(1));
base::Time newer_use_data = AutofillClock::Now();
updated_more_recently_used_profile.set_use_date(newer_use_data);
UpdateProfileOnPersonalDataManager(updated_more_recently_used_profile);
// Verify that less recently used profile was removed.
ASSERT_EQ(personal_data_->GetProfiles().size(), 1U);
EXPECT_EQ(*personal_data_->GetProfiles()[0],
updated_more_recently_used_profile);
EXPECT_EQ(personal_data_->GetProfiles()[0]->use_date(), newer_use_data);
}
TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) {
// Make the IdentityManager return a non-empty AccountInfo when
// GetPrimaryAccountInfo() is called.
std::string sync_account_email =
identity_test_env_.identity_manager()
->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)
.email;
ASSERT_FALSE(sync_account_email.empty());
// Make the sync service returns consistent AccountInfo when GetAccountInfo()
// is called.
ASSERT_EQ(sync_service_.GetAccountInfo().email, sync_account_email);
// The Active Sync AccountInfo should be returned.
EXPECT_EQ(sync_account_email,
personal_data_->GetAccountInfoForPaymentsServer().email);
}
TEST_F(PersonalDataManagerTest, OnAccountsCookieDeletedByUserAction) {
// Set up some sync transport opt-ins in the prefs.
::autofill::prefs::SetUserOptedInWalletSyncTransport(
prefs_.get(), CoreAccountId::FromGaiaId("account1"), true);
EXPECT_FALSE(prefs_->GetDict(prefs::kAutofillSyncTransportOptIn).empty());
// Simulate that the cookies get cleared by the user.
personal_data_->OnAccountsCookieDeletedByUserAction();
// Make sure the pref is now empty.
EXPECT_TRUE(prefs_->GetDict(prefs::kAutofillSyncTransportOptIn).empty());
}
TEST_F(PersonalDataManagerTest, SaveProfileMigrationStrikes) {
EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid));
personal_data_->AddStrikeToBlockProfileMigration(kGuid);
EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid));
personal_data_->AddStrikeToBlockProfileMigration(kGuid);
EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid));
// After the third strike, the guid should be blocked.
personal_data_->AddStrikeToBlockProfileMigration(kGuid);
EXPECT_TRUE(personal_data_->IsProfileMigrationBlocked(kGuid));
// Until the strikes are removed again.
personal_data_->RemoveStrikesToBlockProfileMigration(kGuid);
EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid));
// `AddMaxStrikesToBlockProfileMigration()` should add sufficiently many
// strikes.
personal_data_->AddMaxStrikesToBlockProfileMigration(kGuid);
EXPECT_TRUE(personal_data_->IsProfileMigrationBlocked(kGuid));
}
TEST_F(PersonalDataManagerTest, SaveProfileUpdateStrikes) {
EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid));
personal_data_->AddStrikeToBlockProfileUpdate(kGuid);
EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid));
personal_data_->AddStrikeToBlockProfileUpdate(kGuid);
EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid));
// After the third strike, the guid should be blocked.
personal_data_->AddStrikeToBlockProfileUpdate(kGuid);
EXPECT_TRUE(personal_data_->IsProfileUpdateBlocked(kGuid));
// Until the strikes are removed again.
personal_data_->RemoveStrikesToBlockProfileUpdate(kGuid);
EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid));
}
TEST_F(PersonalDataManagerTest, SaveProfileSaveStrikes) {
GURL domain("https://www.block.me/index.html");
EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
// After the third strike, the domain should be blocked.
personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
// Until the strikes are removed again.
personal_data_->RemoveStrikesToBlockNewProfileImportForDomain(domain);
EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
}
TEST_F(PersonalDataManagerTest, ClearFullBrowsingHistory) {
GURL domain("https://www.block.me/index.html");
personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
history::DeletionInfo deletion_info = history::DeletionInfo::ForAllHistory();
personal_data_->OnURLsDeleted(/*history_service=*/nullptr, deletion_info);
EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
}
TEST_F(PersonalDataManagerTest, ClearUrlsFromBrowsingHistory) {
GURL first_url("https://www.block.me/index.html");
GURL second_url("https://www.block.too/index.html");
// Add strikes to block both domains.
personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
history::URLRows deleted_urls = {history::URLRow(first_url)};
history::DeletionInfo deletion_info =
history::DeletionInfo::ForUrls(deleted_urls, {});
personal_data_->OnURLsDeleted(/*history_service=*/nullptr, deletion_info);
// The strikes for `domain` should be deleted, but the strikes for
// `another_domain` should not.
EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
}
TEST_F(PersonalDataManagerTest, ClearUrlsFromBrowsingHistoryInTimeRange) {
GURL first_url("https://www.block.me/index.html");
GURL second_url("https://www.block.too/index.html");
TestAutofillClock test_clock;
// Add strikes to block both domains.
personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
test_clock.Advance(base::Hours(1));
base::Time end_of_deletion = AutofillClock::Now();
test_clock.Advance(base::Hours(1));
personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
history::URLRows deleted_urls = {history::URLRow(first_url),
history::URLRow(second_url)};
history::DeletionInfo deletion_info(
history::DeletionTimeRange(base::Time::Min(), end_of_deletion), false,
deleted_urls, {},
absl::make_optional<std::set<GURL>>({first_url, second_url}));
personal_data_->OnURLsDeleted(/*history_service=*/nullptr, deletion_info);
// The strikes for `first_url` should be deleted because the strikes have been
// added within the deletion time range.
EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
// The last strike for 'second_url' was collected after the deletion time
// range and therefore, the blocking should prevail.
EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PersonalDataManagerSyncTransportModeTest,
ShouldShowCardsFromAccountOption) {
// The method should return false if one of these is not respected:
// * The sync_service is not null
// * The sync feature is not enabled
// * The user has server cards
// * The user has not opted-in to seeing their account cards
// Start by setting everything up, then making each of these conditions false
// independently, one by one.
// Set everything up so that the proposition should be shown.
// Set a server credit card.
std::vector<CreditCard> server_cards;
server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
SetServerCards(server_cards);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
// Make sure the function returns true.
EXPECT_TRUE(personal_data_->ShouldShowCardsFromAccountOption());
// Set that the user already opted-in. Check that the function now returns
// false.
CoreAccountId account_id =
identity_test_env_.identity_manager()->GetPrimaryAccountId(
signin::ConsentLevel::kSignin);
::autofill::prefs::SetUserOptedInWalletSyncTransport(prefs_.get(), account_id,
true);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Re-opt the user out. Check that the function now returns true.
::autofill::prefs::SetUserOptedInWalletSyncTransport(prefs_.get(), account_id,
false);
EXPECT_TRUE(personal_data_->ShouldShowCardsFromAccountOption());
// Set that the user has no server cards. Check that the function now returns
// false.
SetServerCards({});
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Re-set some server cards. Check that the function now returns true.
SetServerCards(server_cards);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_TRUE(personal_data_->ShouldShowCardsFromAccountOption());
// Set that the user enabled the sync feature. Check that the function now
// returns false.
sync_service_.SetHasSyncConsent(true);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Re-disable the sync feature. Check that the function now returns true.
sync_service_.SetHasSyncConsent(false);
EXPECT_TRUE(personal_data_->ShouldShowCardsFromAccountOption());
// Set a null sync service. Check that the function now returns false.
personal_data_->SetSyncServiceForTest(nullptr);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
}
#else // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) &&
// !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PersonalDataManagerSyncTransportModeTest,
ShouldShowCardsFromAccountOption) {
// The method should return false if one of these is not respected:
// * The sync_service is not null
// * The sync feature is not enabled
// * The user has server cards
// * The user has not opted-in to seeing their account cards
// Start by setting everything up, then making each of these conditions false
// independently, one by one.
// Set everything up so that the proposition should be shown on Desktop.
// Set a server credit card.
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
SetServerCards(server_cards);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
// Make sure the function returns false.
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Set that the user already opted-in. Check that the function still returns
// false.
CoreAccountId account_id =
identity_test_env_.identity_manager()->GetPrimaryAccountId(
signin::ConsentLevel::kSignin);
::autofill::prefs::SetUserOptedInWalletSyncTransport(prefs_.get(), account_id,
true);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Re-opt the user out. Check that the function now returns true.
::autofill::prefs::SetUserOptedInWalletSyncTransport(prefs_.get(), account_id,
false);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Set that the user has no server cards. Check that the function still
// returns false.
SetServerCards({});
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Re-set some server cards. Check that the function still returns false.
SetServerCards(server_cards);
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Set that the user enabled the sync feature. Check that the function still
// returns false.
sync_service_.SetHasSyncConsent(true);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Re-disable the sync feature. Check that the function still returns false.
sync_service_.SetHasSyncConsent(false);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
// Set a null sync service. Check that the function still returns false.
personal_data_->SetSyncServiceForTest(nullptr);
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) &&
// !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PersonalDataManagerSyncTransportModeTest, GetSyncSigninState) {
// Make sure a non-sync-consented account is available for the first tests.
ASSERT_TRUE(identity_test_env_.identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSignin));
ASSERT_FALSE(sync_service_.HasSyncConsent());
sync_service_.GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false,
/*types=*/{syncer::UserSelectableType::kAutofill});
EXPECT_EQ(AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled,
personal_data_->GetSyncSigninState());
// Check that the sync state is |SignedIn| if the sync service does not have
// wallet data active.
sync_service_.GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false,
/*types=*/syncer::UserSelectableTypeSet());
EXPECT_EQ(AutofillSyncSigninState::kSignedIn,
personal_data_->GetSyncSigninState());
// ClearPrimaryAccount is not supported on CrOS.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Check that the sync state is |SignedOut| when the account info is empty.
{
identity_test_env_.ClearPrimaryAccount();
sync_service_.SetAccountInfo(CoreAccountInfo());
sync_service_.SetHasSyncConsent(false);
EXPECT_EQ(AutofillSyncSigninState::kSignedOut,
personal_data_->GetSyncSigninState());
}
#endif
// Simulate that the user has enabled the sync feature.
AccountInfo primary_account_info;
primary_account_info.email = kPrimaryAccountEmail;
sync_service_.SetAccountInfo(primary_account_info);
sync_service_.SetHasSyncConsent(true);
// MakePrimaryAccountAvailable is not supported on CrOS.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
identity_test_env_.MakePrimaryAccountAvailable(primary_account_info.email,
signin::ConsentLevel::kSync);
#endif
// Check that the sync state is |SignedInAndSyncFeature| if the sync feature
// is enabled.
EXPECT_EQ(AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled,
personal_data_->GetSyncSigninState());
}
// On mobile, no dedicated opt-in is required for WalletSyncTransport - the
// user is always considered opted-in and thus this test doesn't make sense.
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(PersonalDataManagerSyncTransportModeTest, OnUserAcceptedUpstreamOffer) {
///////////////////////////////////////////////////////////
// kSignedInAndWalletSyncTransportEnabled
///////////////////////////////////////////////////////////
// Make sure a primary account with no sync consent is available so
// AUTOFILL_WALLET_DATA can run in sync-transport mode.
ASSERT_TRUE(identity_test_env_.identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSignin));
ASSERT_FALSE(identity_test_env_.identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSync));
CoreAccountInfo active_info =
identity_test_env_.identity_manager()->GetPrimaryAccountInfo(
signin::ConsentLevel::kSignin);
sync_service_.SetAccountInfo(active_info);
sync_service_.SetHasSyncConsent(false);
sync_service_.GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false,
/*types=*/{syncer::UserSelectableType::kAutofill});
// Make sure there are no opt-ins recorded yet.
ASSERT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(),
active_info.account_id));
// Account wallet storage only makes sense together with support for
// unconsented primary accounts, i.e. on Win/Mac/Linux.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
EXPECT_EQ(AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled,
personal_data_->GetSyncSigninState());
// Make sure an opt-in gets recorded if the user accepted an Upstream offer.
personal_data_->OnUserAcceptedUpstreamOffer();
EXPECT_TRUE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(),
active_info.account_id));
// Clear the prefs.
prefs::ClearSyncTransportOptIns(prefs_.get());
ASSERT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(),
active_info.account_id));
///////////////////////////////////////////////////////////
// kSignedIn
///////////////////////////////////////////////////////////
// Disable the wallet data type. kSignedInAndWalletSyncTransportEnabled
// shouldn't be available.
sync_service_.GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false,
/*types=*/syncer::UserSelectableTypeSet());
EXPECT_EQ(AutofillSyncSigninState::kSignedIn,
personal_data_->GetSyncSigninState());
// Make sure an opt-in does not get recorded even if the user accepted an
// Upstream offer.
personal_data_->OnUserAcceptedUpstreamOffer();
EXPECT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(),
active_info.account_id));
// Clear the prefs.
prefs::ClearSyncTransportOptIns(prefs_.get());
ASSERT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(),
active_info.account_id));
///////////////////////////////////////////////////////////
// kSignedOut
///////////////////////////////////////////////////////////
identity_test_env_.ClearPrimaryAccount();
sync_service_.SetAccountInfo(CoreAccountInfo());
sync_service_.SetHasSyncConsent(false);
{
EXPECT_EQ(AutofillSyncSigninState::kSignedOut,
personal_data_->GetSyncSigninState());
// Make sure an opt-in does not get recorded even if the user accepted an
// Upstream offer.
personal_data_->OnUserAcceptedUpstreamOffer();
EXPECT_FALSE(prefs::IsUserOptedInWalletSyncTransport(
prefs_.get(), active_info.account_id));
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
///////////////////////////////////////////////////////////
// kSignedInAndSyncFeature
///////////////////////////////////////////////////////////
identity_test_env_.MakePrimaryAccountAvailable(active_info.email,
signin::ConsentLevel::kSync);
sync_service_.SetAccountInfo(active_info);
sync_service_.SetHasSyncConsent(true);
{
EXPECT_EQ(AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled,
personal_data_->GetSyncSigninState());
// Make sure an opt-in does not get recorded even if the user accepted an
// Upstream offer.
personal_data_->OnUserAcceptedUpstreamOffer();
EXPECT_FALSE(prefs::IsUserOptedInWalletSyncTransport(
prefs_.get(), active_info.account_id));
}
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
namespace {
class OneTimeObserver : public PersonalDataManagerObserver {
public:
explicit OneTimeObserver(PersonalDataManager* manager) : manager_(manager) {}
~OneTimeObserver() override {
if (manager_)
manager_->RemoveObserver(this);
}
void OnPersonalDataChanged() override {
ASSERT_TRUE(manager_) << "Callback called after RemoveObserver()";
manager_->RemoveObserver(this);
manager_ = nullptr;
}
void OnPersonalDataFinishedProfileTasks() override {
EXPECT_TRUE(manager_) << "Callback called after RemoveObserver()";
}
bool IsConnected() { return manager_; }
private:
raw_ptr<PersonalDataManager> manager_;
};
} // namespace
TEST_F(PersonalDataManagerTest, RemoveObserverInOnPersonalDataChanged) {
OneTimeObserver observer(personal_data_.get());
personal_data_->AddObserver(&observer);
// Do something to trigger a data change
personal_data_->AddProfile(test::GetFullProfile());
WaitForOnPersonalDataChanged();
EXPECT_FALSE(observer.IsConnected()) << "Observer not called";
}
TEST_F(PersonalDataManagerTest, AddAndGetUpiId) {
constexpr char upi_id[] = "vpa@indianbank";
personal_data_->AddUpiId(upi_id);
WaitOnceForOnPersonalDataChanged();
std::vector<std::string> all_upi_ids = personal_data_->GetUpiIds();
EXPECT_THAT(all_upi_ids, testing::ElementsAre(upi_id));
}
TEST_F(PersonalDataManagerTest, IsEligibleForAddressAccountStorage) {
base::test::ScopedFeatureList features;
features.InitWithFeaturesAndParameters(
/*enabled_features=*/
{{base::test::FeatureRefAndParams(
features::kAutofillAccountProfilesUnionView, {})},
{base::test::FeatureRefAndParams(
features::kAutofillAccountProfileStorage,
{{features::kAutofillAccountProfileStorageFromUnsupportedIPs.name,
"false"}})}},
/*disabled_features=*/{});
// No Sync, no account storage.
personal_data_->SetSyncServiceForTest(nullptr);
EXPECT_FALSE(personal_data_->IsEligibleForAddressAccountStorage());
// Fake the Sync service. All data types are running by default.
syncer::TestSyncService sync_service;
personal_data_->SetSyncServiceForTest(&sync_service);
EXPECT_TRUE(personal_data_->IsEligibleForAddressAccountStorage());
// Being located in an unsupported country makes the user ineligible.
personal_data_->set_variations_country_code_for_testing("CU");
EXPECT_FALSE(personal_data_->IsEligibleForAddressAccountStorage());
// Unregister the Sync observer.
personal_data_->OnSyncShutdown(&sync_service);
}
TEST_F(PersonalDataManagerTest, IsCountryEligibleForAccountStorage) {
EXPECT_TRUE(personal_data_->IsCountryEligibleForAccountStorage("AT"));
EXPECT_FALSE(personal_data_->IsCountryEligibleForAccountStorage("IR"));
}
} // namespace autofill